authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-02 21:52:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:29-07:00
log1e2aab2f97843572138076b21e2efb568e060a33
treed80cc061081c998926b4707035df03b6495cc854
parent3c98e2c826e1a8650090a889cf3a1560335b2968

std: combine BufferedWriter into Writer


147 files changed, 3557 insertions(+), 4007 deletions(-)

lib/compiler/aro/aro/Diagnostics.zig+3-3
...@@ -535,13 +535,13 @@ fn tagKind(d: *Diagnostics, tag: Tag, langopts: LangOpts) Kind {...@@ -535,13 +535,13 @@ fn tagKind(d: *Diagnostics, tag: Tag, langopts: LangOpts) Kind {
535}535}
536536
537const MsgWriter = struct {537const MsgWriter = struct {
538 w: std.io.BufferedWriter(4096, std.fs.File.Writer),538 w: *std.fs.File.Writer,
539 config: std.io.tty.Config,539 config: std.io.tty.Config,
540540
541 fn init(config: std.io.tty.Config) MsgWriter {541 fn init(config: std.io.tty.Config, buffer: []u8) MsgWriter {
542 std.debug.lockStdErr();542 std.debug.lockStdErr();
543 return .{543 return .{
544 .w = std.io.bufferedWriter(std.io.getStdErr().writer()),544 .w = std.fs.stderr().writer(buffer),
545 .config = config,545 .config = config,
546 };546 };
547 }547 }
lib/compiler/build_runner.zig+9-8
...@@ -12,6 +12,7 @@ const Watch = std.Build.Watch;...@@ -12,6 +12,7 @@ const Watch = std.Build.Watch;
12const Fuzz = std.Build.Fuzz;12const Fuzz = std.Build.Fuzz;
13const Allocator = std.mem.Allocator;13const Allocator = std.mem.Allocator;
14const fatal = std.process.fatal;14const fatal = std.process.fatal;
15const Writer = std.io.Writer;
15const runner = @This();16const runner = @This();
1617
17pub const root = @import("@build");18pub const root = @import("@build");
...@@ -773,7 +774,7 @@ const PrintNode = struct {...@@ -773,7 +774,7 @@ const PrintNode = struct {
773 last: bool = false,774 last: bool = false,
774};775};
775776
776fn printPrefix(node: *PrintNode, stderr: *std.io.BufferedWriter, ttyconf: std.io.tty.Config) !void {777fn printPrefix(node: *PrintNode, stderr: *Writer, ttyconf: std.io.tty.Config) !void {
777 const parent = node.parent orelse return;778 const parent = node.parent orelse return;
778 if (parent.parent == null) return;779 if (parent.parent == null) return;
779 try printPrefix(parent, stderr, ttyconf);780 try printPrefix(parent, stderr, ttyconf);
...@@ -787,7 +788,7 @@ fn printPrefix(node: *PrintNode, stderr: *std.io.BufferedWriter, ttyconf: std.io...@@ -787,7 +788,7 @@ fn printPrefix(node: *PrintNode, stderr: *std.io.BufferedWriter, ttyconf: std.io
787 }788 }
788}789}
789790
790fn printChildNodePrefix(stderr: *std.io.BufferedWriter, ttyconf: std.io.tty.Config) !void {791fn printChildNodePrefix(stderr: *Writer, ttyconf: std.io.tty.Config) !void {
791 try stderr.writeAll(switch (ttyconf) {792 try stderr.writeAll(switch (ttyconf) {
792 .no_color, .windows_api => "+- ",793 .no_color, .windows_api => "+- ",
793 .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─794 .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─
...@@ -796,7 +797,7 @@ fn printChildNodePrefix(stderr: *std.io.BufferedWriter, ttyconf: std.io.tty.Conf...@@ -796,7 +797,7 @@ fn printChildNodePrefix(stderr: *std.io.BufferedWriter, ttyconf: std.io.tty.Conf
796797
797fn printStepStatus(798fn printStepStatus(
798 s: *Step,799 s: *Step,
799 stderr: *std.io.BufferedWriter,800 stderr: *Writer,
800 ttyconf: std.io.tty.Config,801 ttyconf: std.io.tty.Config,
801 run: *const Run,802 run: *const Run,
802) !void {803) !void {
...@@ -876,7 +877,7 @@ fn printStepStatus(...@@ -876,7 +877,7 @@ fn printStepStatus(
876877
877fn printStepFailure(878fn printStepFailure(
878 s: *Step,879 s: *Step,
879 stderr: *std.io.BufferedWriter,880 stderr: *Writer,
880 ttyconf: std.io.tty.Config,881 ttyconf: std.io.tty.Config,
881) !void {882) !void {
882 if (s.result_error_bundle.errorMessageCount() > 0) {883 if (s.result_error_bundle.errorMessageCount() > 0) {
...@@ -930,7 +931,7 @@ fn printTreeStep(...@@ -930,7 +931,7 @@ fn printTreeStep(
930 b: *std.Build,931 b: *std.Build,
931 s: *Step,932 s: *Step,
932 run: *const Run,933 run: *const Run,
933 stderr: *std.io.BufferedWriter,934 stderr: *Writer,
934 ttyconf: std.io.tty.Config,935 ttyconf: std.io.tty.Config,
935 parent_node: *PrintNode,936 parent_node: *PrintNode,
936 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),937 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
...@@ -1188,7 +1189,7 @@ pub fn printErrorMessages(...@@ -1188,7 +1189,7 @@ pub fn printErrorMessages(
1188 gpa: Allocator,1189 gpa: Allocator,
1189 failing_step: *Step,1190 failing_step: *Step,
1190 options: std.zig.ErrorBundle.RenderOptions,1191 options: std.zig.ErrorBundle.RenderOptions,
1191 stderr: *std.io.BufferedWriter,1192 stderr: *Writer,
1192 prominent_compile_errors: bool,1193 prominent_compile_errors: bool,
1193) !void {1194) !void {
1194 // Provide context for where these error messages are coming from by1195 // Provide context for where these error messages are coming from by
...@@ -1241,7 +1242,7 @@ pub fn printErrorMessages(...@@ -1241,7 +1242,7 @@ pub fn printErrorMessages(
1241 }1242 }
1242}1243}
12431244
1244fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void {1245fn steps(builder: *std.Build, bw: *Writer) !void {
1245 const allocator = builder.allocator;1246 const allocator = builder.allocator;
1246 for (builder.top_level_steps.values()) |top_level_step| {1247 for (builder.top_level_steps.values()) |top_level_step| {
1247 const name = if (&top_level_step.step == builder.default_step)1248 const name = if (&top_level_step.step == builder.default_step)
...@@ -1254,7 +1255,7 @@ fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void {...@@ -1254,7 +1255,7 @@ fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void {
12541255
1255var stdio_buffer: [256]u8 = undefined;1256var stdio_buffer: [256]u8 = undefined;
12561257
1257fn usage(b: *std.Build, bw: *std.io.BufferedWriter) !void {1258fn usage(b: *std.Build, bw: *Writer) !void {
1258 try bw.print(1259 try bw.print(
1259 \\Usage: {s} build [steps] [options]1260 \\Usage: {s} build [steps] [options]
1260 \\1261 \\
lib/docs/wasm/main.zig+2-1
...@@ -5,6 +5,7 @@ const Ast = std.zig.Ast;...@@ -5,6 +5,7 @@ const Ast = std.zig.Ast;
5const Walk = @import("Walk");5const Walk = @import("Walk");
6const markdown = @import("markdown.zig");6const markdown = @import("markdown.zig");
7const Decl = Walk.Decl;7const Decl = Walk.Decl;
8const Writer = std.io.Writer;
89
9const fileSourceHtml = @import("html_render.zig").fileSourceHtml;10const fileSourceHtml = @import("html_render.zig").fileSourceHtml;
10const appendEscaped = @import("html_render.zig").appendEscaped;11const appendEscaped = @import("html_render.zig").appendEscaped;
...@@ -702,7 +703,7 @@ fn render_docs(...@@ -702,7 +703,7 @@ fn render_docs(
702 r: markdown.Render,703 r: markdown.Render,
703 doc: markdown.Document,704 doc: markdown.Document,
704 node: markdown.Document.Node.Index,705 node: markdown.Document.Node.Index,
705 writer: *std.io.BufferedWriter,706 writer: *Writer,
706 ) !void {707 ) !void {
707 const decl_index_ptr: *const Decl.Index = @alignCast(@ptrCast(r.context));708 const decl_index_ptr: *const Decl.Index = @alignCast(@ptrCast(r.context));
708 const data = doc.nodes.items(.data)[@intFromEnum(node)];709 const data = doc.nodes.items(.data)[@intFromEnum(node)];
lib/docs/wasm/markdown/Document.zig+2-1
...@@ -5,6 +5,7 @@ const builtin = @import("builtin");...@@ -5,6 +5,7 @@ const builtin = @import("builtin");
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
7const Render = @import("Render.zig");7const Render = @import("Render.zig");
8const Writer = std.io.Writer;
89
9nodes: Node.List.Slice,10nodes: Node.List.Slice,
10extra: []u32,11extra: []u32,
...@@ -160,7 +161,7 @@ pub fn deinit(doc: *Document, allocator: Allocator) void {...@@ -160,7 +161,7 @@ pub fn deinit(doc: *Document, allocator: Allocator) void {
160}161}
161162
162/// Renders a document directly to a writer using the default renderer.163/// Renders a document directly to a writer using the default renderer.
163pub fn render(doc: Document, writer: *std.io.BufferedWriter) @TypeOf(writer).Error!void {164pub fn render(doc: Document, writer: *Writer) Writer.Error!void {
164 const renderer: Render(@TypeOf(writer), void) = .{ .context = {} };165 const renderer: Render(@TypeOf(writer), void) = .{ .context = {} };
165 try renderer.render(doc, writer);166 try renderer.render(doc, writer);
166}167}
lib/docs/wasm/markdown/Render.zig+10-8
...@@ -5,6 +5,8 @@...@@ -5,6 +5,8 @@
5//! for node types for which they require no special rendering.5//! for node types for which they require no special rendering.
66
7const std = @import("std");7const std = @import("std");
8const Writer = std.io.Writer;
9
8const Document = @import("Document.zig");10const Document = @import("Document.zig");
9const Node = Document.Node;11const Node = Document.Node;
10const Render = @This();12const Render = @This();
...@@ -14,10 +16,10 @@ renderFn: *const fn (...@@ -14,10 +16,10 @@ renderFn: *const fn (
14 r: Render,16 r: Render,
15 doc: Document,17 doc: Document,
16 node: Node.Index,18 node: Node.Index,
17 writer: *std.io.BufferedWriter,19 writer: *Writer,
18) std.io.Writer.Error!void = renderDefault,20) Writer.Error!void = renderDefault,
1921
20pub fn render(r: Render, doc: Document, writer: *std.io.BufferedWriter) std.io.Writer.Error!void {22pub fn render(r: Render, doc: Document, writer: *Writer) Writer.Error!void {
21 try r.renderFn(r, doc, .root, writer);23 try r.renderFn(r, doc, .root, writer);
22}24}
2325
...@@ -25,8 +27,8 @@ pub fn renderDefault(...@@ -25,8 +27,8 @@ pub fn renderDefault(
25 r: Render,27 r: Render,
26 doc: Document,28 doc: Document,
27 node: Node.Index,29 node: Node.Index,
28 writer: *std.io.BufferedWriter,30 writer: *Writer,
29) std.io.Writer.Error!void {31) Writer.Error!void {
30 const data = doc.nodes.items(.data)[@intFromEnum(node)];32 const data = doc.nodes.items(.data)[@intFromEnum(node)];
31 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {33 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {
32 .root => {34 .root => {
...@@ -183,8 +185,8 @@ pub fn renderDefault(...@@ -183,8 +185,8 @@ pub fn renderDefault(
183pub fn renderInlineNodeText(185pub fn renderInlineNodeText(
184 doc: Document,186 doc: Document,
185 node: Node.Index,187 node: Node.Index,
186 writer: *std.io.BufferedWriter,188 writer: *Writer,
187) std.io.Writer.Error!void {189) Writer.Error!void {
188 const data = doc.nodes.items(.data)[@intFromEnum(node)];190 const data = doc.nodes.items(.data)[@intFromEnum(node)];
189 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {191 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {
190 .root,192 .root,
...@@ -229,7 +231,7 @@ pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter(formatHtml) {...@@ -229,7 +231,7 @@ pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter(formatHtml) {
229 return .{ .data = bytes };231 return .{ .data = bytes };
230}232}
231233
232fn formatHtml(bytes: []const u8, writer: *std.io.BufferedWriter, comptime fmt: []const u8) !void {234fn formatHtml(bytes: []const u8, writer: *Writer, comptime fmt: []const u8) !void {
233 _ = fmt;235 _ = fmt;
234 for (bytes) |b| {236 for (bytes) |b| {
235 switch (b) {237 switch (b) {
lib/std/Build/Cache.zig+2-3
...@@ -286,9 +286,8 @@ pub const HashHelper = struct {...@@ -286,9 +286,8 @@ pub const HashHelper = struct {
286286
287pub fn binToHex(bin_digest: BinDigest) HexDigest {287pub fn binToHex(bin_digest: BinDigest) HexDigest {
288 var out_digest: HexDigest = undefined;288 var out_digest: HexDigest = undefined;
289 var bw: std.io.BufferedWriter = undefined;289 var w: std.io.Writer = .fixed(&out_digest);
290 bw.initFixed(&out_digest);290 w.printHex(&bin_digest, .lower) catch unreachable;
291 bw.printHex(&bin_digest, .lower) catch unreachable;
292 return out_digest;291 return out_digest;
293}292}
294293
lib/std/Build/Cache/Directory.zig+3-7
...@@ -55,15 +55,11 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {...@@ -55,15 +55,11 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
55 self.* = undefined;55 self.* = undefined;
56}56}
5757
58pub fn format(58pub fn format(self: Directory, w: *std.io.Writer, comptime fmt_string: []const u8) !void {
59 self: Directory,
60 bw: *std.io.BufferedWriter,
61 comptime fmt_string: []const u8,
62) !void {
63 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);59 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);
64 if (self.path) |p| {60 if (self.path) |p| {
65 try bw.writeAll(p);61 try w.writeAll(p);
66 try bw.writeAll(fs.path.sep_str);62 try w.writeAll(fs.path.sep_str);
67 }63 }
68}64}
6965
lib/std/Build/Cache/Path.zig+10-14
...@@ -140,11 +140,7 @@ pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {...@@ -140,11 +140,7 @@ pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
140 return std.fmt.allocPrintZ(allocator, "{f}", .{p});140 return std.fmt.allocPrintZ(allocator, "{f}", .{p});
141}141}
142142
143pub fn format(143pub fn format(self: Path, w: *std.io.Writer, comptime fmt_string: []const u8) !void {
144 self: Path,
145 bw: *std.io.BufferedWriter,
146 comptime fmt_string: []const u8,
147) !void {
148 if (fmt_string.len == 1) {144 if (fmt_string.len == 1) {
149 // Quote-escape the string.145 // Quote-escape the string.
150 const stringEscape = std.zig.stringEscape;146 const stringEscape = std.zig.stringEscape;
...@@ -154,33 +150,33 @@ pub fn format(...@@ -154,33 +150,33 @@ pub fn format(
154 else => @compileError("unsupported format string: " ++ fmt_string),150 else => @compileError("unsupported format string: " ++ fmt_string),
155 };151 };
156 if (self.root_dir.path) |p| {152 if (self.root_dir.path) |p| {
157 try stringEscape(p, bw, f);153 try stringEscape(p, w, f);
158 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, bw, f);154 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, w, f);
159 }155 }
160 if (self.sub_path.len > 0) {156 if (self.sub_path.len > 0) {
161 try stringEscape(self.sub_path, bw, f);157 try stringEscape(self.sub_path, w, f);
162 }158 }
163 return;159 return;
164 }160 }
165 if (fmt_string.len > 0)161 if (fmt_string.len > 0)
166 std.fmt.invalidFmtError(fmt_string, self);162 std.fmt.invalidFmtError(fmt_string, self);
167 if (std.fs.path.isAbsolute(self.sub_path)) {163 if (std.fs.path.isAbsolute(self.sub_path)) {
168 try bw.writeAll(self.sub_path);164 try w.writeAll(self.sub_path);
169 return;165 return;
170 }166 }
171 if (self.root_dir.path) |p| {167 if (self.root_dir.path) |p| {
172 try bw.writeAll(p);168 try w.writeAll(p);
173 if (self.sub_path.len > 0) {169 if (self.sub_path.len > 0) {
174 try bw.writeAll(fs.path.sep_str);170 try w.writeAll(fs.path.sep_str);
175 try bw.writeAll(self.sub_path);171 try w.writeAll(self.sub_path);
176 }172 }
177 return;173 return;
178 }174 }
179 if (self.sub_path.len > 0) {175 if (self.sub_path.len > 0) {
180 try bw.writeAll(self.sub_path);176 try w.writeAll(self.sub_path);
181 return;177 return;
182 }178 }
183 try bw.writeByte('.');179 try w.writeByte('.');
184}180}
185181
186pub fn eql(self: Path, other: Path) bool {182pub fn eql(self: Path, other: Path) bool {
lib/std/Build/Step/CheckObject.zig+39-44
...@@ -6,6 +6,7 @@ const macho = std.macho;...@@ -6,6 +6,7 @@ const macho = std.macho;
6const math = std.math;6const math = std.math;
7const mem = std.mem;7const mem = std.mem;
8const testing = std.testing;8const testing = std.testing;
9const Writer = std.io.Writer;
910
10const CheckObject = @This();11const CheckObject = @This();
1112
...@@ -231,7 +232,7 @@ const ComputeCompareExpected = struct {...@@ -231,7 +232,7 @@ const ComputeCompareExpected = struct {
231232
232 pub fn format(233 pub fn format(
233 value: ComputeCompareExpected,234 value: ComputeCompareExpected,
234 bw: *std.io.BufferedWriter,235 bw: *Writer,
235 comptime fmt: []const u8,236 comptime fmt: []const u8,
236 ) !void {237 ) !void {
237 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
...@@ -619,7 +620,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -619,7 +620,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
619620
620 fn formatMessageString(621 fn formatMessageString(
621 ctx: Ctx,622 ctx: Ctx,
622 bw: *std.io.BufferedWriter,623 bw: *Writer,
623 comptime unused_fmt_string: []const u8,624 comptime unused_fmt_string: []const u8,
624 ) !void {625 ) !void {
625 _ = unused_fmt_string;626 _ = unused_fmt_string;
...@@ -813,7 +814,7 @@ const MachODumper = struct {...@@ -813,7 +814,7 @@ const MachODumper = struct {
813 return null;814 return null;
814 }815 }
815816
816 fn dumpHeader(hdr: macho.mach_header_64, bw: *std.io.BufferedWriter) !void {817 fn dumpHeader(hdr: macho.mach_header_64, bw: *Writer) !void {
817 const cputype = switch (hdr.cputype) {818 const cputype = switch (hdr.cputype) {
818 macho.CPU_TYPE_ARM64 => "ARM64",819 macho.CPU_TYPE_ARM64 => "ARM64",
819 macho.CPU_TYPE_X86_64 => "X86_64",820 macho.CPU_TYPE_X86_64 => "X86_64",
...@@ -881,7 +882,7 @@ const MachODumper = struct {...@@ -881,7 +882,7 @@ const MachODumper = struct {
881 try bw.writeByte('\n');882 try bw.writeByte('\n');
882 }883 }
883884
884 fn dumpLoadCommand(lc: macho.LoadCommandIterator.LoadCommand, index: usize, bw: *std.io.BufferedWriter) !void {885 fn dumpLoadCommand(lc: macho.LoadCommandIterator.LoadCommand, index: usize, bw: *Writer) !void {
885 // print header first886 // print header first
886 try bw.print(887 try bw.print(
887 \\LC {d}888 \\LC {d}
...@@ -1107,7 +1108,7 @@ const MachODumper = struct {...@@ -1107,7 +1108,7 @@ const MachODumper = struct {
1107 }1108 }
1108 }1109 }
11091110
1110 fn dumpSymtab(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {1111 fn dumpSymtab(ctx: ObjectContext, bw: *Writer) !void {
1111 try bw.writeAll(symtab_label ++ "\n");1112 try bw.writeAll(symtab_label ++ "\n");
11121113
1113 for (ctx.symtab.items) |sym| {1114 for (ctx.symtab.items) |sym| {
...@@ -1178,7 +1179,7 @@ const MachODumper = struct {...@@ -1178,7 +1179,7 @@ const MachODumper = struct {
1178 }1179 }
1179 }1180 }
11801181
1181 fn dumpIndirectSymtab(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {1182 fn dumpIndirectSymtab(ctx: ObjectContext, bw: *Writer) !void {
1182 try bw.writeAll(indirect_symtab_label ++ "\n");1183 try bw.writeAll(indirect_symtab_label ++ "\n");
11831184
1184 var sects_buffer: [3]macho.section_64 = undefined;1185 var sects_buffer: [3]macho.section_64 = undefined;
...@@ -1227,7 +1228,7 @@ const MachODumper = struct {...@@ -1227,7 +1228,7 @@ const MachODumper = struct {
1227 }1228 }
1228 }1229 }
12291230
1230 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {1231 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1231 var rebases: std.ArrayList(u64) = .init(ctx.gpa);1232 var rebases: std.ArrayList(u64) = .init(ctx.gpa);
1232 defer rebases.deinit();1233 defer rebases.deinit();
1233 try ctx.parseRebaseInfo(data, &rebases);1234 try ctx.parseRebaseInfo(data, &rebases);
...@@ -1324,7 +1325,7 @@ const MachODumper = struct {...@@ -1324,7 +1325,7 @@ const MachODumper = struct {
1324 };1325 };
1325 };1326 };
13261327
1327 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {1328 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1328 var bindings: std.ArrayList(Binding) = .init(ctx.gpa);1329 var bindings: std.ArrayList(Binding) = .init(ctx.gpa);
1329 defer {1330 defer {
1330 for (bindings.items) |*b| {1331 for (bindings.items) |*b| {
...@@ -1348,8 +1349,7 @@ const MachODumper = struct {...@@ -1348,8 +1349,7 @@ const MachODumper = struct {
1348 }1349 }
13491350
1350 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {1351 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
1351 var br: std.io.Reader = undefined;1352 var br: std.io.Reader = .fixed(data);
1352 br.initFixed(@constCast(data));
13531353
1354 var seg_id: ?u8 = null;1354 var seg_id: ?u8 = null;
1355 var tag: Binding.Tag = .self;1355 var tag: Binding.Tag = .self;
...@@ -1439,15 +1439,14 @@ const MachODumper = struct {...@@ -1439,15 +1439,14 @@ const MachODumper = struct {
1439 } else |_| {}1439 } else |_| {}
1440 }1440 }
14411441
1442 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {1442 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1443 const seg = ctx.getSegmentByName("__TEXT") orelse return;1443 const seg = ctx.getSegmentByName("__TEXT") orelse return;
14441444
1445 var arena = std.heap.ArenaAllocator.init(ctx.gpa);1445 var arena = std.heap.ArenaAllocator.init(ctx.gpa);
1446 defer arena.deinit();1446 defer arena.deinit();
14471447
1448 var exports: std.ArrayList(Export) = .init(arena.allocator());1448 var exports: std.ArrayList(Export) = .init(arena.allocator());
1449 var br: std.io.Reader = undefined;1449 var br: std.io.Reader = .fixed(data);
1450 br.initFixed(@constCast(data));
1451 try parseTrieNode(arena.allocator(), &br, "", &exports);1450 try parseTrieNode(arena.allocator(), &br, "", &exports);
14521451
1453 mem.sort(Export, exports.items, {}, Export.lessThan);1452 mem.sort(Export, exports.items, {}, Export.lessThan);
...@@ -1577,7 +1576,7 @@ const MachODumper = struct {...@@ -1577,7 +1576,7 @@ const MachODumper = struct {
1577 }1576 }
1578 }1577 }
15791578
1580 fn dumpSection(ctx: ObjectContext, sect: macho.section_64, bw: *std.io.BufferedWriter) !void {1579 fn dumpSection(ctx: ObjectContext, sect: macho.section_64, bw: *Writer) !void {
1581 const data = ctx.data[sect.offset..][0..sect.size];1580 const data = ctx.data[sect.offset..][0..sect.size];
1582 try bw.print("{s}", .{data});1581 try bw.print("{s}", .{data});
1583 }1582 }
...@@ -1704,8 +1703,7 @@ const ElfDumper = struct {...@@ -1704,8 +1703,7 @@ const ElfDumper = struct {
17041703
1705 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1704 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1706 const gpa = step.owner.allocator;1705 const gpa = step.owner.allocator;
1707 var br: std.io.Reader = undefined;1706 var br: std.io.Reader = .fixed(bytes);
1708 br.initFixed(@constCast(bytes));
17091707
1710 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;1708 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
17111709
...@@ -1779,8 +1777,7 @@ const ElfDumper = struct {...@@ -1779,8 +1777,7 @@ const ElfDumper = struct {
1779 }1777 }
17801778
1781 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {1779 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {
1782 var br: std.io.Reader = undefined;1780 var br: std.io.Reader = .fixed(data);
1783 br.initFixed(@constCast(data));
1784 const num = switch (ptr_width) {1781 const num = switch (ptr_width) {
1785 .p32 => try br.takeInt(u32, .big),1782 .p32 => try br.takeInt(u32, .big),
1786 .p64 => try br.takeInt(u64, .big),1783 .p64 => try br.takeInt(u64, .big),
...@@ -1807,7 +1804,7 @@ const ElfDumper = struct {...@@ -1807,7 +1804,7 @@ const ElfDumper = struct {
1807 }1804 }
1808 }1805 }
18091806
1810 fn dumpSymtab(ctx: ArchiveContext, bw: *std.io.BufferedWriter) !void {1807 fn dumpSymtab(ctx: ArchiveContext, bw: *Writer) !void {
1811 var symbols: std.AutoArrayHashMap(usize, std.ArrayList([]const u8)) = .init(ctx.gpa);1808 var symbols: std.AutoArrayHashMap(usize, std.ArrayList([]const u8)) = .init(ctx.gpa);
1812 defer {1809 defer {
1813 for (symbols.values()) |*value| value.deinit();1810 for (symbols.values()) |*value| value.deinit();
...@@ -1827,7 +1824,7 @@ const ElfDumper = struct {...@@ -1827,7 +1824,7 @@ const ElfDumper = struct {
1827 }1824 }
1828 }1825 }
18291826
1830 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *std.io.BufferedWriter) !void {1827 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *Writer) !void {
1831 for (ctx.objects.values()) |object| {1828 for (ctx.objects.values()) |object| {
1832 try bw.print("object {s}\n", .{object.name});1829 try bw.print("object {s}\n", .{object.name});
1833 const output = try parseAndDumpObject(step, check, object.data);1830 const output = try parseAndDumpObject(step, check, object.data);
...@@ -1850,8 +1847,7 @@ const ElfDumper = struct {...@@ -1850,8 +1847,7 @@ const ElfDumper = struct {
18501847
1851 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1848 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1852 const gpa = step.owner.allocator;1849 const gpa = step.owner.allocator;
1853 var br: std.io.Reader = undefined;1850 var br: std.io.Reader = .fixed(bytes);
1854 br.initFixed(@constCast(bytes));
18551851
1856 const hdr = try br.takeStruct(elf.Elf64_Ehdr);1852 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
1857 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;1853 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;
...@@ -1944,13 +1940,13 @@ const ElfDumper = struct {...@@ -1944,13 +1940,13 @@ const ElfDumper = struct {
1944 symtab: Symtab,1940 symtab: Symtab,
1945 dysymtab: Symtab,1941 dysymtab: Symtab,
19461942
1947 fn dumpHeader(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {1943 fn dumpHeader(ctx: ObjectContext, bw: *Writer) !void {
1948 try bw.writeAll("header\n");1944 try bw.writeAll("header\n");
1949 try bw.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});1945 try bw.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
1950 try bw.print("entry {x}\n", .{ctx.hdr.e_entry});1946 try bw.print("entry {x}\n", .{ctx.hdr.e_entry});
1951 }1947 }
19521948
1953 fn dumpPhdrs(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {1949 fn dumpPhdrs(ctx: ObjectContext, bw: *Writer) !void {
1954 if (ctx.phdrs.len == 0) return;1950 if (ctx.phdrs.len == 0) return;
19551951
1956 try bw.writeAll("program headers\n");1952 try bw.writeAll("program headers\n");
...@@ -1989,7 +1985,7 @@ const ElfDumper = struct {...@@ -1989,7 +1985,7 @@ const ElfDumper = struct {
1989 }1985 }
1990 }1986 }
19911987
1992 fn dumpShdrs(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {1988 fn dumpShdrs(ctx: ObjectContext, bw: *Writer) !void {
1993 if (ctx.shdrs.len == 0) return;1989 if (ctx.shdrs.len == 0) return;
19941990
1995 try bw.writeAll("section headers\n");1991 try bw.writeAll("section headers\n");
...@@ -2006,7 +2002,7 @@ const ElfDumper = struct {...@@ -2006,7 +2002,7 @@ const ElfDumper = struct {
2006 }2002 }
2007 }2003 }
20082004
2009 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, bw: *std.io.BufferedWriter) !void {2005 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, bw: *Writer) !void {
2010 const shdr = ctx.shdrs[shndx];2006 const shdr = ctx.shdrs[shndx];
2011 const strtab = ctx.getSectionContents(shdr.sh_link);2007 const strtab = ctx.getSectionContents(shdr.sh_link);
2012 const data = ctx.getSectionContents(shndx);2008 const data = ctx.getSectionContents(shndx);
...@@ -2144,7 +2140,7 @@ const ElfDumper = struct {...@@ -2144,7 +2140,7 @@ const ElfDumper = struct {
2144 }2140 }
2145 }2141 }
21462142
2147 fn dumpSymtab(ctx: ObjectContext, comptime @"type": enum { symtab, dysymtab }, bw: *std.io.BufferedWriter) !void {2143 fn dumpSymtab(ctx: ObjectContext, comptime @"type": enum { symtab, dysymtab }, bw: *Writer) !void {
2148 const symtab = switch (@"type") {2144 const symtab = switch (@"type") {
2149 .symtab => ctx.symtab,2145 .symtab => ctx.symtab,
2150 .dysymtab => ctx.dysymtab,2146 .dysymtab => ctx.dysymtab,
...@@ -2226,7 +2222,7 @@ const ElfDumper = struct {...@@ -2226,7 +2222,7 @@ const ElfDumper = struct {
2226 }2222 }
2227 }2223 }
22282224
2229 fn dumpSection(ctx: ObjectContext, shndx: usize, bw: *std.io.BufferedWriter) !void {2225 fn dumpSection(ctx: ObjectContext, shndx: usize, bw: *Writer) !void {
2230 const data = ctx.getSectionContents(shndx);2226 const data = ctx.getSectionContents(shndx);
2231 try bw.print("{s}", .{data});2227 try bw.print("{s}", .{data});
2232 }2228 }
...@@ -2276,7 +2272,7 @@ const ElfDumper = struct {...@@ -2276,7 +2272,7 @@ const ElfDumper = struct {
22762272
2277 fn formatShType(2273 fn formatShType(
2278 sh_type: u32,2274 sh_type: u32,
2279 bw: *std.io.BufferedWriter,2275 bw: *Writer,
2280 comptime unused_fmt_string: []const u8,2276 comptime unused_fmt_string: []const u8,
2281 ) !void {2277 ) !void {
2282 _ = unused_fmt_string;2278 _ = unused_fmt_string;
...@@ -2321,7 +2317,7 @@ const ElfDumper = struct {...@@ -2321,7 +2317,7 @@ const ElfDumper = struct {
23212317
2322 fn formatPhType(2318 fn formatPhType(
2323 ph_type: u32,2319 ph_type: u32,
2324 bw: *std.io.BufferedWriter,2320 bw: *Writer,
2325 comptime unused_fmt_string: []const u8,2321 comptime unused_fmt_string: []const u8,
2326 ) !void {2322 ) !void {
2327 _ = unused_fmt_string;2323 _ = unused_fmt_string;
...@@ -2353,8 +2349,7 @@ const WasmDumper = struct {...@@ -2353,8 +2349,7 @@ const WasmDumper = struct {
23532349
2354 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {2350 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
2355 const gpa = step.owner.allocator;2351 const gpa = step.owner.allocator;
2356 var br: std.io.Reader = undefined;2352 var br: std.io.Reader = .fixed(bytes);
2357 br.initFixed(@constCast(bytes));
23582353
2359 const buf = try br.takeArray(8);2354 const buf = try br.takeArray(8);
2360 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;2355 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;
...@@ -2376,12 +2371,12 @@ const WasmDumper = struct {...@@ -2376,12 +2371,12 @@ const WasmDumper = struct {
2376 step: *Step,2371 step: *Step,
2377 check: Check,2372 check: Check,
2378 br: *std.io.Reader,2373 br: *std.io.Reader,
2379 bw: *std.io.BufferedWriter,2374 bw: *Writer,
2380 ) !void {2375 ) !void {
2381 var section_br: std.io.Reader = undefined;2376 var section_br: std.io.Reader = undefined;
2382 switch (check.kind) {2377 switch (check.kind) {
2383 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {2378 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
2384 section_br.initFixed(try br.take(try br.takeLeb128(u32)));2379 section_br = .fixed(try br.take(try br.takeLeb128(u32)));
2385 try parseAndDumpSection(step, section, &section_br, bw);2380 try parseAndDumpSection(step, section, &section_br, bw);
2386 } else |err| switch (err) {2381 } else |err| switch (err) {
2387 error.InvalidEnumTag => return step.fail("invalid section id", .{}),2382 error.InvalidEnumTag => return step.fail("invalid section id", .{}),
...@@ -2396,7 +2391,7 @@ const WasmDumper = struct {...@@ -2396,7 +2391,7 @@ const WasmDumper = struct {
2396 step: *Step,2391 step: *Step,
2397 section: std.wasm.Section,2392 section: std.wasm.Section,
2398 br: *std.io.Reader,2393 br: *std.io.Reader,
2399 bw: *std.io.BufferedWriter,2394 bw: *Writer,
2400 ) !void {2395 ) !void {
2401 try bw.print(2396 try bw.print(
2402 \\Section {s}2397 \\Section {s}
...@@ -2444,7 +2439,7 @@ const WasmDumper = struct {...@@ -2444,7 +2439,7 @@ const WasmDumper = struct {
2444 }2439 }
2445 }2440 }
24462441
2447 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.Reader, entries: u32, bw: *std.io.BufferedWriter) !void {2442 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.Reader, entries: u32, bw: *Writer) !void {
2448 switch (section) {2443 switch (section) {
2449 .type => {2444 .type => {
2450 var i: u32 = 0;2445 var i: u32 = 0;
...@@ -2575,7 +2570,7 @@ const WasmDumper = struct {...@@ -2575,7 +2570,7 @@ const WasmDumper = struct {
2575 }2570 }
2576 }2571 }
25772572
2578 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.Reader, bw: *std.io.BufferedWriter) !E {2573 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.Reader, bw: *Writer) !E {
2579 const tag = br.takeEnum(E, .little) catch |err| switch (err) {2574 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
2580 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),2575 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
2581 else => |e| return e,2576 else => |e| return e,
...@@ -2584,7 +2579,7 @@ const WasmDumper = struct {...@@ -2584,7 +2579,7 @@ const WasmDumper = struct {
2584 return tag;2579 return tag;
2585 }2580 }
25862581
2587 fn parseDumpLimits(br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {2582 fn parseDumpLimits(br: *std.io.Reader, bw: *Writer) !void {
2588 const flags = try br.takeLeb128(u8);2583 const flags = try br.takeLeb128(u8);
2589 const min = try br.takeLeb128(u32);2584 const min = try br.takeLeb128(u32);
25902585
...@@ -2592,7 +2587,7 @@ const WasmDumper = struct {...@@ -2592,7 +2587,7 @@ const WasmDumper = struct {
2592 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});2587 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
2593 }2588 }
25942589
2595 fn parseDumpInit(step: *Step, br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {2590 fn parseDumpInit(step: *Step, br: *std.io.Reader, bw: *Writer) !void {
2596 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {2591 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
2597 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),2592 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
2598 else => |e| return e,2593 else => |e| return e,
...@@ -2612,14 +2607,14 @@ const WasmDumper = struct {...@@ -2612,14 +2607,14 @@ const WasmDumper = struct {
2612 }2607 }
26132608
2614 /// https://webassembly.github.io/spec/core/appendix/custom.html2609 /// https://webassembly.github.io/spec/core/appendix/custom.html
2615 fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {2610 fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *Writer) !void {
2616 var subsection_br: std.io.Reader = undefined;2611 var subsection_br: std.io.Reader = undefined;
2617 while (br.seek < br.buffer.len) {2612 while (br.seek < br.buffer.len) {
2618 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {2613 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
2619 // The module name subsection ... consists of a single name2614 // The module name subsection ... consists of a single name
2620 // that is assigned to the module itself.2615 // that is assigned to the module itself.
2621 .module => {2616 .module => {
2622 subsection_br.initFixed(try br.take(try br.takeLeb128(u32)));2617 subsection_br = .fixed(try br.take(try br.takeLeb128(u32)));
2623 const name = try subsection_br.take(try subsection_br.takeLeb128(u32));2618 const name = try subsection_br.take(try subsection_br.takeLeb128(u32));
2624 try bw.print(2619 try bw.print(
2625 \\name {s}2620 \\name {s}
...@@ -2631,7 +2626,7 @@ const WasmDumper = struct {...@@ -2631,7 +2626,7 @@ const WasmDumper = struct {
2631 // The function name subsection ... consists of a name map2626 // The function name subsection ... consists of a name map
2632 // assigning function names to function indices.2627 // assigning function names to function indices.
2633 .function, .global, .data_segment => {2628 .function, .global, .data_segment => {
2634 subsection_br.initFixed(try br.take(try br.takeLeb128(u32)));2629 subsection_br = .fixed(try br.take(try br.takeLeb128(u32)));
2635 const entries = try br.takeLeb128(u32);2630 const entries = try br.takeLeb128(u32);
2636 try bw.print(2631 try bw.print(
2637 \\names {d}2632 \\names {d}
...@@ -2661,7 +2656,7 @@ const WasmDumper = struct {...@@ -2661,7 +2656,7 @@ const WasmDumper = struct {
2661 }2656 }
2662 }2657 }
26632658
2664 fn parseDumpProducers(br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {2659 fn parseDumpProducers(br: *std.io.Reader, bw: *Writer) !void {
2665 const field_count = try br.takeLeb128(u32);2660 const field_count = try br.takeLeb128(u32);
2666 try bw.print(2661 try bw.print(
2667 \\fields {d}2662 \\fields {d}
...@@ -2689,7 +2684,7 @@ const WasmDumper = struct {...@@ -2689,7 +2684,7 @@ const WasmDumper = struct {
2689 }2684 }
2690 }2685 }
26912686
2692 fn parseDumpFeatures(br: *std.io.Reader, bw: *std.io.BufferedWriter) !void {2687 fn parseDumpFeatures(br: *std.io.Reader, bw: *Writer) !void {
2693 const feature_count = try br.takeLeb128(u32);2688 const feature_count = try br.takeLeb128(u32);
2694 try bw.print(2689 try bw.print(
2695 \\features {d}2690 \\features {d}
lib/std/Build/Step/ConfigHeader.zig+8-7
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const ConfigHeader = @This();2const ConfigHeader = @This();
3const Step = std.Build.Step;3const Step = std.Build.Step;
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const Writer = std.io.Writer;
56
6pub const Style = union(enum) {7pub const Style = union(enum) {
7 /// A configure format supported by autotools that uses `#undef foo` to8 /// A configure format supported by autotools that uses `#undef foo` to
...@@ -277,7 +278,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -277,7 +278,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
277fn render_autoconf_undef(278fn render_autoconf_undef(
278 step: *Step,279 step: *Step,
279 contents: []const u8,280 contents: []const u8,
280 bw: *std.io.BufferedWriter,281 bw: *Writer,
281 values: std.StringArrayHashMap(Value),282 values: std.StringArrayHashMap(Value),
282 src_path: []const u8,283 src_path: []const u8,
283) !void {284) !void {
...@@ -382,7 +383,7 @@ fn render_autoconf_at(...@@ -382,7 +383,7 @@ fn render_autoconf_at(
382fn render_cmake(383fn render_cmake(
383 step: *Step,384 step: *Step,
384 contents: []const u8,385 contents: []const u8,
385 bw: *std.io.BufferedWriter,386 bw: *Writer,
386 values: std.StringArrayHashMap(Value),387 values: std.StringArrayHashMap(Value),
387 src_path: []const u8,388 src_path: []const u8,
388) !void {389) !void {
...@@ -508,7 +509,7 @@ fn render_cmake(...@@ -508,7 +509,7 @@ fn render_cmake(
508509
509fn render_blank(510fn render_blank(
510 gpa: std.mem.Allocator,511 gpa: std.mem.Allocator,
511 bw: *std.io.BufferedWriter,512 bw: *Writer,
512 defines: std.StringArrayHashMap(Value),513 defines: std.StringArrayHashMap(Value),
513 include_path: []const u8,514 include_path: []const u8,
514 include_guard_override: ?[]const u8,515 include_guard_override: ?[]const u8,
...@@ -541,11 +542,11 @@ fn render_blank(...@@ -541,11 +542,11 @@ fn render_blank(
541 , .{include_guard_name});542 , .{include_guard_name});
542}543}
543544
544fn render_nasm(bw: *std.io.BufferedWriter, defines: std.StringArrayHashMap(Value)) !void {545fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {
545 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);546 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
546}547}
547548
548fn renderValueC(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !void {549fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void {
549 switch (value) {550 switch (value) {
550 .undef => try bw.print("/* #undef {s} */\n", .{name}),551 .undef => try bw.print("/* #undef {s} */\n", .{name}),
551 .defined => try bw.print("#define {s}\n", .{name}),552 .defined => try bw.print("#define {s}\n", .{name}),
...@@ -557,7 +558,7 @@ fn renderValueC(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !voi...@@ -557,7 +558,7 @@ fn renderValueC(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !voi
557 }558 }
558}559}
559560
560fn renderValueNasm(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !void {561fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
561 switch (value) {562 switch (value) {
562 .undef => try bw.print("; %undef {s}\n", .{name}),563 .undef => try bw.print("; %undef {s}\n", .{name}),
563 .defined => try bw.print("%define {s}\n", .{name}),564 .defined => try bw.print("%define {s}\n", .{name}),
...@@ -570,7 +571,7 @@ fn renderValueNasm(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !...@@ -570,7 +571,7 @@ fn renderValueNasm(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !
570}571}
571572
572fn expand_variables_autoconf_at(573fn expand_variables_autoconf_at(
573 bw: *std.io.BufferedWriter,574 bw: *Writer,
574 contents: []const u8,575 contents: []const u8,
575 values: std.StringArrayHashMap(Value),576 values: std.StringArrayHashMap(Value),
576 used: []bool,577 used: []bool,
lib/std/Build/Step/Run.zig+7-11
...@@ -1015,18 +1015,14 @@ fn populateGeneratedPaths(...@@ -1015,18 +1015,14 @@ fn populateGeneratedPaths(
1015 }1015 }
1016}1016}
10171017
1018fn formatTerm(1018fn formatTerm(term: ?std.process.Child.Term, w: *std.io.Writer, comptime fmt: []const u8) !void {
1019 term: ?std.process.Child.Term,1019 comptime assert(fmt.len == 0);
1020 bw: *std.io.BufferedWriter,
1021 comptime fmt: []const u8,
1022) !void {
1023 _ = fmt;
1024 if (term) |t| switch (t) {1020 if (term) |t| switch (t) {
1025 .Exited => |code| try bw.print("exited with code {}", .{code}),1021 .Exited => |code| try w.print("exited with code {}", .{code}),
1026 .Signal => |sig| try bw.print("terminated with signal {}", .{sig}),1022 .Signal => |sig| try w.print("terminated with signal {}", .{sig}),
1027 .Stopped => |sig| try bw.print("stopped with signal {}", .{sig}),1023 .Stopped => |sig| try w.print("stopped with signal {}", .{sig}),
1028 .Unknown => |code| try bw.print("terminated for unknown reason with code {}", .{code}),1024 .Unknown => |code| try w.print("terminated for unknown reason with code {}", .{code}),
1029 } else try bw.writeAll("exited with any code");1025 } else try w.writeAll("exited with any code");
1030}1026}
1031fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {1027fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {
1032 return .{ .data = term };1028 return .{ .data = term };
lib/std/Progress.zig+4-3
...@@ -9,6 +9,7 @@ const Progress = @This();...@@ -9,6 +9,7 @@ const Progress = @This();
9const posix = std.posix;9const posix = std.posix;
10const is_big_endian = builtin.cpu.arch.endian() == .big;10const is_big_endian = builtin.cpu.arch.endian() == .big;
11const is_windows = builtin.os.tag == .windows;11const is_windows = builtin.os.tag == .windows;
12const Writer = std.io.Writer;
1213
13/// `null` if the current node (and its children) should14/// `null` if the current node (and its children) should
14/// not print on update()15/// not print on update()
...@@ -607,7 +608,7 @@ pub fn unlockStdErr() void {...@@ -607,7 +608,7 @@ pub fn unlockStdErr() void {
607}608}
608609
609/// Protected by `stderr_mutex`.610/// Protected by `stderr_mutex`.
610var stderr_buffered_writer: std.io.BufferedWriter = .{611var stderr_buffered_writer: Writer = .{
611 .unbuffered_writer = stderr_file_writer.interface(),612 .unbuffered_writer = stderr_file_writer.interface(),
612 .buffer = &.{},613 .buffer = &.{},
613};614};
...@@ -617,13 +618,13 @@ var stderr_file_writer: std.fs.File.Writer = .{...@@ -617,13 +618,13 @@ var stderr_file_writer: std.fs.File.Writer = .{
617 .mode = .streaming,618 .mode = .streaming,
618};619};
619620
620/// Allows the caller to freely write to the returned `std.io.BufferedWriter`,621/// Allows the caller to freely write to the returned `Writer`,
621/// initialized with `buffer`, until `unlockStderrWriter` is called.622/// initialized with `buffer`, until `unlockStderrWriter` is called.
622///623///
623/// During the lock, any `std.Progress` information is cleared from the terminal.624/// During the lock, any `std.Progress` information is cleared from the terminal.
624///625///
625/// The lock is recursive; the same thread may hold the lock multiple times.626/// The lock is recursive; the same thread may hold the lock multiple times.
626pub fn lockStderrWriter(buffer: []u8) *std.io.BufferedWriter {627pub fn lockStderrWriter(buffer: []u8) *Writer {
627 stderr_mutex.lock();628 stderr_mutex.lock();
628 clearWrittenWithEscapeCodes() catch {};629 clearWrittenWithEscapeCodes() catch {};
629 if (is_windows) stderr_file_writer.file = .stderr();630 if (is_windows) stderr_file_writer.file = .stderr();
lib/std/SemanticVersion.zig+1-1
...@@ -152,7 +152,7 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {...@@ -152,7 +152,7 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {
152152
153pub fn format(153pub fn format(
154 self: Version,154 self: Version,
155 bw: *std.io.BufferedWriter,155 bw: *std.io.Writer,
156 comptime fmt: []const u8,156 comptime fmt: []const u8,
157) !void {157) !void {
158 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);158 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
lib/std/Target.zig+1-1
...@@ -301,7 +301,7 @@ pub const Os = struct {...@@ -301,7 +301,7 @@ pub const Os = struct {
301301
302 /// This function is defined to serialize a Zig source code representation of this302 /// This function is defined to serialize a Zig source code representation of this
303 /// type, that, when parsed, will deserialize into the same data.303 /// type, that, when parsed, will deserialize into the same data.
304 pub fn format(ver: WindowsVersion, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {304 pub fn format(ver: WindowsVersion, bw: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
305 const maybe_name = std.enums.tagName(WindowsVersion, ver);305 const maybe_name = std.enums.tagName(WindowsVersion, ver);
306 if (comptime std.mem.eql(u8, fmt_str, "s")) {306 if (comptime std.mem.eql(u8, fmt_str, "s")) {
307 if (maybe_name) |name|307 if (maybe_name) |name|
lib/std/Uri.zig+7-7
...@@ -5,6 +5,7 @@ const std = @import("std.zig");...@@ -5,6 +5,7 @@ const std = @import("std.zig");
5const testing = std.testing;5const testing = std.testing;
6const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const Writer = std.io.Writer;
89
9const Uri = @This();10const Uri = @This();
1011
...@@ -84,7 +85,7 @@ pub const Component = union(enum) {...@@ -84,7 +85,7 @@ pub const Component = union(enum) {
84 };85 };
85 }86 }
8687
87 pub fn format(component: Component, bw: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {88 pub fn format(component: Component, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
88 if (fmt.len == 0) {89 if (fmt.len == 0) {
89 try bw.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{90 try bw.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{
90 @tagName(component),91 @tagName(component),
...@@ -136,10 +137,10 @@ pub const Component = union(enum) {...@@ -136,10 +137,10 @@ pub const Component = union(enum) {
136 }137 }
137138
138 pub fn percentEncode(139 pub fn percentEncode(
139 bw: *std.io.BufferedWriter,140 bw: *Writer,
140 raw: []const u8,141 raw: []const u8,
141 comptime isValidChar: fn (u8) bool,142 comptime isValidChar: fn (u8) bool,
142 ) std.io.Writer.Error!void {143 ) Writer.Error!void {
143 var start: usize = 0;144 var start: usize = 0;
144 for (raw, 0..) |char, index| {145 for (raw, 0..) |char, index| {
145 if (isValidChar(char)) continue;146 if (isValidChar(char)) continue;
...@@ -280,7 +281,7 @@ pub const WriteToStreamOptions = struct {...@@ -280,7 +281,7 @@ pub const WriteToStreamOptions = struct {
280 port: bool = true,281 port: bool = true,
281};282};
282283
283pub fn writeToStream(uri: Uri, options: WriteToStreamOptions, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {284pub fn writeToStream(uri: Uri, options: WriteToStreamOptions, bw: *Writer) Writer.Error!void {
284 if (options.scheme) {285 if (options.scheme) {
285 try bw.print("{s}:", .{uri.scheme});286 try bw.print("{s}:", .{uri.scheme});
286 if (options.authority and uri.host != null) {287 if (options.authority and uri.host != null) {
...@@ -317,7 +318,7 @@ pub fn writeToStream(uri: Uri, options: WriteToStreamOptions, bw: *std.io.Buffer...@@ -317,7 +318,7 @@ pub fn writeToStream(uri: Uri, options: WriteToStreamOptions, bw: *std.io.Buffer
317 }318 }
318}319}
319320
320pub fn format(uri: Uri, bw: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {321pub fn format(uri: Uri, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
321 const scheme = comptime std.mem.indexOfScalar(u8, fmt, ';') != null or fmt.len == 0;322 const scheme = comptime std.mem.indexOfScalar(u8, fmt, ';') != null or fmt.len == 0;
322 const authentication = comptime std.mem.indexOfScalar(u8, fmt, '@') != null or fmt.len == 0;323 const authentication = comptime std.mem.indexOfScalar(u8, fmt, '@') != null or fmt.len == 0;
323 const authority = comptime std.mem.indexOfScalar(u8, fmt, '+') != null or fmt.len == 0;324 const authority = comptime std.mem.indexOfScalar(u8, fmt, '+') != null or fmt.len == 0;
...@@ -461,8 +462,7 @@ test remove_dot_segments {...@@ -461,8 +462,7 @@ test remove_dot_segments {
461462
462/// 5.2.3. Merge Paths463/// 5.2.3. Merge Paths
463fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {464fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
464 var aux: std.io.BufferedWriter = undefined;465 var aux: Writer = .fixed(aux_buf.*);
465 aux.initFixed(aux_buf.*);
466 if (!base.isEmpty()) {466 if (!base.isEmpty()) {
467 aux.print("{fpath}", .{base}) catch return error.NoSpaceLeft;467 aux.print("{fpath}", .{base}) catch return error.NoSpaceLeft;
468 aux.end = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse468 aux.end = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse
lib/std/array_list.zig+5-7
...@@ -905,20 +905,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -905,20 +905,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
905 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {905 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
906 comptime assert(T == u8);906 comptime assert(T == u8);
907 try self.ensureUnusedCapacity(gpa, fmt.len);907 try self.ensureUnusedCapacity(gpa, fmt.len);
908 var aw: std.io.AllocatingWriter = undefined;908 var aw: std.io.AllocatingWriter = .fromArrayList(gpa, self);
909 const bw = aw.fromArrayList(gpa, self);
910 defer self.* = aw.toArrayList();909 defer self.* = aw.toArrayList();
911 return bw.print(fmt, args) catch |err| switch (err) {910 return aw.interface.print(fmt, args) catch |err| switch (err) {
912 error.WriteFailed => return error.OutOfMemory,911 error.WriteFailed => return error.OutOfMemory,
913 };912 };
914 }913 }
915914
916 pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void {915 pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void {
917 comptime assert(T == u8);916 comptime assert(T == u8);
918 var bw: std.io.BufferedWriter = undefined;917 var w: std.io.Writer = .fixed(self.unusedCapacitySlice());
919 bw.initFixed(self.unusedCapacitySlice());918 w.print(fmt, args) catch unreachable;
920 bw.print(fmt, args) catch unreachable;919 self.items.len += w.end;
921 self.items.len += bw.end;
922 }920 }
923921
924 /// Append a value to the list `n` times.922 /// Append a value to the list `n` times.
lib/std/builtin.zig+1-1
...@@ -34,7 +34,7 @@ pub const StackTrace = struct {...@@ -34,7 +34,7 @@ pub const StackTrace = struct {
34 index: usize,34 index: usize,
35 instruction_addresses: []usize,35 instruction_addresses: []usize,
3636
37 pub fn format(st: StackTrace, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {37 pub fn format(st: StackTrace, bw: *std.io.Writer, comptime fmt: []const u8) !void {
38 comptime if (fmt.len != 0) unreachable;38 comptime if (fmt.len != 0) unreachable;
3939
40 // TODO: re-evaluate whether to use format() methods at all.40 // TODO: re-evaluate whether to use format() methods at all.
lib/std/compress/flate.zig+22-41
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("../std.zig");2const std = @import("../std.zig");
3const testing = std.testing;3const testing = std.testing;
4const Writer = std.io.Writer;
45
5/// Container of the deflate bit stream body. Container adds header before6/// Container of the deflate bit stream body. Container adds header before
6/// deflate bit stream and footer after. It can bi gzip, zlib or raw (no header,7/// deflate bit stream and footer after. It can bi gzip, zlib or raw (no header,
...@@ -106,7 +107,7 @@ pub const Container = enum {...@@ -106,7 +107,7 @@ pub const Container = enum {
106 }107 }
107 }108 }
108109
109 pub fn writeFooter(hasher: *Hasher, writer: *std.io.BufferedWriter) std.io.Writer.Error!void {110 pub fn writeFooter(hasher: *Hasher, writer: *Writer) Writer.Error!void {
110 var bits: [4]u8 = undefined;111 var bits: [4]u8 = undefined;
111 switch (hasher.*) {112 switch (hasher.*) {
112 .gzip => |*gzip| {113 .gzip => |*gzip| {
...@@ -230,8 +231,7 @@ test "compress/decompress" {...@@ -230,8 +231,7 @@ test "compress/decompress" {
230 // compress original stream to compressed stream231 // compress original stream to compressed stream
231 {232 {
232 var original: std.io.Reader = .fixed(data);233 var original: std.io.Reader = .fixed(data);
233 var compressed: std.io.BufferedWriter = undefined;234 var compressed: Writer = .fixed(&cmp_buf);
234 compressed.initFixed(&cmp_buf);
235 var compress: Compress = .init(&original, .raw);235 var compress: Compress = .init(&original, .raw);
236 var compress_br = compress.readable(&.{});236 var compress_br = compress.readable(&.{});
237 const n = try compress_br.readRemaining(&compressed, .{ .level = level });237 const n = try compress_br.readRemaining(&compressed, .{ .level = level });
...@@ -246,16 +246,14 @@ test "compress/decompress" {...@@ -246,16 +246,14 @@ test "compress/decompress" {
246 // decompress compressed stream to decompressed stream246 // decompress compressed stream to decompressed stream
247 {247 {
248 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);248 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
249 var decompressed: std.io.BufferedWriter = undefined;249 var decompressed: Writer = .fixed(&dcm_buf);
250 decompressed.initFixed(&dcm_buf);
251 try Decompress.pump(container, &compressed, &decompressed);250 try Decompress.pump(container, &compressed, &decompressed);
252 try testing.expectEqualSlices(u8, data, decompressed.getWritten());251 try testing.expectEqualSlices(u8, data, decompressed.getWritten());
253 }252 }
254253
255 // compressor writer interface254 // compressor writer interface
256 {255 {
257 var compressed: std.io.BufferedWriter = undefined;256 var compressed: Writer = .fixed(&cmp_buf);
258 compressed.initFixed(&cmp_buf);
259 var cmp = try Compress.init(container, &compressed, .{ .level = level });257 var cmp = try Compress.init(container, &compressed, .{ .level = level });
260 var cmp_wrt = cmp.writer();258 var cmp_wrt = cmp.writer();
261 try cmp_wrt.writeAll(data);259 try cmp_wrt.writeAll(data);
...@@ -285,8 +283,7 @@ test "compress/decompress" {...@@ -285,8 +283,7 @@ test "compress/decompress" {
285 // compress original stream to compressed stream283 // compress original stream to compressed stream
286 {284 {
287 var original: std.io.Reader = .fixed(data);285 var original: std.io.Reader = .fixed(data);
288 var compressed: std.io.BufferedWriter = undefined;286 var compressed: Writer = .fixed(&cmp_buf);
289 compressed.initFixed(&cmp_buf);
290 var cmp = try Compress.Huffman.init(container, &compressed);287 var cmp = try Compress.Huffman.init(container, &compressed);
291 try cmp.compress(original.reader());288 try cmp.compress(original.reader());
292 try cmp.finish();289 try cmp.finish();
...@@ -300,8 +297,7 @@ test "compress/decompress" {...@@ -300,8 +297,7 @@ test "compress/decompress" {
300 // decompress compressed stream to decompressed stream297 // decompress compressed stream to decompressed stream
301 {298 {
302 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);299 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
303 var decompressed: std.io.BufferedWriter = undefined;300 var decompressed: Writer = .fixed(&dcm_buf);
304 decompressed.initFixed(&dcm_buf);
305 try Decompress.pump(container, &compressed, &decompressed);301 try Decompress.pump(container, &compressed, &decompressed);
306 try testing.expectEqualSlices(u8, data, decompressed.getWritten());302 try testing.expectEqualSlices(u8, data, decompressed.getWritten());
307 }303 }
...@@ -319,8 +315,7 @@ test "compress/decompress" {...@@ -319,8 +315,7 @@ test "compress/decompress" {
319 // compress original stream to compressed stream315 // compress original stream to compressed stream
320 {316 {
321 var original: std.io.Reader = .fixed(data);317 var original: std.io.Reader = .fixed(data);
322 var compressed: std.io.BufferedWriter = undefined;318 var compressed: Writer = .fixed(&cmp_buf);
323 compressed.initFixed(&cmp_buf);
324 var cmp = try Compress.SimpleCompressor(.store, container).init(&compressed);319 var cmp = try Compress.SimpleCompressor(.store, container).init(&compressed);
325 try cmp.compress(original.reader());320 try cmp.compress(original.reader());
326 try cmp.finish();321 try cmp.finish();
...@@ -335,8 +330,7 @@ test "compress/decompress" {...@@ -335,8 +330,7 @@ test "compress/decompress" {
335 // decompress compressed stream to decompressed stream330 // decompress compressed stream to decompressed stream
336 {331 {
337 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);332 var compressed: std.io.Reader = .fixed(cmp_buf[0..compressed_size]);
338 var decompressed: std.io.BufferedWriter = undefined;333 var decompressed: Writer = .fixed(&dcm_buf);
339 decompressed.initFixed(&dcm_buf);
340 try Decompress.pump(container, &compressed, &decompressed);334 try Decompress.pump(container, &compressed, &decompressed);
341 try testing.expectEqualSlices(u8, data, decompressed.getWritten());335 try testing.expectEqualSlices(u8, data, decompressed.getWritten());
342 }336 }
...@@ -491,8 +485,7 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -491,8 +485,7 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
491485
492 // decompress486 // decompress
493 {487 {
494 var plain: std.io.BufferedWriter = undefined;488 var plain: Writer = .fixed(&buffer2);
495 plain.initFixed(&buffer2);
496489
497 var in: std.io.Reader = .fixed(gzip_data);490 var in: std.io.Reader = .fixed(gzip_data);
498 try pkg.decompress(&in, &plain);491 try pkg.decompress(&in, &plain);
...@@ -501,10 +494,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -501,10 +494,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
501494
502 // compress/decompress495 // compress/decompress
503 {496 {
504 var plain: std.io.BufferedWriter = undefined;497 var plain: Writer = .fixed(&buffer2);
505 plain.initFixed(&buffer2);498 var compressed: Writer = .fixed(&buffer1);
506 var compressed: std.io.BufferedWriter = undefined;
507 compressed.initFixed(&buffer1);
508499
509 var in: std.io.Reader = .fixed(plain_data);500 var in: std.io.Reader = .fixed(plain_data);
510 try pkg.compress(&in, &compressed, .{});501 try pkg.compress(&in, &compressed, .{});
...@@ -516,10 +507,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -516,10 +507,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
516507
517 // compressor/decompressor508 // compressor/decompressor
518 {509 {
519 var plain: std.io.BufferedWriter = undefined;510 var plain: Writer = .fixed(&buffer2);
520 plain.initFixed(&buffer2);511 var compressed: Writer = .fixed(&buffer1);
521 var compressed: std.io.BufferedWriter = undefined;
522 compressed.initFixed(&buffer1);
523512
524 var in: std.io.Reader = .fixed(plain_data);513 var in: std.io.Reader = .fixed(plain_data);
525 var cmp = try pkg.compressor(&compressed, .{});514 var cmp = try pkg.compressor(&compressed, .{});
...@@ -536,10 +525,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -536,10 +525,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
536 {525 {
537 // huffman compress/decompress526 // huffman compress/decompress
538 {527 {
539 var plain: std.io.BufferedWriter = undefined;528 var plain: Writer = .fixed(&buffer2);
540 plain.initFixed(&buffer2);529 var compressed: Writer = .fixed(&buffer1);
541 var compressed: std.io.BufferedWriter = undefined;
542 compressed.initFixed(&buffer1);
543530
544 var in: std.io.Reader = .fixed(plain_data);531 var in: std.io.Reader = .fixed(plain_data);
545 try pkg.huffman.compress(&in, &compressed);532 try pkg.huffman.compress(&in, &compressed);
...@@ -551,10 +538,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -551,10 +538,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
551538
552 // huffman compressor/decompressor539 // huffman compressor/decompressor
553 {540 {
554 var plain: std.io.BufferedWriter = undefined;541 var plain: Writer = .fixed(&buffer2);
555 plain.initFixed(&buffer2);542 var compressed: Writer = .fixed(&buffer1);
556 var compressed: std.io.BufferedWriter = undefined;
557 compressed.initFixed(&buffer1);
558543
559 var in: std.io.Reader = .fixed(plain_data);544 var in: std.io.Reader = .fixed(plain_data);
560 var cmp = try pkg.huffman.compressor(&compressed);545 var cmp = try pkg.huffman.compressor(&compressed);
...@@ -571,10 +556,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -571,10 +556,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
571 {556 {
572 // store compress/decompress557 // store compress/decompress
573 {558 {
574 var plain: std.io.BufferedWriter = undefined;559 var plain: Writer = .fixed(&buffer2);
575 plain.initFixed(&buffer2);560 var compressed: Writer = .fixed(&buffer1);
576 var compressed: std.io.BufferedWriter = undefined;
577 compressed.initFixed(&buffer1);
578561
579 var in: std.io.Reader = .fixed(plain_data);562 var in: std.io.Reader = .fixed(plain_data);
580 try pkg.store.compress(&in, &compressed);563 try pkg.store.compress(&in, &compressed);
...@@ -586,10 +569,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const...@@ -586,10 +569,8 @@ fn testInterface(comptime pkg: type, gzip_data: []const u8, plain_data: []const
586569
587 // store compressor/decompressor570 // store compressor/decompressor
588 {571 {
589 var plain: std.io.BufferedWriter = undefined;572 var plain: Writer = .fixed(&buffer2);
590 plain.initFixed(&buffer2);573 var compressed: Writer = .fixed(&buffer1);
591 var compressed: std.io.BufferedWriter = undefined;
592 compressed.initFixed(&buffer1);
593574
594 var in: std.io.Reader = .fixed(plain_data);575 var in: std.io.Reader = .fixed(plain_data);
595 var cmp = try pkg.store.compressor(&compressed);576 var cmp = try pkg.store.compressor(&compressed);
lib/std/compress/flate/BlockWriter.zig+14-13
...@@ -3,6 +3,7 @@...@@ -3,6 +3,7 @@
3const std = @import("std");3const std = @import("std");
4const io = std.io;4const io = std.io;
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const Writer = std.io.Writer;
67
7const BlockWriter = @This();8const BlockWriter = @This();
8const flate = @import("../flate.zig");9const flate = @import("../flate.zig");
...@@ -13,7 +14,7 @@ const Token = @import("Token.zig");...@@ -13,7 +14,7 @@ const Token = @import("Token.zig");
13const codegen_order = huffman.codegen_order;14const codegen_order = huffman.codegen_order;
14const end_code_mark = 255;15const end_code_mark = 255;
1516
16output: *std.io.BufferedWriter,17output: *Writer,
1718
18codegen_freq: [huffman.codegen_code_count]u16 = undefined,19codegen_freq: [huffman.codegen_code_count]u16 = undefined,
19literal_freq: [huffman.max_num_lit]u16 = undefined,20literal_freq: [huffman.max_num_lit]u16 = undefined,
...@@ -26,7 +27,7 @@ fixed_literal_encoding: Compress.LiteralEncoder,...@@ -26,7 +27,7 @@ fixed_literal_encoding: Compress.LiteralEncoder,
26fixed_distance_encoding: Compress.DistanceEncoder,27fixed_distance_encoding: Compress.DistanceEncoder,
27huff_distance: Compress.DistanceEncoder,28huff_distance: Compress.DistanceEncoder,
2829
29pub fn init(output: *std.io.BufferedWriter) BlockWriter {30pub fn init(output: *Writer) BlockWriter {
30 return .{31 return .{
31 .output = output,32 .output = output,
32 .fixed_literal_encoding = Compress.fixedLiteralEncoder(),33 .fixed_literal_encoding = Compress.fixedLiteralEncoder(),
...@@ -41,15 +42,15 @@ pub fn init(output: *std.io.BufferedWriter) BlockWriter {...@@ -41,15 +42,15 @@ pub fn init(output: *std.io.BufferedWriter) BlockWriter {
41/// That is after final block; when last byte could be incomplete or42/// That is after final block; when last byte could be incomplete or
42/// after stored block; which is aligned to the byte boundary (it has x43/// after stored block; which is aligned to the byte boundary (it has x
43/// padding bits after first 3 bits).44/// padding bits after first 3 bits).
44pub fn flush(self: *BlockWriter) std.io.Writer.Error!void {45pub fn flush(self: *BlockWriter) Writer.Error!void {
45 try self.bit_writer.flush();46 try self.bit_writer.flush();
46}47}
4748
48pub fn setWriter(self: *BlockWriter, new_writer: *std.io.BufferedWriter) void {49pub fn setWriter(self: *BlockWriter, new_writer: *Writer) void {
49 self.bit_writer.setWriter(new_writer);50 self.bit_writer.setWriter(new_writer);
50}51}
5152
52fn writeCode(self: *BlockWriter, c: Compress.HuffCode) std.io.Writer.Error!void {53fn writeCode(self: *BlockWriter, c: Compress.HuffCode) Writer.Error!void {
53 try self.bit_writer.writeBits(c.code, c.len);54 try self.bit_writer.writeBits(c.code, c.len);
54}55}
5556
...@@ -231,7 +232,7 @@ fn dynamicHeader(...@@ -231,7 +232,7 @@ fn dynamicHeader(
231 num_distances: u32,232 num_distances: u32,
232 num_codegens: u32,233 num_codegens: u32,
233 eof: bool,234 eof: bool,
234) std.io.Writer.Error!void {235) Writer.Error!void {
235 const first_bits: u32 = if (eof) 5 else 4;236 const first_bits: u32 = if (eof) 5 else 4;
236 try self.bit_writer.writeBits(first_bits, 3);237 try self.bit_writer.writeBits(first_bits, 3);
237 try self.bit_writer.writeBits(num_literals - 257, 5);238 try self.bit_writer.writeBits(num_literals - 257, 5);
...@@ -271,7 +272,7 @@ fn dynamicHeader(...@@ -271,7 +272,7 @@ fn dynamicHeader(
271 }272 }
272}273}
273274
274fn storedHeader(self: *BlockWriter, length: usize, eof: bool) std.io.Writer.Error!void {275fn storedHeader(self: *BlockWriter, length: usize, eof: bool) Writer.Error!void {
275 assert(length <= 65535);276 assert(length <= 65535);
276 const flag: u32 = if (eof) 1 else 0;277 const flag: u32 = if (eof) 1 else 0;
277 try self.bit_writer.writeBits(flag, 3);278 try self.bit_writer.writeBits(flag, 3);
...@@ -281,7 +282,7 @@ fn storedHeader(self: *BlockWriter, length: usize, eof: bool) std.io.Writer.Erro...@@ -281,7 +282,7 @@ fn storedHeader(self: *BlockWriter, length: usize, eof: bool) std.io.Writer.Erro
281 try self.bit_writer.writeBits(~l, 16);282 try self.bit_writer.writeBits(~l, 16);
282}283}
283284
284fn fixedHeader(self: *BlockWriter, eof: bool) std.io.Writer.Error!void {285fn fixedHeader(self: *BlockWriter, eof: bool) Writer.Error!void {
285 // Indicate that we are a fixed Huffman block286 // Indicate that we are a fixed Huffman block
286 var value: u32 = 2;287 var value: u32 = 2;
287 if (eof) {288 if (eof) {
...@@ -295,7 +296,7 @@ fn fixedHeader(self: *BlockWriter, eof: bool) std.io.Writer.Error!void {...@@ -295,7 +296,7 @@ fn fixedHeader(self: *BlockWriter, eof: bool) std.io.Writer.Error!void {
295// is larger than the original bytes, the data will be written as a296// is larger than the original bytes, the data will be written as a
296// stored block.297// stored block.
297// If the input is null, the tokens will always be Huffman encoded.298// If the input is null, the tokens will always be Huffman encoded.
298pub fn write(self: *BlockWriter, tokens: []const Token, eof: bool, input: ?[]const u8) std.io.Writer.Error!void {299pub fn write(self: *BlockWriter, tokens: []const Token, eof: bool, input: ?[]const u8) Writer.Error!void {
299 const lit_and_dist = self.indexTokens(tokens);300 const lit_and_dist = self.indexTokens(tokens);
300 const num_literals = lit_and_dist.num_literals;301 const num_literals = lit_and_dist.num_literals;
301 const num_distances = lit_and_dist.num_distances;302 const num_distances = lit_and_dist.num_distances;
...@@ -373,7 +374,7 @@ pub fn write(self: *BlockWriter, tokens: []const Token, eof: bool, input: ?[]con...@@ -373,7 +374,7 @@ pub fn write(self: *BlockWriter, tokens: []const Token, eof: bool, input: ?[]con
373 try self.writeTokens(tokens, &literal_encoding.codes, &distance_encoding.codes);374 try self.writeTokens(tokens, &literal_encoding.codes, &distance_encoding.codes);
374}375}
375376
376pub fn storedBlock(self: *BlockWriter, input: []const u8, eof: bool) std.io.Writer.Error!void {377pub fn storedBlock(self: *BlockWriter, input: []const u8, eof: bool) Writer.Error!void {
377 try self.storedHeader(input.len, eof);378 try self.storedHeader(input.len, eof);
378 try self.bit_writer.writeBytes(input);379 try self.bit_writer.writeBytes(input);
379}380}
...@@ -388,7 +389,7 @@ fn dynamicBlock(...@@ -388,7 +389,7 @@ fn dynamicBlock(
388 tokens: []const Token,389 tokens: []const Token,
389 eof: bool,390 eof: bool,
390 input: ?[]const u8,391 input: ?[]const u8,
391) std.io.Writer.Error!void {392) Writer.Error!void {
392 const total_tokens = self.indexTokens(tokens);393 const total_tokens = self.indexTokens(tokens);
393 const num_literals = total_tokens.num_literals;394 const num_literals = total_tokens.num_literals;
394 const num_distances = total_tokens.num_distances;395 const num_distances = total_tokens.num_distances;
...@@ -485,7 +486,7 @@ fn writeTokens(...@@ -485,7 +486,7 @@ fn writeTokens(
485 tokens: []const Token,486 tokens: []const Token,
486 le_codes: []Compress.HuffCode,487 le_codes: []Compress.HuffCode,
487 oe_codes: []Compress.HuffCode,488 oe_codes: []Compress.HuffCode,
488) std.io.Writer.Error!void {489) Writer.Error!void {
489 for (tokens) |t| {490 for (tokens) |t| {
490 if (t.kind == Token.Kind.literal) {491 if (t.kind == Token.Kind.literal) {
491 try self.writeCode(le_codes[t.literal()]);492 try self.writeCode(le_codes[t.literal()]);
...@@ -512,7 +513,7 @@ fn writeTokens(...@@ -512,7 +513,7 @@ fn writeTokens(
512513
513// Encodes a block of bytes as either Huffman encoded literals or uncompressed bytes514// Encodes a block of bytes as either Huffman encoded literals or uncompressed bytes
514// if the results only gains very little from compression.515// if the results only gains very little from compression.
515pub fn huffmanBlock(self: *BlockWriter, input: []const u8, eof: bool) std.io.Writer.Error!void {516pub fn huffmanBlock(self: *BlockWriter, input: []const u8, eof: bool) Writer.Error!void {
516 // Add everything as literals517 // Add everything as literals
517 histogram(input, &self.literal_freq);518 histogram(input, &self.literal_freq);
518519
lib/std/compress/flate/Compress.zig+15-16
...@@ -47,6 +47,7 @@ const testing = std.testing;...@@ -47,6 +47,7 @@ const testing = std.testing;
47const expect = testing.expect;47const expect = testing.expect;
48const mem = std.mem;48const mem = std.mem;
49const math = std.math;49const math = std.math;
50const Writer = std.io.Writer;
5051
51const Compress = @This();52const Compress = @This();
52const Token = @import("Token.zig");53const Token = @import("Token.zig");
...@@ -142,7 +143,7 @@ const FlushOption = enum { none, flush, final };...@@ -142,7 +143,7 @@ const FlushOption = enum { none, flush, final };
142/// flush tokens to the token writer.143/// flush tokens to the token writer.
143///144///
144/// Returns number of bytes consumed from `lh`.145/// Returns number of bytes consumed from `lh`.
145fn tokenizeSlice(c: *Compress, bw: *std.io.BufferedWriter, limit: std.io.Limit, lh: []const u8) !usize {146fn tokenizeSlice(c: *Compress, bw: *Writer, limit: std.io.Limit, lh: []const u8) !usize {
146 _ = bw;147 _ = bw;
147 _ = limit;148 _ = limit;
148 if (true) @panic("TODO");149 if (true) @panic("TODO");
...@@ -299,7 +300,7 @@ pub fn finish(c: *Compress) !void {...@@ -299,7 +300,7 @@ pub fn finish(c: *Compress) !void {
299300
300/// Use another writer while preserving history. Most probably flush301/// Use another writer while preserving history. Most probably flush
301/// should be called on old writer before setting new.302/// should be called on old writer before setting new.
302pub fn setWriter(self: *Compress, new_writer: *std.io.BufferedWriter) void {303pub fn setWriter(self: *Compress, new_writer: *Writer) void {
303 self.block_writer.setWriter(new_writer);304 self.block_writer.setWriter(new_writer);
304 self.output = new_writer;305 self.output = new_writer;
305}306}
...@@ -767,7 +768,7 @@ fn byFreq(context: void, a: LiteralNode, b: LiteralNode) bool {...@@ -767,7 +768,7 @@ fn byFreq(context: void, a: LiteralNode, b: LiteralNode) bool {
767768
768fn read(769fn read(
769 context: ?*anyopaque,770 context: ?*anyopaque,
770 bw: *std.io.BufferedWriter,771 bw: *Writer,
771 limit: std.io.Limit,772 limit: std.io.Limit,
772) std.io.Reader.StreamError!usize {773) std.io.Reader.StreamError!usize {
773 const c: *Compress = @ptrCast(@alignCast(context));774 const c: *Compress = @ptrCast(@alignCast(context));
...@@ -1147,8 +1148,7 @@ test "file tokenization" {...@@ -1147,8 +1148,7 @@ test "file tokenization" {
1147 const data = case.data;1148 const data = case.data;
11481149
1149 for (levels, 0..) |level, i| { // for each compression level1150 for (levels, 0..) |level, i| { // for each compression level
1150 var original: std.io.Reader = undefined;1151 var original: std.io.Reader = .fixed(data);
1151 original.initFixed(data);
11521152
1153 // buffer for decompressed data1153 // buffer for decompressed data
1154 var al = std.ArrayList(u8).init(testing.allocator);1154 var al = std.ArrayList(u8).init(testing.allocator);
...@@ -1181,10 +1181,10 @@ test "file tokenization" {...@@ -1181,10 +1181,10 @@ test "file tokenization" {
1181}1181}
11821182
1183const TokenDecoder = struct {1183const TokenDecoder = struct {
1184 output: *std.io.BufferedWriter,1184 output: *Writer,
1185 tokens_count: usize,1185 tokens_count: usize,
11861186
1187 pub fn init(output: *std.io.BufferedWriter) TokenDecoder {1187 pub fn init(output: *Writer) TokenDecoder {
1188 return .{1188 return .{
1189 .output = output,1189 .output = output,
1190 .tokens_count = 0,1190 .tokens_count = 0,
...@@ -1222,8 +1222,7 @@ test "store simple compressor" {...@@ -1222,8 +1222,7 @@ test "store simple compressor" {
1222 //0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,1222 //0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
1223 };1223 };
12241224
1225 var fbs: std.io.Reader = undefined;1225 var fbs: std.io.Reader = .fixed(data);
1226 fbs.initFixed(data);
1227 var al = std.ArrayList(u8).init(testing.allocator);1226 var al = std.ArrayList(u8).init(testing.allocator);
1228 defer al.deinit();1227 defer al.deinit();
12291228
...@@ -1232,7 +1231,7 @@ test "store simple compressor" {...@@ -1232,7 +1231,7 @@ test "store simple compressor" {
1232 try cmp.finish();1231 try cmp.finish();
1233 try testing.expectEqualSlices(u8, &expected, al.items);1232 try testing.expectEqualSlices(u8, &expected, al.items);
12341233
1235 fbs.initFixed(data);1234 fbs = .fixed(data);
1236 try al.resize(0);1235 try al.resize(0);
12371236
1238 // huffman only compresoor will also emit store block for this small sample1237 // huffman only compresoor will also emit store block for this small sample
...@@ -1244,7 +1243,7 @@ test "store simple compressor" {...@@ -1244,7 +1243,7 @@ test "store simple compressor" {
12441243
1245test "sliding window match" {1244test "sliding window match" {
1246 const data = "Blah blah blah blah blah!";1245 const data = "Blah blah blah blah blah!";
1247 var win: std.io.BufferedWriter = .{};1246 var win: Writer = .{};
1248 try expect(win.write(data) == data.len);1247 try expect(win.write(data) == data.len);
1249 try expect(win.wp == data.len);1248 try expect(win.wp == data.len);
1250 try expect(win.rp == 0);1249 try expect(win.rp == 0);
...@@ -1263,9 +1262,9 @@ test "sliding window match" {...@@ -1263,9 +1262,9 @@ test "sliding window match" {
1263}1262}
12641263
1265test "sliding window slide" {1264test "sliding window slide" {
1266 var win: std.io.BufferedWriter = .{};1265 var win: Writer = .{};
1267 win.wp = std.io.BufferedWriter.buffer_len - 11;1266 win.wp = Writer.buffer_len - 11;
1268 win.rp = std.io.BufferedWriter.buffer_len - 111;1267 win.rp = Writer.buffer_len - 111;
1269 win.buffer[win.rp] = 0xab;1268 win.buffer[win.rp] = 0xab;
1270 try expect(win.lookahead().len == 100);1269 try expect(win.lookahead().len == 100);
1271 try expect(win.tokensBuffer().?.len == win.rp);1270 try expect(win.tokensBuffer().?.len == win.rp);
...@@ -1273,8 +1272,8 @@ test "sliding window slide" {...@@ -1273,8 +1272,8 @@ test "sliding window slide" {
1273 const n = win.slide();1272 const n = win.slide();
1274 try expect(n == 32757);1273 try expect(n == 32757);
1275 try expect(win.buffer[win.rp] == 0xab);1274 try expect(win.buffer[win.rp] == 0xab);
1276 try expect(win.rp == std.io.BufferedWriter.hist_len - 111);1275 try expect(win.rp == Writer.hist_len - 111);
1277 try expect(win.wp == std.io.BufferedWriter.hist_len - 11);1276 try expect(win.wp == Writer.hist_len - 11);
1278 try expect(win.lookahead().len == 100);1277 try expect(win.lookahead().len == 100);
1279 try expect(win.tokensBuffer() == null);1278 try expect(win.tokensBuffer() == null);
1280}1279}
lib/std/compress/flate/Decompress.zig+10-15
...@@ -23,6 +23,7 @@ const Container = flate.Container;...@@ -23,6 +23,7 @@ const Container = flate.Container;
23const Token = @import("Token.zig");23const Token = @import("Token.zig");
24const testing = std.testing;24const testing = std.testing;
25const Decompress = @This();25const Decompress = @This();
26const Writer = std.io.Writer;
2627
27input: *std.io.Reader,28input: *std.io.Reader,
28// Hashes, produces checksum, of uncompressed data for gzip/zlib footer.29// Hashes, produces checksum, of uncompressed data for gzip/zlib footer.
...@@ -141,7 +142,7 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {...@@ -141,7 +142,7 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {
141142
142pub fn read(143pub fn read(
143 context: ?*anyopaque,144 context: ?*anyopaque,
144 bw: *std.io.BufferedWriter,145 bw: *Writer,
145 limit: std.io.Limit,146 limit: std.io.Limit,
146) std.io.Reader.StreamError!usize {147) std.io.Reader.StreamError!usize {
147 const d: *Decompress = @alignCast(@ptrCast(context));148 const d: *Decompress = @alignCast(@ptrCast(context));
...@@ -159,7 +160,7 @@ pub fn read(...@@ -159,7 +160,7 @@ pub fn read(
159160
160fn readInner(161fn readInner(
161 d: *Decompress,162 d: *Decompress,
162 bw: *std.io.BufferedWriter,163 bw: *Writer,
163 limit: std.io.Limit,164 limit: std.io.Limit,
164) (Error || error{ WriteFailed, EndOfStream })!usize {165) (Error || error{ WriteFailed, EndOfStream })!usize {
165 const in = d.input;166 const in = d.input;
...@@ -347,7 +348,7 @@ fn readInner(...@@ -347,7 +348,7 @@ fn readInner(
347348
348/// Write match (back-reference to the same data slice) starting at `distance`349/// Write match (back-reference to the same data slice) starting at `distance`
349/// back from current write position, and `length` of bytes.350/// back from current write position, and `length` of bytes.
350fn writeMatch(bw: *std.io.BufferedWriter, length: u16, distance: u16) !void {351fn writeMatch(bw: *Writer, length: u16, distance: u16) !void {
351 _ = bw;352 _ = bw;
352 _ = length;353 _ = length;
353 _ = distance;354 _ = distance;
...@@ -727,8 +728,7 @@ test "decompress" {...@@ -727,8 +728,7 @@ test "decompress" {
727 },728 },
728 };729 };
729 for (cases) |c| {730 for (cases) |c| {
730 var fb: std.io.Reader = undefined;731 var fb: std.io.Reader = .fixed(c.in);
731 fb.initFixed(@constCast(c.in));
732 var aw: std.io.AllocatingWriter = undefined;732 var aw: std.io.AllocatingWriter = undefined;
733 aw.init(testing.allocator);733 aw.init(testing.allocator);
734 defer aw.deinit();734 defer aw.deinit();
...@@ -788,8 +788,7 @@ test "gzip decompress" {...@@ -788,8 +788,7 @@ test "gzip decompress" {
788 },788 },
789 };789 };
790 for (cases) |c| {790 for (cases) |c| {
791 var fb: std.io.Reader = undefined;791 var fb: std.io.Reader = .fixed(c.in);
792 fb.initFixed(@constCast(c.in));
793 var aw: std.io.AllocatingWriter = undefined;792 var aw: std.io.AllocatingWriter = undefined;
794 aw.init(testing.allocator);793 aw.init(testing.allocator);
795 defer aw.deinit();794 defer aw.deinit();
...@@ -818,8 +817,7 @@ test "zlib decompress" {...@@ -818,8 +817,7 @@ test "zlib decompress" {
818 },817 },
819 };818 };
820 for (cases) |c| {819 for (cases) |c| {
821 var fb: std.io.Reader = undefined;820 var fb: std.io.Reader = .fixed(c.in);
822 fb.initFixed(@constCast(c.in));
823 var aw: std.io.AllocatingWriter = undefined;821 var aw: std.io.AllocatingWriter = undefined;
824 aw.init(testing.allocator);822 aw.init(testing.allocator);
825 defer aw.deinit();823 defer aw.deinit();
...@@ -880,8 +878,7 @@ test "fuzzing tests" {...@@ -880,8 +878,7 @@ test "fuzzing tests" {
880 };878 };
881879
882 inline for (cases, 0..) |c, case_no| {880 inline for (cases, 0..) |c, case_no| {
883 var in: std.io.Reader = undefined;881 var in: std.io.Reader = .fixed(@embedFile("testdata/fuzz/" ++ c.input ++ ".input"));
884 in.initFixed(@constCast(@embedFile("testdata/fuzz/" ++ c.input ++ ".input")));
885 var aw: std.io.AllocatingWriter = undefined;882 var aw: std.io.AllocatingWriter = undefined;
886 aw.init(testing.allocator);883 aw.init(testing.allocator);
887 defer aw.deinit();884 defer aw.deinit();
...@@ -903,8 +900,7 @@ test "bug 18966" {...@@ -903,8 +900,7 @@ test "bug 18966" {
903 const input = @embedFile("testdata/fuzz/bug_18966.input");900 const input = @embedFile("testdata/fuzz/bug_18966.input");
904 const expect = @embedFile("testdata/fuzz/bug_18966.expect");901 const expect = @embedFile("testdata/fuzz/bug_18966.expect");
905902
906 var in: std.io.Reader = undefined;903 var in: std.io.Reader = .fixed(input);
907 in.initFixed(@constCast(input));
908 var aw: std.io.AllocatingWriter = undefined;904 var aw: std.io.AllocatingWriter = undefined;
909 aw.init(testing.allocator);905 aw.init(testing.allocator);
910 defer aw.deinit();906 defer aw.deinit();
...@@ -921,8 +917,7 @@ test "reading into empty buffer" {...@@ -921,8 +917,7 @@ test "reading into empty buffer" {
921 0b0000_0001, 0b0000_1100, 0x00, 0b1111_0011, 0xff, // deflate fixed buffer header len, nlen917 0b0000_0001, 0b0000_1100, 0x00, 0b1111_0011, 0xff, // deflate fixed buffer header len, nlen
922 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0x0a, // non compressed data918 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0x0a, // non compressed data
923 };919 };
924 var in: std.io.Reader = undefined;920 var in: std.io.Reader = .fixed(input);
925 in.initFixed(@constCast(input));
926 var decomp: Decompress = .init(&in, .raw);921 var decomp: Decompress = .init(&in, .raw);
927 var decompress_br = decomp.readable(&.{});922 var decompress_br = decomp.readable(&.{});
928 var buf: [0]u8 = undefined;923 var buf: [0]u8 = undefined;
lib/std/compress/lzma.zig+11-12
...@@ -6,6 +6,7 @@ const Allocator = std.mem.Allocator;...@@ -6,6 +6,7 @@ const Allocator = std.mem.Allocator;
6const testing = std.testing;6const testing = std.testing;
7const expectEqualSlices = std.testing.expectEqualSlices;7const expectEqualSlices = std.testing.expectEqualSlices;
8const expectError = std.testing.expectError;8const expectError = std.testing.expectError;
9const Writer = std.io.Writer;
910
10pub const RangeDecoder = struct {11pub const RangeDecoder = struct {
11 range: u32,12 range: u32,
...@@ -320,7 +321,7 @@ pub const Decode = struct {...@@ -320,7 +321,7 @@ pub const Decode = struct {
320 self: *Decode,321 self: *Decode,
321 allocator: Allocator,322 allocator: Allocator,
322 br: *std.io.Reader,323 br: *std.io.Reader,
323 bw: *std.io.BufferedWriter,324 bw: *Writer,
324 buffer: anytype,325 buffer: anytype,
325 decoder: *RangeDecoder,326 decoder: *RangeDecoder,
326 bytes_read: *usize,327 bytes_read: *usize,
...@@ -417,7 +418,7 @@ pub const Decode = struct {...@@ -417,7 +418,7 @@ pub const Decode = struct {
417 self: *Decode,418 self: *Decode,
418 allocator: Allocator,419 allocator: Allocator,
419 br: *std.io.Reader,420 br: *std.io.Reader,
420 bw: *std.io.BufferedWriter,421 bw: *Writer,
421 buffer: anytype,422 buffer: anytype,
422 decoder: *RangeDecoder,423 decoder: *RangeDecoder,
423 bytes_read: *usize,424 bytes_read: *usize,
...@@ -429,7 +430,7 @@ pub const Decode = struct {...@@ -429,7 +430,7 @@ pub const Decode = struct {
429 self: *Decode,430 self: *Decode,
430 allocator: Allocator,431 allocator: Allocator,
431 br: *std.io.Reader,432 br: *std.io.Reader,
432 bw: *std.io.BufferedWriter,433 bw: *Writer,
433 buffer: anytype,434 buffer: anytype,
434 decoder: *RangeDecoder,435 decoder: *RangeDecoder,
435 bytes_read: *usize,436 bytes_read: *usize,
...@@ -667,8 +668,8 @@ const LzCircularBuffer = struct {...@@ -667,8 +668,8 @@ const LzCircularBuffer = struct {
667 self: *Self,668 self: *Self,
668 allocator: Allocator,669 allocator: Allocator,
669 lit: u8,670 lit: u8,
670 bw: *std.io.BufferedWriter,671 bw: *Writer,
671 ) std.io.Writer.Error!void {672 ) Writer.Error!void {
672 try self.set(allocator, self.cursor, lit);673 try self.set(allocator, self.cursor, lit);
673 self.cursor += 1;674 self.cursor += 1;
674 self.len += 1;675 self.len += 1;
...@@ -686,8 +687,8 @@ const LzCircularBuffer = struct {...@@ -686,8 +687,8 @@ const LzCircularBuffer = struct {
686 allocator: Allocator,687 allocator: Allocator,
687 len: usize,688 len: usize,
688 dist: usize,689 dist: usize,
689 bw: *std.io.BufferedWriter,690 bw: *Writer,
690 ) std.io.Writer.Error!void {691 ) Writer.Error!void {
691 if (dist > self.dict_size or dist > self.len) {692 if (dist > self.dict_size or dist > self.len) {
692 return error.CorruptInput;693 return error.CorruptInput;
693 }694 }
...@@ -704,7 +705,7 @@ const LzCircularBuffer = struct {...@@ -704,7 +705,7 @@ const LzCircularBuffer = struct {
704 }705 }
705 }706 }
706707
707 pub fn finish(self: *Self, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {708 pub fn finish(self: *Self, bw: *Writer) Writer.Error!void {
708 if (self.cursor > 0) {709 if (self.cursor > 0) {
709 try bw.writeAll(self.buf.items[0..self.cursor]);710 try bw.writeAll(self.buf.items[0..self.cursor]);
710 self.cursor = 0;711 self.cursor = 0;
...@@ -839,8 +840,7 @@ test "Vec2D get addition overflow" {...@@ -839,8 +840,7 @@ test "Vec2D get addition overflow" {
839840
840fn testDecompress(compressed: []const u8) ![]u8 {841fn testDecompress(compressed: []const u8) ![]u8 {
841 const allocator = std.testing.allocator;842 const allocator = std.testing.allocator;
842 var br: std.io.Reader = undefined;843 var br: std.io.Reader = .fixed(compressed);
843 br.initFixed(compressed);
844 var decompressor = try Decompress.initOptions(allocator, &br, .{});844 var decompressor = try Decompress.initOptions(allocator, &br, .{});
845 defer decompressor.deinit();845 defer decompressor.deinit();
846 const reader = decompressor.reader();846 const reader = decompressor.reader();
...@@ -927,8 +927,7 @@ test "too small uncompressed size in header" {...@@ -927,8 +927,7 @@ test "too small uncompressed size in header" {
927927
928test "reading one byte" {928test "reading one byte" {
929 const compressed = @embedFile("testdata/good-known_size-with_eopm.lzma");929 const compressed = @embedFile("testdata/good-known_size-with_eopm.lzma");
930 var br: std.io.Reader = undefined;930 var br: std.io.Reader = .fixed(compressed);
931 br.initFixed(compressed);
932 var decompressor = try Decompress.initOptions(std.testing.allocator, &br, .{});931 var decompressor = try Decompress.initOptions(std.testing.allocator, &br, .{});
933 defer decompressor.deinit();932 defer decompressor.deinit();
934 var buffer = [1]u8{0};933 var buffer = [1]u8{0};
lib/std/compress/lzma2.zig+6-6
...@@ -1,8 +1,9 @@...@@ -1,8 +1,9 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const Allocator = std.mem.Allocator;2const Allocator = std.mem.Allocator;
3const lzma = std.compress.lzma;3const lzma = std.compress.lzma;
4const Writer = std.io.Writer;
45
5pub fn decompress(gpa: Allocator, reader: *std.io.Reader, writer: *std.io.BufferedWriter) std.io.Reader.StreamError!void {6pub fn decompress(gpa: Allocator, reader: *std.io.Reader, writer: *Writer) std.io.Reader.StreamError!void {
6 var decoder = try Decode.init(gpa);7 var decoder = try Decode.init(gpa);
7 defer decoder.deinit(gpa);8 defer decoder.deinit(gpa);
8 return decoder.decompress(gpa, reader, writer);9 return decoder.decompress(gpa, reader, writer);
...@@ -34,7 +35,7 @@ pub const Decode = struct {...@@ -34,7 +35,7 @@ pub const Decode = struct {
34 self: *Decode,35 self: *Decode,
35 allocator: Allocator,36 allocator: Allocator,
36 reader: *std.io.Reader,37 reader: *std.io.Reader,
37 writer: *std.io.BufferedWriter,38 writer: *Writer,
38 ) !void {39 ) !void {
39 var accum = LzAccumBuffer.init(std.math.maxInt(usize));40 var accum = LzAccumBuffer.init(std.math.maxInt(usize));
40 defer accum.deinit(allocator);41 defer accum.deinit(allocator);
...@@ -57,7 +58,7 @@ pub const Decode = struct {...@@ -57,7 +58,7 @@ pub const Decode = struct {
57 self: *Decode,58 self: *Decode,
58 allocator: Allocator,59 allocator: Allocator,
59 br: *std.io.Reader,60 br: *std.io.Reader,
60 writer: *std.io.BufferedWriter,61 writer: *Writer,
61 accum: *LzAccumBuffer,62 accum: *LzAccumBuffer,
62 status: u8,63 status: u8,
63 ) !void {64 ) !void {
...@@ -150,7 +151,7 @@ pub const Decode = struct {...@@ -150,7 +151,7 @@ pub const Decode = struct {
150 fn parseUncompressed(151 fn parseUncompressed(
151 allocator: Allocator,152 allocator: Allocator,
152 reader: *std.io.Reader,153 reader: *std.io.Reader,
153 writer: *std.io.BufferedWriter,154 writer: *Writer,
154 accum: *LzAccumBuffer,155 accum: *LzAccumBuffer,
155 reset_dict: bool,156 reset_dict: bool,
156 ) !void {157 ) !void {
...@@ -276,8 +277,7 @@ test decompress {...@@ -276,8 +277,7 @@ test decompress {
276 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02,277 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02,
277 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00,278 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00,
278 };279 };
279 var stream: std.io.Reader = undefined;280 var stream: std.io.Reader = .fixed(&compressed);
280 stream.initFixed(&compressed);
281 var decomp: std.io.AllocatingWriter = undefined;281 var decomp: std.io.AllocatingWriter = undefined;
282 const decomp_bw = decomp.init(std.testing.allocator);282 const decomp_bw = decomp.init(std.testing.allocator);
283 defer decomp.deinit();283 defer decomp.deinit();
lib/std/compress/zstd/Decompress.zig+5-6
...@@ -3,8 +3,8 @@ const std = @import("std");...@@ -3,8 +3,8 @@ const std = @import("std");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const Reader = std.io.Reader;4const Reader = std.io.Reader;
5const Limit = std.io.Limit;5const Limit = std.io.Limit;
6const BufferedWriter = std.io.BufferedWriter;
7const zstd = @import("../zstd.zig");6const zstd = @import("../zstd.zig");
7const Writer = std.io.Writer;
88
9input: *Reader,9input: *Reader,
10state: State,10state: State,
...@@ -77,7 +77,7 @@ pub fn reader(self: *Decompress) Reader {...@@ -77,7 +77,7 @@ pub fn reader(self: *Decompress) Reader {
77 };77 };
78}78}
7979
80fn read(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {80fn read(context: ?*anyopaque, bw: *Writer, limit: Limit) Reader.StreamError!usize {
81 const d: *Decompress = @ptrCast(@alignCast(context));81 const d: *Decompress = @ptrCast(@alignCast(context));
82 const in = d.input;82 const in = d.input;
8383
...@@ -139,7 +139,7 @@ fn initFrame(d: *Decompress, window_size_max: usize, magic: Frame.Magic) !void {...@@ -139,7 +139,7 @@ fn initFrame(d: *Decompress, window_size_max: usize, magic: Frame.Magic) !void {
139 }139 }
140}140}
141141
142fn readInFrame(d: *Decompress, bw: *BufferedWriter, limit: Limit, state: *State.InFrame) !usize {142fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame) !usize {
143 const in = d.input;143 const in = d.input;
144144
145 const header_bytes = try in.takeArray(3);145 const header_bytes = try in.takeArray(3);
...@@ -649,8 +649,7 @@ pub const Frame = struct {...@@ -649,8 +649,7 @@ pub const Frame = struct {
649649
650 if (decode.literal_written_count + literal_length > decode.literal_header.regenerated_size)650 if (decode.literal_written_count + literal_length > decode.literal_header.regenerated_size)
651 return error.MalformedLiteralsLength;651 return error.MalformedLiteralsLength;
652 var sub_bw: BufferedWriter = undefined;652 var sub_bw: Writer = .fixed(dest[write_pos..]);
653 sub_bw.initFixed(dest[write_pos..]);
654 try decodeLiterals(decode, &sub_bw, literal_length);653 try decodeLiterals(decode, &sub_bw, literal_length);
655 decode.literal_written_count += literal_length;654 decode.literal_written_count += literal_length;
656 // This is not a @memmove; it intentionally repeats patterns655 // This is not a @memmove; it intentionally repeats patterns
...@@ -698,7 +697,7 @@ pub const Frame = struct {...@@ -698,7 +697,7 @@ pub const Frame = struct {
698 }697 }
699698
700 /// Decode `len` bytes of literals into `dest`.699 /// Decode `len` bytes of literals into `dest`.
701 fn decodeLiterals(self: *Decode, dest: *BufferedWriter, len: usize) !void {700 fn decodeLiterals(self: *Decode, dest: *Writer, len: usize) !void {
702 switch (self.literal_header.block_type) {701 switch (self.literal_header.block_type) {
703 .raw => {702 .raw => {
704 try dest.writeAll(self.literal_streams.one[self.literal_written_count..][0..len]);703 try dest.writeAll(self.literal_streams.one[self.literal_written_count..][0..len]);
lib/std/crypto/Sha1.zig+9-11
...@@ -7,6 +7,7 @@ const std = @import("../std.zig");...@@ -7,6 +7,7 @@ const std = @import("../std.zig");
7const mem = std.mem;7const mem = std.mem;
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const Writer = std.io.Writer;
1011
11pub const block_length = 64;12pub const block_length = 64;
12pub const digest_length = 20;13pub const digest_length = 20;
...@@ -252,21 +253,18 @@ pub fn round(d_s: *[5]u32, b: *const [64]u8) void {...@@ -252,21 +253,18 @@ pub fn round(d_s: *[5]u32, b: *const [64]u8) void {
252 d_s[4] +%= v[4];253 d_s[4] +%= v[4];
253}254}
254255
255pub fn writable(sha1: *Sha1, buffer: []u8) std.io.BufferedWriter {256pub fn writer(sha1: *Sha1, buffer: []u8) Writer {
256 return .{257 return .{
257 .unbuffered_writer = .{258 .context = sha1,
258 .context = sha1,259 .vtable = &.{ .drain = drain },
259 .vtable = &.{
260 .writeSplat = writeSplat,
261 .writeFile = std.io.Writer.unimplementedWriteFile,
262 },
263 },
264 .buffer = buffer,260 .buffer = buffer,
265 };261 };
266}262}
267263
268fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {264fn drain(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
269 const sha1: *Sha1 = @ptrCast(@alignCast(context));265 const sha1: *Sha1 = @ptrCast(@alignCast(w.context));
266 sha1.update(w.buffered());
267 w.end = 0;
270 const start_total = sha1.total_len;268 const start_total = sha1.total_len;
271 if (sha1.buf_end == 0) {269 if (sha1.buf_end == 0) {
272 try writeSplatAligned(sha1, data, splat);270 try writeSplatAligned(sha1, data, splat);
...@@ -299,7 +297,7 @@ fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std....@@ -299,7 +297,7 @@ fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.
299 return @intCast(sha1.total_len - start_total);297 return @intCast(sha1.total_len - start_total);
300}298}
301299
302fn writeSplatAligned(sha1: *Sha1, data: []const []const u8, splat: usize) std.io.Writer.Error!void {300fn writeSplatAligned(sha1: *Sha1, data: []const []const u8, splat: usize) Writer.Error!void {
303 assert(sha1.buf_end == 0);301 assert(sha1.buf_end == 0);
304 for (data[0 .. data.len - 1]) |slice| {302 for (data[0 .. data.len - 1]) |slice| {
305 var off: usize = 0;303 var off: usize = 0;
lib/std/crypto/codecs/asn1.zig+4-1
...@@ -1,5 +1,8 @@...@@ -1,5 +1,8 @@
1//! ASN.1 types for public consumption.1//! ASN.1 types for public consumption.
2
2const std = @import("std");3const std = @import("std");
4const Writer = std.io.Writer;
5
3pub const der = @import("./asn1/der.zig");6pub const der = @import("./asn1/der.zig");
4pub const Oid = @import("./asn1/Oid.zig");7pub const Oid = @import("./asn1/Oid.zig");
58
...@@ -90,7 +93,7 @@ pub const Tag = struct {...@@ -90,7 +93,7 @@ pub const Tag = struct {
90 };93 };
91 }94 }
9295
93 pub fn encode(self: Tag, writer: *std.io.BufferedWriter) std.io.Writer.Error!void {96 pub fn encode(self: Tag, writer: *Writer) Writer.Error!void {
94 var tag1: FirstTag = .{97 var tag1: FirstTag = .{
95 .number = undefined,98 .number = undefined,
96 .constructed = self.constructed,99 .constructed = self.constructed,
lib/std/crypto/codecs/asn1/Oid.zig+5-6
...@@ -9,7 +9,7 @@ pub const EncodeError = error{...@@ -9,7 +9,7 @@ pub const EncodeError = error{
9 MissingPrefix,9 MissingPrefix,
10};10};
1111
12pub fn encode(dot_notation: []const u8, out: *std.io.BufferedWriter) EncodeError!void {12pub fn encode(dot_notation: []const u8, out: *Writer) EncodeError!void {
13 var split = std.mem.splitScalar(u8, dot_notation, '.');13 var split = std.mem.splitScalar(u8, dot_notation, '.');
14 const first_str = split.next() orelse return error.MissingPrefix;14 const first_str = split.next() orelse return error.MissingPrefix;
15 const second_str = split.next() orelse return error.MissingPrefix;15 const second_str = split.next() orelse return error.MissingPrefix;
...@@ -41,8 +41,7 @@ pub fn encode(dot_notation: []const u8, out: *std.io.BufferedWriter) EncodeError...@@ -41,8 +41,7 @@ pub fn encode(dot_notation: []const u8, out: *std.io.BufferedWriter) EncodeError
41pub const InitError = std.fmt.ParseIntError || error{ MissingPrefix, BufferTooSmall };41pub const InitError = std.fmt.ParseIntError || error{ MissingPrefix, BufferTooSmall };
4242
43pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {43pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {
44 var bw: std.io.BufferedWriter = undefined;44 var bw: Writer = .fixed(out);
45 bw.initFixed(out);
46 encode(dot_notation, &bw) catch |err| switch (err) {45 encode(dot_notation, &bw) catch |err| switch (err) {
47 error.WriteFailed => return error.BufferTooSmall,46 error.WriteFailed => return error.BufferTooSmall,
48 else => |e| return e,47 else => |e| return e,
...@@ -58,7 +57,7 @@ test fromDot {...@@ -58,7 +57,7 @@ test fromDot {
58 }57 }
59}58}
6059
61pub fn toDot(self: Oid, writer: *std.io.BufferedWriter) std.io.Writer.Error!void {60pub fn toDot(self: Oid, writer: *Writer) Writer.Error!void {
62 const encoded = self.encoded;61 const encoded = self.encoded;
63 const first = @divTrunc(encoded[0], 40);62 const first = @divTrunc(encoded[0], 40);
64 const second = encoded[0] - first * 40;63 const second = encoded[0] - first * 40;
...@@ -90,8 +89,7 @@ test toDot {...@@ -90,8 +89,7 @@ test toDot {
90 var buf: [256]u8 = undefined;89 var buf: [256]u8 = undefined;
9190
92 for (test_cases) |t| {91 for (test_cases) |t| {
93 var bw: std.io.BufferedWriter = undefined;92 var bw: Writer = .fixed(&buf);
94 bw.initFixed(&buf);
95 try toDot(Oid{ .encoded = t.encoded }, &bw);93 try toDot(Oid{ .encoded = t.encoded }, &bw);
96 try std.testing.expectEqualStrings(t.dot_notation, bw.getWritten());94 try std.testing.expectEqualStrings(t.dot_notation, bw.getWritten());
97 }95 }
...@@ -219,3 +217,4 @@ const encoding_base = 128;...@@ -219,3 +217,4 @@ const encoding_base = 128;
219const Allocator = std.mem.Allocator;217const Allocator = std.mem.Allocator;
220const der = @import("der.zig");218const der = @import("der.zig");
221const asn1 = @import("../asn1.zig");219const asn1 = @import("../asn1.zig");
220const Writer = std.io.Writer;
lib/std/crypto/ecdsa.zig+2-2
...@@ -6,6 +6,7 @@ const io = std.io;...@@ -6,6 +6,7 @@ const io = std.io;
6const mem = std.mem;6const mem = std.mem;
7const sha3 = crypto.hash.sha3;7const sha3 = crypto.hash.sha3;
8const testing = std.testing;8const testing = std.testing;
9const Writer = std.io.Writer;
910
10const EncodingError = crypto.errors.EncodingError;11const EncodingError = crypto.errors.EncodingError;
11const IdentityElementError = crypto.errors.IdentityElementError;12const IdentityElementError = crypto.errors.IdentityElementError;
...@@ -135,8 +136,7 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {...@@ -135,8 +136,7 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
135 /// The maximum length of the DER encoding is der_encoded_length_max.136 /// The maximum length of the DER encoding is der_encoded_length_max.
136 /// The function returns a slice, that can be shorter than der_encoded_length_max.137 /// The function returns a slice, that can be shorter than der_encoded_length_max.
137 pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8 {138 pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8 {
138 var w: std.io.BufferedWriter = undefined;139 var w: Writer = .fixed(buf);
139 w.initFixed(buf);
140 const r_len = @as(u8, @intCast(sig.r.len + (sig.r[0] >> 7)));140 const r_len = @as(u8, @intCast(sig.r.len + (sig.r[0] >> 7)));
141 const s_len = @as(u8, @intCast(sig.s.len + (sig.s[0] >> 7)));141 const s_len = @as(u8, @intCast(sig.s.len + (sig.s[0] >> 7)));
142 const seq_len = @as(u8, @intCast(2 + r_len + 2 + s_len));142 const seq_len = @as(u8, @intCast(2 + r_len + 2 + s_len));
lib/std/crypto/phc_encoding.zig+6-6
...@@ -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,16 +189,15 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult...@@ -188,16 +189,15 @@ 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 bw: std.io.BufferedWriter = undefined;192 var w: Writer = .fixed(str);
192 bw.initFixed(str);193 try serializeTo(params, &w);
193 try serializeTo(params, &bw);194 return w.buffered();
194 return bw.getWritten();
195}195}
196196
197/// Compute the number of bytes required to serialize `params`197/// Compute the number of bytes required to serialize `params`
198pub fn calcSize(params: anytype) usize {198pub fn calcSize(params: anytype) usize {
199 var trash: [128]u8 = undefined;199 var trash: [128]u8 = undefined;
200 var bw: std.io.BufferedWriter = .{200 var bw: Writer = .{
201 .unbuffered_writer = .discarding,201 .unbuffered_writer = .discarding,
202 .buffer = &trash,202 .buffer = &trash,
203 };203 };
...@@ -205,7 +205,7 @@ pub fn calcSize(params: anytype) usize {...@@ -205,7 +205,7 @@ pub fn calcSize(params: anytype) usize {
205 return bw.count;205 return bw.count;
206}206}
207207
208fn serializeTo(params: anytype, out: *std.io.BufferedWriter) !void {208fn serializeTo(params: anytype, out: *Writer) !void {
209 const HashResult = @TypeOf(params);209 const HashResult = @TypeOf(params);
210210
211 if (@hasField(HashResult, version_param_name)) {211 if (@hasField(HashResult, version_param_name)) {
lib/std/crypto/scrypt.zig+8-11
...@@ -10,6 +10,7 @@ const math = std.math;...@@ -10,6 +10,7 @@ const math = std.math;
10const mem = std.mem;10const mem = std.mem;
11const meta = std.meta;11const meta = std.meta;
12const pwhash = crypto.pwhash;12const pwhash = crypto.pwhash;
13const Writer = std.io.Writer;
1314
14const phc_format = @import("phc_encoding.zig");15const phc_format = @import("phc_encoding.zig");
1516
...@@ -304,26 +305,22 @@ const crypt_format = struct {...@@ -304,26 +305,22 @@ const crypt_format = struct {
304305
305 /// Serialize parameters into a string in modular crypt format.306 /// Serialize parameters into a string in modular crypt format.
306 pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {307 pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {
307 var bw: std.io.BufferedWriter = undefined;308 var w: Writer = .fixed(str);
308 bw.initFixed(str);309 try serializeTo(params, &w);
309 try serializeTo(params, &bw);310 return w.getWritten();
310 return bw.getWritten();
311 }311 }
312312
313 /// Compute the number of bytes required to serialize `params`313 /// Compute the number of bytes required to serialize `params`
314 pub fn calcSize(params: anytype) usize {314 pub fn calcSize(params: anytype) usize {
315 var trash: [64]u8 = undefined;315 var trash: [64]u8 = undefined;
316 var bw: std.io.BufferedWriter = .{316 var w: std.io.Writer = .discarding(&trash);
317 .unbuffered_writer = .discarding,317 serializeTo(params, &w) catch |err| switch (err) {
318 .buffer = &trash,
319 };
320 serializeTo(params, &bw) catch |err| switch (err) {
321 error.WriteFailed => unreachable,318 error.WriteFailed => unreachable,
322 };319 };
323 return bw.count;320 return w.count;
324 }321 }
325322
326 fn serializeTo(params: anytype, out: *std.io.BufferedWriter) !void {323 fn serializeTo(params: anytype, out: *Writer) !void {
327 var header: [14]u8 = undefined;324 var header: [14]u8 = undefined;
328 header[0..3].* = prefix.*;325 header[0..3].* = prefix.*;
329 Codec.intEncode(header[3..4], params.ln);326 Codec.intEncode(header[3..4], params.ln);
lib/std/crypto/sha2.zig+4-3
...@@ -18,6 +18,7 @@ const builtin = @import("builtin");...@@ -18,6 +18,7 @@ const builtin = @import("builtin");
18const mem = std.mem;18const mem = std.mem;
19const math = std.math;19const math = std.math;
20const htest = @import("test.zig");20const htest = @import("test.zig");
21const Writer = std.io.Writer;
2122
22pub const Sha224 = Sha2x32(iv224, 224);23pub const Sha224 = Sha2x32(iv224, 224);
23pub const Sha256 = Sha2x32(iv256, 256);24pub const Sha256 = Sha2x32(iv256, 256);
...@@ -382,20 +383,20 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {...@@ -382,20 +383,20 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {
382 for (&d.s, v) |*dv, vv| dv.* +%= vv;383 for (&d.s, v) |*dv, vv| dv.* +%= vv;
383 }384 }
384385
385 pub fn writable(this: *@This(), buffer: []u8) std.io.BufferedWriter {386 pub fn writable(this: *@This(), buffer: []u8) Writer {
386 return .{387 return .{
387 .unbuffered_writer = .{388 .unbuffered_writer = .{
388 .context = this,389 .context = this,
389 .vtable = &.{390 .vtable = &.{
390 .writeSplat = writeSplat,391 .writeSplat = writeSplat,
391 .writeFile = std.io.Writer.unimplementedWriteFile,392 .writeFile = Writer.unimplementedWriteFile,
392 },393 },
393 },394 },
394 .buffer = buffer,395 .buffer = buffer,
395 };396 };
396 }397 }
397398
398 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {399 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {
399 const this: *@This() = @ptrCast(@alignCast(context));400 const this: *@This() = @ptrCast(@alignCast(context));
400 const start_total = this.total_len;401 const start_total = this.total_len;
401 for (data[0 .. data.len - 1]) |slice| this.update(slice);402 for (data[0 .. data.len - 1]) |slice| this.update(slice);
lib/std/crypto/tls/Client.zig+5-5
...@@ -25,7 +25,7 @@ input: *std.io.Reader,...@@ -25,7 +25,7 @@ input: *std.io.Reader,
2525
26/// The encrypted stream from the client to the server. Bytes are pushed here26/// The encrypted stream from the client to the server. Bytes are pushed here
27/// via `writer`.27/// via `writer`.
28output: *std.io.BufferedWriter,28output: *Writer,
2929
30/// Populated when `error.TlsAlert` is returned.30/// Populated when `error.TlsAlert` is returned.
31alert: ?tls.Alert = null,31alert: ?tls.Alert = null,
...@@ -72,7 +72,7 @@ pub const SslKeyLog = struct {...@@ -72,7 +72,7 @@ pub const SslKeyLog = struct {
72 client_key_seq: u64,72 client_key_seq: u64,
73 server_key_seq: u64,73 server_key_seq: u64,
74 client_random: [32]u8,74 client_random: [32]u8,
75 writer: *std.io.BufferedWriter,75 writer: *Writer,
7676
77 fn clientCounter(key_log: *@This()) u64 {77 fn clientCounter(key_log: *@This()) u64 {
78 defer key_log.client_key_seq += 1;78 defer key_log.client_key_seq += 1;
...@@ -176,7 +176,7 @@ const InitError = error{...@@ -176,7 +176,7 @@ const InitError = error{
176pub fn init(176pub fn init(
177 client: *Client,177 client: *Client,
178 input: *std.io.Reader,178 input: *std.io.Reader,
179 output: *std.io.BufferedWriter,179 output: *Writer,
180 options: Options,180 options: Options,
181) InitError!void {181) InitError!void {
182 assert(input.buffer.len >= min_buffer_len);182 assert(input.buffer.len >= min_buffer_len);
...@@ -1043,7 +1043,7 @@ pub fn eof(c: Client) bool {...@@ -1043,7 +1043,7 @@ pub fn eof(c: Client) bool {
1043 return c.received_close_notify;1043 return c.received_close_notify;
1044}1044}
10451045
1046fn read(context: ?*anyopaque, bw: *std.io.BufferedWriter, limit: std.io.Limit) Reader.StreamError!usize {1046fn read(context: ?*anyopaque, bw: *Writer, limit: std.io.Limit) Reader.StreamError!usize {
1047 const c: *Client = @ptrCast(@alignCast(context));1047 const c: *Client = @ptrCast(@alignCast(context));
1048 if (c.eof()) return error.EndOfStream;1048 if (c.eof()) return error.EndOfStream;
1049 const input = c.input;1049 const input = c.input;
...@@ -1226,7 +1226,7 @@ fn failRead(c: *Client, err: ReadError) error{ReadFailed} {...@@ -1226,7 +1226,7 @@ fn failRead(c: *Client, err: ReadError) error{ReadFailed} {
1226 return error.ReadFailed;1226 return error.ReadFailed;
1227}1227}
12281228
1229fn logSecrets(bw: *std.io.BufferedWriter, context: anytype, secrets: anytype) void {1229fn logSecrets(bw: *Writer, context: anytype, secrets: anytype) void {
1230 inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| bw.print("{s}" ++1230 inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| bw.print("{s}" ++
1231 (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++1231 (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++
1232 (if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{1232 (if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{
lib/std/debug.zig+18-18
...@@ -12,6 +12,7 @@ const windows = std.os.windows;...@@ -12,6 +12,7 @@ const windows = std.os.windows;
12const native_arch = builtin.cpu.arch;12const native_arch = builtin.cpu.arch;
13const native_os = builtin.os.tag;13const native_os = builtin.os.tag;
14const native_endian = native_arch.endian();14const native_endian = native_arch.endian();
15const Writer = std.io.Writer;
1516
16pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");17pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
17pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");18pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
...@@ -208,9 +209,9 @@ pub fn unlockStdErr() void {...@@ -208,9 +209,9 @@ pub fn unlockStdErr() void {
208///209///
209/// During the lock, any `std.Progress` information is cleared from the terminal.210/// During the lock, any `std.Progress` information is cleared from the terminal.
210///211///
211/// Returns a `std.io.BufferedWriter` with empty buffer, meaning that it is212/// Returns a `Writer` with empty buffer, meaning that it is
212/// in fact unbuffered and does not need to be flushed.213/// in fact unbuffered and does not need to be flushed.
213pub fn lockStderrWriter(buffer: []u8) *std.io.BufferedWriter {214pub fn lockStderrWriter(buffer: []u8) *Writer {
214 return std.Progress.lockStderrWriter(buffer);215 return std.Progress.lockStderrWriter(buffer);
215}216}
216217
...@@ -252,7 +253,7 @@ pub fn dumpHex(bytes: []const u8) void {...@@ -252,7 +253,7 @@ pub fn dumpHex(bytes: []const u8) void {
252}253}
253254
254/// Prints a hexadecimal view of the bytes, returning any error that occurs.255/// Prints a hexadecimal view of the bytes, returning any error that occurs.
255pub fn dumpHexFallible(bw: *std.io.BufferedWriter, ttyconf: std.io.tty.Config, bytes: []const u8) !void {256pub fn dumpHexFallible(bw: *Writer, ttyconf: std.io.tty.Config, bytes: []const u8) !void {
256 var chunks = mem.window(u8, bytes, 16, 16);257 var chunks = mem.window(u8, bytes, 16, 16);
257 while (chunks.next()) |window| {258 while (chunks.next()) |window| {
258 // 1. Print the address.259 // 1. Print the address.
...@@ -329,7 +330,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {...@@ -329,7 +330,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
329}330}
330331
331/// Prints the current stack trace to the provided writer.332/// Prints the current stack trace to the provided writer.
332pub fn dumpCurrentStackTraceToWriter(start_addr: ?usize, writer: *std.io.BufferedWriter) !void {333pub fn dumpCurrentStackTraceToWriter(start_addr: ?usize, writer: *Writer) !void {
333 if (builtin.target.cpu.arch.isWasm()) {334 if (builtin.target.cpu.arch.isWasm()) {
334 if (native_os == .wasi) {335 if (native_os == .wasi) {
335 try writer.writeAll("Unable to dump stack trace: not implemented for Wasm\n");336 try writer.writeAll("Unable to dump stack trace: not implemented for Wasm\n");
...@@ -413,7 +414,7 @@ pub inline fn getContext(context: *ThreadContext) bool {...@@ -413,7 +414,7 @@ pub inline fn getContext(context: *ThreadContext) bool {
413/// Tries to print the stack trace starting from the supplied base pointer to stderr,414/// Tries to print the stack trace starting from the supplied base pointer to stderr,
414/// unbuffered, and ignores any error returned.415/// unbuffered, and ignores any error returned.
415/// TODO multithreaded awareness416/// TODO multithreaded awareness
416pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *std.io.BufferedWriter) void {417pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void {
417 nosuspend {418 nosuspend {
418 if (builtin.target.cpu.arch.isWasm()) {419 if (builtin.target.cpu.arch.isWasm()) {
419 if (native_os == .wasi) {420 if (native_os == .wasi) {
...@@ -584,8 +585,7 @@ pub fn panicExtra(...@@ -584,8 +585,7 @@ pub fn panicExtra(
584 const size = 0x1000;585 const size = 0x1000;
585 const trunc_msg = "(msg truncated)";586 const trunc_msg = "(msg truncated)";
586 var buf: [size + trunc_msg.len]u8 = undefined;587 var buf: [size + trunc_msg.len]u8 = undefined;
587 var bw: std.io.BufferedWriter = undefined;588 var bw: Writer = .fixed(buf[0..size]);
588 bw.initFixed(buf[0..size]);
589 // a minor annoyance with this is that it will result in the NoSpaceLeft589 // a minor annoyance with this is that it will result in the NoSpaceLeft
590 // error being part of the @panic stack trace (but that error should590 // error being part of the @panic stack trace (but that error should
591 // only happen rarely)591 // only happen rarely)
...@@ -733,7 +733,7 @@ fn waitForOtherThreadToFinishPanicking() void {...@@ -733,7 +733,7 @@ fn waitForOtherThreadToFinishPanicking() void {
733733
734pub fn writeStackTrace(734pub fn writeStackTrace(
735 stack_trace: std.builtin.StackTrace,735 stack_trace: std.builtin.StackTrace,
736 writer: *std.io.BufferedWriter,736 writer: *Writer,
737 debug_info: *SelfInfo,737 debug_info: *SelfInfo,
738 tty_config: io.tty.Config,738 tty_config: io.tty.Config,
739) !void {739) !void {
...@@ -964,7 +964,7 @@ pub const StackIterator = struct {...@@ -964,7 +964,7 @@ pub const StackIterator = struct {
964};964};
965965
966pub fn writeCurrentStackTrace(966pub fn writeCurrentStackTrace(
967 writer: *std.io.BufferedWriter,967 writer: *Writer,
968 debug_info: *SelfInfo,968 debug_info: *SelfInfo,
969 tty_config: io.tty.Config,969 tty_config: io.tty.Config,
970 start_addr: ?usize,970 start_addr: ?usize,
...@@ -1052,7 +1052,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w...@@ -1052,7 +1052,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w
1052}1052}
10531053
1054pub fn writeStackTraceWindows(1054pub fn writeStackTraceWindows(
1055 writer: *std.io.BufferedWriter,1055 writer: *Writer,
1056 debug_info: *SelfInfo,1056 debug_info: *SelfInfo,
1057 tty_config: io.tty.Config,1057 tty_config: io.tty.Config,
1058 context: *const windows.CONTEXT,1058 context: *const windows.CONTEXT,
...@@ -1072,7 +1072,7 @@ pub fn writeStackTraceWindows(...@@ -1072,7 +1072,7 @@ pub fn writeStackTraceWindows(
1072 }1072 }
1073}1073}
10741074
1075fn printUnknownSource(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, address: usize, tty_config: io.tty.Config) !void {1075fn printUnknownSource(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void {
1076 const module_name = debug_info.getModuleNameForAddress(address);1076 const module_name = debug_info.getModuleNameForAddress(address);
1077 return printLineInfo(1077 return printLineInfo(
1078 writer,1078 writer,
...@@ -1085,14 +1085,14 @@ fn printUnknownSource(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, add...@@ -1085,14 +1085,14 @@ fn printUnknownSource(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, add
1085 );1085 );
1086}1086}
10871087
1088fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, writer: *std.io.BufferedWriter, tty_config: io.tty.Config) void {1088fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, writer: *Writer, tty_config: io.tty.Config) void {
1089 if (!have_ucontext) return;1089 if (!have_ucontext) return;
1090 if (it.getLastError()) |unwind_error| {1090 if (it.getLastError()) |unwind_error| {
1091 printUnwindError(debug_info, writer, unwind_error.address, unwind_error.err, tty_config) catch {};1091 printUnwindError(debug_info, writer, unwind_error.address, unwind_error.err, tty_config) catch {};
1092 }1092 }
1093}1093}
10941094
1095fn printUnwindError(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, address: usize, err: UnwindError, tty_config: io.tty.Config) !void {1095fn printUnwindError(debug_info: *SelfInfo, writer: *Writer, address: usize, err: UnwindError, tty_config: io.tty.Config) !void {
1096 const module_name = debug_info.getModuleNameForAddress(address) orelse "???";1096 const module_name = debug_info.getModuleNameForAddress(address) orelse "???";
1097 try tty_config.setColor(writer, .dim);1097 try tty_config.setColor(writer, .dim);
1098 if (err == error.MissingDebugInfo) {1098 if (err == error.MissingDebugInfo) {
...@@ -1103,7 +1103,7 @@ fn printUnwindError(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, addre...@@ -1103,7 +1103,7 @@ fn printUnwindError(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, addre
1103 try tty_config.setColor(writer, .reset);1103 try tty_config.setColor(writer, .reset);
1104}1104}
11051105
1106pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *std.io.BufferedWriter, address: usize, tty_config: io.tty.Config) !void {1106pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void {
1107 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {1107 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
1108 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),1108 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),
1109 else => return err,1109 else => return err,
...@@ -1127,7 +1127,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *std.io.BufferedWrite...@@ -1127,7 +1127,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *std.io.BufferedWrite
1127}1127}
11281128
1129fn printLineInfo(1129fn printLineInfo(
1130 writer: *std.io.BufferedWriter,1130 writer: *Writer,
1131 source_location: ?SourceLocation,1131 source_location: ?SourceLocation,
1132 address: usize,1132 address: usize,
1133 symbol_name: []const u8,1133 symbol_name: []const u8,
...@@ -1174,7 +1174,7 @@ fn printLineInfo(...@@ -1174,7 +1174,7 @@ fn printLineInfo(
1174 }1174 }
1175}1175}
11761176
1177fn printLineFromFileAnyOs(writer: *std.io.BufferedWriter, source_location: SourceLocation) !void {1177fn printLineFromFileAnyOs(writer: *Writer, source_location: SourceLocation) !void {
1178 // Need this to always block even in async I/O mode, because this could potentially1178 // Need this to always block even in async I/O mode, because this could potentially
1179 // be called from e.g. the event loop code crashing.1179 // be called from e.g. the event loop code crashing.
1180 var f = try fs.cwd().openFile(source_location.file_name, .{});1180 var f = try fs.cwd().openFile(source_location.file_name, .{});
...@@ -1567,7 +1567,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:...@@ -1567,7 +1567,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
1567 posix.abort();1567 posix.abort();
1568}1568}
15691569
1570fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *std.io.BufferedWriter) void {1570fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *Writer) void {
1571 _ = switch (msg) {1571 _ = switch (msg) {
1572 0 => stderr.print("{s}\n", .{label.?}),1572 0 => stderr.print("{s}\n", .{label.?}),
1573 1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),1573 1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
...@@ -1699,7 +1699,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1699,7 +1699,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1699 t: @This(),1699 t: @This(),
1700 comptime fmt: []const u8,1700 comptime fmt: []const u8,
1701 options: std.fmt.FormatOptions,1701 options: std.fmt.FormatOptions,
1702 writer: *std.io.BufferedWriter,1702 writer: *Writer,
1703 ) !void {1703 ) !void {
1704 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);1704 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
1705 _ = options;1705 _ = options;
lib/std/debug/Dwarf/expression.zig+28-27
...@@ -9,6 +9,7 @@ const abi = std.debug.Dwarf.abi;...@@ -9,6 +9,7 @@ const abi = std.debug.Dwarf.abi;
9const mem = std.mem;9const mem = std.mem;
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
12const Writer = std.io.Writer;
1213
13/// Expressions can be evaluated in different contexts, each requiring its own set of inputs.14/// Expressions can be evaluated in different contexts, each requiring its own set of inputs.
14/// Callers should specify all the fields relevant to their context. If a field is required15/// Callers should specify all the fields relevant to their context. If a field is required
...@@ -826,7 +827,7 @@ pub fn Builder(comptime options: Options) type {...@@ -826,7 +827,7 @@ pub fn Builder(comptime options: Options) type {
826827
827 return struct {828 return struct {
828 /// Zero-operand instructions829 /// Zero-operand instructions
829 pub fn writeOpcode(writer: *std.io.BufferedWriter, comptime opcode: u8) !void {830 pub fn writeOpcode(writer: *Writer, comptime opcode: u8) !void {
830 if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;831 if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;
831 switch (opcode) {832 switch (opcode) {
832 OP.dup,833 OP.dup,
...@@ -867,14 +868,14 @@ pub fn Builder(comptime options: Options) type {...@@ -867,14 +868,14 @@ pub fn Builder(comptime options: Options) type {
867 }868 }
868869
869 // 2.5.1.1: Literal Encodings870 // 2.5.1.1: Literal Encodings
870 pub fn writeLiteral(writer: *std.io.BufferedWriter, literal: u8) !void {871 pub fn writeLiteral(writer: *Writer, literal: u8) !void {
871 switch (literal) {872 switch (literal) {
872 0...31 => |n| try writer.writeByte(n + OP.lit0),873 0...31 => |n| try writer.writeByte(n + OP.lit0),
873 else => return error.InvalidLiteral,874 else => return error.InvalidLiteral,
874 }875 }
875 }876 }
876877
877 pub fn writeConst(writer: *std.io.BufferedWriter, comptime T: type, value: T) !void {878 pub fn writeConst(writer: *Writer, comptime T: type, value: T) !void {
878 if (@typeInfo(T) != .int) @compileError("Constants must be integers");879 if (@typeInfo(T) != .int) @compileError("Constants must be integers");
879880
880 switch (T) {881 switch (T) {
...@@ -906,12 +907,12 @@ pub fn Builder(comptime options: Options) type {...@@ -906,12 +907,12 @@ pub fn Builder(comptime options: Options) type {
906 }907 }
907 }908 }
908909
909 pub fn writeConstx(writer: *std.io.BufferedWriter, debug_addr_offset: anytype) !void {910 pub fn writeConstx(writer: *Writer, debug_addr_offset: anytype) !void {
910 try writer.writeByte(OP.constx);911 try writer.writeByte(OP.constx);
911 try leb.writeUleb128(writer, debug_addr_offset);912 try leb.writeUleb128(writer, debug_addr_offset);
912 }913 }
913914
914 pub fn writeConstType(writer: *std.io.BufferedWriter, die_offset: anytype, value_bytes: []const u8) !void {915 pub fn writeConstType(writer: *Writer, die_offset: anytype, value_bytes: []const u8) !void {
915 if (options.call_frame_context) return error.InvalidCFAOpcode;916 if (options.call_frame_context) return error.InvalidCFAOpcode;
916 if (value_bytes.len > 0xff) return error.InvalidTypeLength;917 if (value_bytes.len > 0xff) return error.InvalidTypeLength;
917 try writer.writeByte(OP.const_type);918 try writer.writeByte(OP.const_type);
...@@ -920,36 +921,36 @@ pub fn Builder(comptime options: Options) type {...@@ -920,36 +921,36 @@ pub fn Builder(comptime options: Options) type {
920 try writer.writeAll(value_bytes);921 try writer.writeAll(value_bytes);
921 }922 }
922923
923 pub fn writeAddr(writer: *std.io.BufferedWriter, value: Address) !void {924 pub fn writeAddr(writer: *Writer, value: Address) !void {
924 try writer.writeByte(OP.addr);925 try writer.writeByte(OP.addr);
925 try writer.writeInt(Address, value, options.endian);926 try writer.writeInt(Address, value, options.endian);
926 }927 }
927928
928 pub fn writeAddrx(writer: *std.io.BufferedWriter, debug_addr_offset: anytype) !void {929 pub fn writeAddrx(writer: *Writer, debug_addr_offset: anytype) !void {
929 if (options.call_frame_context) return error.InvalidCFAOpcode;930 if (options.call_frame_context) return error.InvalidCFAOpcode;
930 try writer.writeByte(OP.addrx);931 try writer.writeByte(OP.addrx);
931 try leb.writeUleb128(writer, debug_addr_offset);932 try leb.writeUleb128(writer, debug_addr_offset);
932 }933 }
933934
934 // 2.5.1.2: Register Values935 // 2.5.1.2: Register Values
935 pub fn writeFbreg(writer: *std.io.BufferedWriter, offset: anytype) !void {936 pub fn writeFbreg(writer: *Writer, offset: anytype) !void {
936 try writer.writeByte(OP.fbreg);937 try writer.writeByte(OP.fbreg);
937 try leb.writeIleb128(writer, offset);938 try leb.writeIleb128(writer, offset);
938 }939 }
939940
940 pub fn writeBreg(writer: *std.io.BufferedWriter, register: u8, offset: anytype) !void {941 pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void {
941 if (register > 31) return error.InvalidRegister;942 if (register > 31) return error.InvalidRegister;
942 try writer.writeByte(OP.breg0 + register);943 try writer.writeByte(OP.breg0 + register);
943 try leb.writeIleb128(writer, offset);944 try leb.writeIleb128(writer, offset);
944 }945 }
945946
946 pub fn writeBregx(writer: *std.io.BufferedWriter, register: anytype, offset: anytype) !void {947 pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void {
947 try writer.writeByte(OP.bregx);948 try writer.writeByte(OP.bregx);
948 try leb.writeUleb128(writer, register);949 try leb.writeUleb128(writer, register);
949 try leb.writeIleb128(writer, offset);950 try leb.writeIleb128(writer, offset);
950 }951 }
951952
952 pub fn writeRegvalType(writer: *std.io.BufferedWriter, register: anytype, offset: anytype) !void {953 pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void {
953 if (options.call_frame_context) return error.InvalidCFAOpcode;954 if (options.call_frame_context) return error.InvalidCFAOpcode;
954 try writer.writeByte(OP.regval_type);955 try writer.writeByte(OP.regval_type);
955 try leb.writeUleb128(writer, register);956 try leb.writeUleb128(writer, register);
...@@ -957,29 +958,29 @@ pub fn Builder(comptime options: Options) type {...@@ -957,29 +958,29 @@ pub fn Builder(comptime options: Options) type {
957 }958 }
958959
959 // 2.5.1.3: Stack Operations960 // 2.5.1.3: Stack Operations
960 pub fn writePick(writer: *std.io.BufferedWriter, index: u8) !void {961 pub fn writePick(writer: *Writer, index: u8) !void {
961 try writer.writeByte(OP.pick);962 try writer.writeByte(OP.pick);
962 try writer.writeByte(index);963 try writer.writeByte(index);
963 }964 }
964965
965 pub fn writeDerefSize(writer: *std.io.BufferedWriter, size: u8) !void {966 pub fn writeDerefSize(writer: *Writer, size: u8) !void {
966 try writer.writeByte(OP.deref_size);967 try writer.writeByte(OP.deref_size);
967 try writer.writeByte(size);968 try writer.writeByte(size);
968 }969 }
969970
970 pub fn writeXDerefSize(writer: *std.io.BufferedWriter, size: u8) !void {971 pub fn writeXDerefSize(writer: *Writer, size: u8) !void {
971 try writer.writeByte(OP.xderef_size);972 try writer.writeByte(OP.xderef_size);
972 try writer.writeByte(size);973 try writer.writeByte(size);
973 }974 }
974975
975 pub fn writeDerefType(writer: *std.io.BufferedWriter, size: u8, die_offset: anytype) !void {976 pub fn writeDerefType(writer: *Writer, size: u8, die_offset: anytype) !void {
976 if (options.call_frame_context) return error.InvalidCFAOpcode;977 if (options.call_frame_context) return error.InvalidCFAOpcode;
977 try writer.writeByte(OP.deref_type);978 try writer.writeByte(OP.deref_type);
978 try writer.writeByte(size);979 try writer.writeByte(size);
979 try leb.writeUleb128(writer, die_offset);980 try leb.writeUleb128(writer, die_offset);
980 }981 }
981982
982 pub fn writeXDerefType(writer: *std.io.BufferedWriter, size: u8, die_offset: anytype) !void {983 pub fn writeXDerefType(writer: *Writer, size: u8, die_offset: anytype) !void {
983 try writer.writeByte(OP.xderef_type);984 try writer.writeByte(OP.xderef_type);
984 try writer.writeByte(size);985 try writer.writeByte(size);
985 try leb.writeUleb128(writer, die_offset);986 try leb.writeUleb128(writer, die_offset);
...@@ -987,24 +988,24 @@ pub fn Builder(comptime options: Options) type {...@@ -987,24 +988,24 @@ pub fn Builder(comptime options: Options) type {
987988
988 // 2.5.1.4: Arithmetic and Logical Operations989 // 2.5.1.4: Arithmetic and Logical Operations
989990
990 pub fn writePlusUconst(writer: *std.io.BufferedWriter, uint_value: anytype) !void {991 pub fn writePlusUconst(writer: *Writer, uint_value: anytype) !void {
991 try writer.writeByte(OP.plus_uconst);992 try writer.writeByte(OP.plus_uconst);
992 try leb.writeUleb128(writer, uint_value);993 try leb.writeUleb128(writer, uint_value);
993 }994 }
994995
995 // 2.5.1.5: Control Flow Operations996 // 2.5.1.5: Control Flow Operations
996997
997 pub fn writeSkip(writer: *std.io.BufferedWriter, offset: i16) !void {998 pub fn writeSkip(writer: *Writer, offset: i16) !void {
998 try writer.writeByte(OP.skip);999 try writer.writeByte(OP.skip);
999 try writer.writeInt(i16, offset, options.endian);1000 try writer.writeInt(i16, offset, options.endian);
1000 }1001 }
10011002
1002 pub fn writeBra(writer: *std.io.BufferedWriter, offset: i16) !void {1003 pub fn writeBra(writer: *Writer, offset: i16) !void {
1003 try writer.writeByte(OP.bra);1004 try writer.writeByte(OP.bra);
1004 try writer.writeInt(i16, offset, options.endian);1005 try writer.writeInt(i16, offset, options.endian);
1005 }1006 }
10061007
1007 pub fn writeCall(writer: *std.io.BufferedWriter, comptime T: type, offset: T) !void {1008 pub fn writeCall(writer: *Writer, comptime T: type, offset: T) !void {
1008 if (options.call_frame_context) return error.InvalidCFAOpcode;1009 if (options.call_frame_context) return error.InvalidCFAOpcode;
1009 switch (T) {1010 switch (T) {
1010 u16 => try writer.writeByte(OP.call2),1011 u16 => try writer.writeByte(OP.call2),
...@@ -1015,19 +1016,19 @@ pub fn Builder(comptime options: Options) type {...@@ -1015,19 +1016,19 @@ pub fn Builder(comptime options: Options) type {
1015 try writer.writeInt(T, offset, options.endian);1016 try writer.writeInt(T, offset, options.endian);
1016 }1017 }
10171018
1018 pub fn writeCallRef(writer: *std.io.BufferedWriter, comptime is_64: bool, value: if (is_64) u64 else u32) !void {1019 pub fn writeCallRef(writer: *Writer, comptime is_64: bool, value: if (is_64) u64 else u32) !void {
1019 if (options.call_frame_context) return error.InvalidCFAOpcode;1020 if (options.call_frame_context) return error.InvalidCFAOpcode;
1020 try writer.writeByte(OP.call_ref);1021 try writer.writeByte(OP.call_ref);
1021 try writer.writeInt(if (is_64) u64 else u32, value, options.endian);1022 try writer.writeInt(if (is_64) u64 else u32, value, options.endian);
1022 }1023 }
10231024
1024 pub fn writeConvert(writer: *std.io.BufferedWriter, die_offset: anytype) !void {1025 pub fn writeConvert(writer: *Writer, die_offset: anytype) !void {
1025 if (options.call_frame_context) return error.InvalidCFAOpcode;1026 if (options.call_frame_context) return error.InvalidCFAOpcode;
1026 try writer.writeByte(OP.convert);1027 try writer.writeByte(OP.convert);
1027 try leb.writeUleb128(writer, die_offset);1028 try leb.writeUleb128(writer, die_offset);
1028 }1029 }
10291030
1030 pub fn writeReinterpret(writer: *std.io.BufferedWriter, die_offset: anytype) !void {1031 pub fn writeReinterpret(writer: *Writer, die_offset: anytype) !void {
1031 if (options.call_frame_context) return error.InvalidCFAOpcode;1032 if (options.call_frame_context) return error.InvalidCFAOpcode;
1032 try writer.writeByte(OP.reinterpret);1033 try writer.writeByte(OP.reinterpret);
1033 try leb.writeUleb128(writer, die_offset);1034 try leb.writeUleb128(writer, die_offset);
...@@ -1035,23 +1036,23 @@ pub fn Builder(comptime options: Options) type {...@@ -1035,23 +1036,23 @@ pub fn Builder(comptime options: Options) type {
10351036
1036 // 2.5.1.7: Special Operations1037 // 2.5.1.7: Special Operations
10371038
1038 pub fn writeEntryValue(writer: *std.io.BufferedWriter, expression: []const u8) !void {1039 pub fn writeEntryValue(writer: *Writer, expression: []const u8) !void {
1039 try writer.writeByte(OP.entry_value);1040 try writer.writeByte(OP.entry_value);
1040 try leb.writeUleb128(writer, expression.len);1041 try leb.writeUleb128(writer, expression.len);
1041 try writer.writeAll(expression);1042 try writer.writeAll(expression);
1042 }1043 }
10431044
1044 // 2.6: Location Descriptions1045 // 2.6: Location Descriptions
1045 pub fn writeReg(writer: *std.io.BufferedWriter, register: u8) !void {1046 pub fn writeReg(writer: *Writer, register: u8) !void {
1046 try writer.writeByte(OP.reg0 + register);1047 try writer.writeByte(OP.reg0 + register);
1047 }1048 }
10481049
1049 pub fn writeRegx(writer: *std.io.BufferedWriter, register: anytype) !void {1050 pub fn writeRegx(writer: *Writer, register: anytype) !void {
1050 try writer.writeByte(OP.regx);1051 try writer.writeByte(OP.regx);
1051 try leb.writeUleb128(writer, register);1052 try leb.writeUleb128(writer, register);
1052 }1053 }
10531054
1054 pub fn writeImplicitValue(writer: *std.io.BufferedWriter, value_bytes: []const u8) !void {1055 pub fn writeImplicitValue(writer: *Writer, value_bytes: []const u8) !void {
1055 try writer.writeByte(OP.implicit_value);1056 try writer.writeByte(OP.implicit_value);
1056 try leb.writeUleb128(writer, value_bytes.len);1057 try leb.writeUleb128(writer, value_bytes.len);
1057 try writer.writeAll(value_bytes);1058 try writer.writeAll(value_bytes);
lib/std/debug/FixedBufferReader.zig+1-2
...@@ -52,8 +52,7 @@ pub fn readIntChecked(...@@ -52,8 +52,7 @@ pub fn readIntChecked(
52}52}
5353
54pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T {54pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
55 var br: std.io.Reader = undefined;55 var br: std.io.Reader = .fixed(fbr.buf);
56 br.initFixed(@constCast(fbr.buf));
57 br.seek = fbr.pos;56 br.seek = fbr.pos;
58 const result = br.takeLeb128(T);57 const result = br.takeLeb128(T);
59 fbr.pos = br.seek;58 fbr.pos = br.seek;
lib/std/fmt.zig+10-12
...@@ -13,6 +13,7 @@ const lossyCast = math.lossyCast;...@@ -13,6 +13,7 @@ const lossyCast = math.lossyCast;
13const expectFmt = std.testing.expectFmt;13const expectFmt = std.testing.expectFmt;
14const testing = std.testing;14const testing = std.testing;
15const Allocator = std.mem.Allocator;15const Allocator = std.mem.Allocator;
16const Writer = std.io.Writer;
1617
17pub const float = @import("fmt/float.zig");18pub const float = @import("fmt/float.zig");
1819
...@@ -92,7 +93,7 @@ pub const Options = struct {...@@ -92,7 +93,7 @@ pub const Options = struct {
92/// A user type may be a `struct`, `vector`, `union` or `enum` type.93/// A user type may be a `struct`, `vector`, `union` or `enum` type.
93///94///
94/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.95/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
95pub fn format(bw: *std.io.BufferedWriter, comptime fmt: []const u8, args: anytype) std.io.Writer.Error!void {96pub fn format(bw: *Writer, comptime fmt: []const u8, args: anytype) Writer.Error!void {
96 const ArgsType = @TypeOf(args);97 const ArgsType = @TypeOf(args);
97 const args_type_info = @typeInfo(ArgsType);98 const args_type_info = @typeInfo(ArgsType);
98 if (args_type_info != .@"struct") {99 if (args_type_info != .@"struct") {
...@@ -452,7 +453,7 @@ fn SliceEscape(comptime case: Case) type {...@@ -452,7 +453,7 @@ fn SliceEscape(comptime case: Case) type {
452 return struct {453 return struct {
453 pub fn format(454 pub fn format(
454 bytes: []const u8,455 bytes: []const u8,
455 bw: *std.io.BufferedWriter,456 bw: *Writer,
456 comptime fmt: []const u8,457 comptime fmt: []const u8,
457 ) !void {458 ) !void {
458 _ = fmt;459 _ = fmt;
...@@ -494,8 +495,7 @@ pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscap...@@ -494,8 +495,7 @@ pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscap
494/// Asserts the rendered integer value fits in `buffer`.495/// Asserts the rendered integer value fits in `buffer`.
495/// Returns the end index within `buffer`.496/// Returns the end index within `buffer`.
496pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {497pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {
497 var bw: std.io.BufferedWriter = undefined;498 var bw: Writer = .fixed(buffer);
498 bw.initFixed(buffer);
499 bw.printIntOptions(value, base, case, options) catch unreachable;499 bw.printIntOptions(value, base, case, options) catch unreachable;
500 return bw.end;500 return bw.end;
501}501}
...@@ -532,7 +532,7 @@ pub fn Formatter(comptime formatFn: anytype) type {...@@ -532,7 +532,7 @@ pub fn Formatter(comptime formatFn: anytype) type {
532 const Data = @typeInfo(@TypeOf(formatFn)).@"fn".params[0].type.?;532 const Data = @typeInfo(@TypeOf(formatFn)).@"fn".params[0].type.?;
533 return struct {533 return struct {
534 data: Data,534 data: Data,
535 pub fn format(self: @This(), writer: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {535 pub fn format(self: @This(), writer: *Writer, comptime fmt: []const u8) Writer.Error!void {
536 try formatFn(self.data, writer, fmt);536 try formatFn(self.data, writer, fmt);
537 }537 }
538 };538 };
...@@ -830,8 +830,7 @@ pub const BufPrintError = error{...@@ -830,8 +830,7 @@ pub const BufPrintError = error{
830830
831/// Print a Formatter string into `buf`. Returns a slice of the bytes printed.831/// Print a Formatter string into `buf`. Returns a slice of the bytes printed.
832pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {832pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {
833 var bw: std.io.BufferedWriter = undefined;833 var bw: Writer = .fixed(buf);
834 bw.initFixed(buf);
835 bw.print(fmt, args) catch |err| switch (err) {834 bw.print(fmt, args) catch |err| switch (err) {
836 error.WriteFailed => return error.NoSpaceLeft,835 error.WriteFailed => return error.NoSpaceLeft,
837 };836 };
...@@ -846,7 +845,7 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr...@@ -846,7 +845,7 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr
846/// Count the characters needed for format.845/// Count the characters needed for format.
847pub fn count(comptime fmt: []const u8, args: anytype) usize {846pub fn count(comptime fmt: []const u8, args: anytype) usize {
848 var trash_buffer: [64]u8 = undefined;847 var trash_buffer: [64]u8 = undefined;
849 var bw: std.io.BufferedWriter = .{848 var bw: Writer = .{
850 .unbuffered_writer = .discarding,849 .unbuffered_writer = .discarding,
851 .buffer = &trash_buffer,850 .buffer = &trash_buffer,
852 };851 };
...@@ -1018,16 +1017,15 @@ test "int.padded" {...@@ -1018,16 +1017,15 @@ test "int.padded" {
1018test "buffer" {1017test "buffer" {
1019 {1018 {
1020 var buf1: [32]u8 = undefined;1019 var buf1: [32]u8 = undefined;
1021 var bw: std.io.BufferedWriter = undefined;1020 var bw: Writer = .fixed(&buf1);
1022 bw.initFixed(&buf1);
1023 try bw.printValue("", .{}, 1234, std.options.fmt_max_depth);1021 try bw.printValue("", .{}, 1234, std.options.fmt_max_depth);
1024 try std.testing.expectEqualStrings("1234", bw.getWritten());1022 try std.testing.expectEqualStrings("1234", bw.getWritten());
10251023
1026 bw.initFixed(&buf1);1024 bw = .fixed(&buf1);
1027 try bw.printValue("c", .{}, 'a', std.options.fmt_max_depth);1025 try bw.printValue("c", .{}, 'a', std.options.fmt_max_depth);
1028 try std.testing.expectEqualStrings("a", bw.getWritten());1026 try std.testing.expectEqualStrings("a", bw.getWritten());
10291027
1030 bw.initFixed(&buf1);1028 bw = .fixed(&buf1);
1031 try bw.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);1029 try bw.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);
1032 try std.testing.expectEqualStrings("1100", bw.getWritten());1030 try std.testing.expectEqualStrings("1100", bw.getWritten());
1033 }1031 }
lib/std/fs/File.zig+26-27
...@@ -844,7 +844,7 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize {...@@ -844,7 +844,7 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize {
844 return posix.write(self.handle, bytes);844 return posix.write(self.handle, bytes);
845}845}
846846
847/// One-shot alternative to `std.io.BufferedWriter.writeAll` via `writer`.847/// One-shot alternative to `std.io.Writer.writeAll` via `writer`.
848pub fn writeAll(self: File, bytes: []const u8) WriteError!void {848pub fn writeAll(self: File, bytes: []const u8) WriteError!void {
849 var index: usize = 0;849 var index: usize = 0;
850 while (index < bytes.len) {850 while (index < bytes.len) {
...@@ -1029,7 +1029,7 @@ pub const Reader = struct {...@@ -1029,7 +1029,7 @@ pub const Reader = struct {
10291029
1030 fn stream(1030 fn stream(
1031 io_reader: *std.io.Reader,1031 io_reader: *std.io.Reader,
1032 bw: *BufferedWriter,1032 bw: *std.io.Writer,
1033 limit: std.io.Limit,1033 limit: std.io.Limit,
1034 ) std.io.Reader.StreamError!usize {1034 ) std.io.Reader.StreamError!usize {
1035 const r: *Reader = @fieldParentPtr("interface", io_reader);1035 const r: *Reader = @fieldParentPtr("interface", io_reader);
...@@ -1180,6 +1180,12 @@ pub const Reader = struct {...@@ -1180,6 +1180,12 @@ pub const Reader = struct {
1180 .failure => return error.ReadFailed,1180 .failure => return error.ReadFailed,
1181 }1181 }
1182 }1182 }
1183
1184 pub fn atEnd(r: *Reader) bool {
1185 // Even if stat fails, size is set when end is encountered.
1186 const size = r.getSize() orelse return false;
1187 return size - r.pos == 0;
1188 }
1183};1189};
11841190
1185pub const Writer = struct {1191pub const Writer = struct {
...@@ -1189,6 +1195,7 @@ pub const Writer = struct {...@@ -1189,6 +1195,7 @@ pub const Writer = struct {
1189 pos: u64 = 0,1195 pos: u64 = 0,
1190 sendfile_err: ?SendfileError = null,1196 sendfile_err: ?SendfileError = null,
1191 seek_err: ?SeekError = null,1197 seek_err: ?SeekError = null,
1198 interface: std.io.Writer,
11921199
1193 pub const Mode = Reader.Mode;1200 pub const Mode = Reader.Mode;
11941201
...@@ -1205,20 +1212,20 @@ pub const Writer = struct {...@@ -1205,20 +1212,20 @@ pub const Writer = struct {
1205 /// vectors through the underlying write calls as possible.1212 /// vectors through the underlying write calls as possible.
1206 const max_buffers_len = 16;1213 const max_buffers_len = 16;
12071214
1208 pub fn interface(w: *Writer) std.io.Writer {1215 pub fn init(file: File, buffer: []u8) std.io.Writer {
1209 return .{1216 return .{
1210 .context = w,1217 .file = file,
1211 .vtable = &.{1218 .interface = .{
1212 .writeSplat = writeSplat,1219 .context = undefined,
1213 .writeFile = writeFile,1220 .vtable = &.{
1221 .drain = drain,
1222 .sendFile = sendFile,
1223 },
1224 .buffer = buffer,
1214 },1225 },
1215 };1226 };
1216 }1227 }
12171228
1218 pub fn writable(w: *Writer, buffer: []u8) std.io.BufferedWriter {
1219 return interface(w).buffered(buffer);
1220 }
1221
1222 pub fn moveToReader(w: *Writer) Reader {1229 pub fn moveToReader(w: *Writer) Reader {
1223 defer w.* = undefined;1230 defer w.* = undefined;
1224 return .{1231 return .{
...@@ -1229,9 +1236,10 @@ pub const Writer = struct {...@@ -1229,9 +1236,10 @@ pub const Writer = struct {
1229 };1236 };
1230 }1237 }
12311238
1232 pub fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {1239 pub fn drain(io_writer: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
1233 const w: *Writer = @ptrCast(@alignCast(context));1240 const w: *Writer = @fieldParentPtr("interface", io_writer);
1234 const handle = w.file.handle;1241 const handle = w.file.handle;
1242 if (true) @panic("update to check for buffered data");
1235 var splat_buffer: [256]u8 = undefined;1243 var splat_buffer: [256]u8 = undefined;
1236 if (is_windows) {1244 if (is_windows) {
1237 if (data.len == 1 and splat == 0) return 0;1245 if (data.len == 1 and splat == 0) return 0;
...@@ -1282,14 +1290,8 @@ pub const Writer = struct {...@@ -1282,14 +1290,8 @@ pub const Writer = struct {
1282 };1290 };
1283 }1291 }
12841292
1285 pub fn writeFile(1293 pub fn sendFile(io_writer: *Writer, file_reader: *Reader, limit: std.io.Limit) std.io.Writer.FileError!usize {
1286 context: ?*anyopaque,1294 const w: *Writer = @fieldParentPtr("interface", io_writer);
1287 file_reader: *Reader,
1288 limit: std.io.Limit,
1289 headers_and_trailers: []const []const u8,
1290 headers_len: usize,
1291 ) std.io.Writer.FileError!usize {
1292 const w: *Writer = @ptrCast(@alignCast(context));
1293 const out_fd = w.file.handle;1295 const out_fd = w.file.handle;
1294 const in_fd = file_reader.file.handle;1296 const in_fd = file_reader.file.handle;
1295 // TODO try using copy_file_range on Linux1297 // TODO try using copy_file_range on Linux
...@@ -1299,9 +1301,8 @@ pub const Writer = struct {...@@ -1299,9 +1301,8 @@ pub const Writer = struct {
1299 if (native_os == .linux and w.mode == .streaming) sf: {1301 if (native_os == .linux and w.mode == .streaming) sf: {
1300 // Try using sendfile on Linux.1302 // Try using sendfile on Linux.
1301 if (w.sendfile_err != null) break :sf;1303 if (w.sendfile_err != null) break :sf;
1302 // Linux sendfile does not support headers or trailers but it does1304 // Linux sendfile does not support headers.
1303 // support a streaming read from in_file.1305 if (io_writer.end != 0) return drain(io_writer, &.{""}, 1);
1304 if (headers_len > 0) return writeSplat(context, headers_and_trailers[0..headers_len], 1);
1305 const max_count = 0x7ffff000; // Avoid EINVAL.1306 const max_count = 0x7ffff000; // Avoid EINVAL.
1306 var off: std.os.linux.off_t = undefined;1307 var off: std.os.linux.off_t = undefined;
1307 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {1308 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {
...@@ -1315,8 +1316,7 @@ pub const Writer = struct {...@@ -1315,8 +1316,7 @@ pub const Writer = struct {
1315 }1316 }
1316 return 0;1317 return 0;
1317 };1318 };
1318 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse1319 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed;
1319 return writeSplat(context, headers_and_trailers, 1);
1320 break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) };1320 break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) };
1321 },1321 },
1322 .streaming => .{ null, limit.minInt(max_count) },1322 .streaming => .{ null, limit.minInt(max_count) },
...@@ -1576,4 +1576,3 @@ const linux = std.os.linux;...@@ -1576,4 +1576,3 @@ const linux = std.os.linux;
1576const windows = std.os.windows;1576const windows = std.os.windows;
1577const maxInt = std.math.maxInt;1577const maxInt = std.math.maxInt;
1578const Alignment = std.mem.Alignment;1578const Alignment = std.mem.Alignment;
1579const BufferedWriter = std.io.BufferedWriter;
lib/std/fs/path.zig+2-2
...@@ -150,8 +150,8 @@ pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter(formatJoin) {...@@ -150,8 +150,8 @@ pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter(formatJoin) {
150 return .{ .data = paths };150 return .{ .data = paths };
151}151}
152152
153fn formatJoin(paths: []const []const u8, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {153fn formatJoin(paths: []const []const u8, bw: *std.io.Writer, comptime fmt: []const u8) !void {
154 _ = fmt;154 comptime assert(fmt.len == 0);
155155
156 const first_path_idx = for (paths, 0..) |p, idx| {156 const first_path_idx = for (paths, 0..) |p, idx| {
157 if (p.len != 0) break idx;157 if (p.len != 0) break idx;
lib/std/hash/crc.zig+8-10
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const Writer = std.io.Writer;
23
3pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {4pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {
4 return struct {5 return struct {
...@@ -79,21 +80,18 @@ pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {...@@ -79,21 +80,18 @@ pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {
79 return c.final();80 return c.final();
80 }81 }
8182
82 pub fn writable(self: *Self, buffer: []u8) std.io.BufferedWriter {83 pub fn writer(self: *Self, buffer: []u8) Writer {
83 return .{84 return .{
84 .unbuffered_writer = .{85 .context = self,
85 .context = self,86 .vtable = &.{ .drain = drain },
86 .vtable = &.{
87 .writeSplat = writeSplat,
88 .writeFile = std.io.Writer.unimplementedWriteFile,
89 },
90 },
91 .buffer = buffer,87 .buffer = buffer,
92 };88 };
93 }89 }
9490
95 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {91 fn drain(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
96 const self: *Self = @ptrCast(@alignCast(context));92 const self: *Self = @ptrCast(@alignCast(w.context));
93 self.update(w.buffered());
94 w.end = 0;
97 var n: usize = 0;95 var n: usize = 0;
98 for (data[0 .. data.len - 1]) |slice| {96 for (data[0 .. data.len - 1]) |slice| {
99 self.update(slice);97 self.update(slice);
lib/std/http.zig+70-129
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std.zig");2const std = @import("std.zig");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const Writer = std.io.Writer;
5const File = std.fs.File;
46
5pub const Client = @import("http/Client.zig");7pub const Client = @import("http/Client.zig");
6pub const Server = @import("http/Server.zig");8pub const Server = @import("http/Server.zig");
...@@ -504,7 +506,7 @@ pub const Reader = struct {...@@ -504,7 +506,7 @@ pub const Reader = struct {
504506
505 fn contentLengthRead(507 fn contentLengthRead(
506 ctx: ?*anyopaque,508 ctx: ?*anyopaque,
507 bw: *std.io.BufferedWriter,509 bw: *Writer,
508 limit: std.io.Limit,510 limit: std.io.Limit,
509 ) std.io.Reader.StreamError!usize {511 ) std.io.Reader.StreamError!usize {
510 const reader: *Reader = @alignCast(@ptrCast(ctx));512 const reader: *Reader = @alignCast(@ptrCast(ctx));
...@@ -534,7 +536,7 @@ pub const Reader = struct {...@@ -534,7 +536,7 @@ pub const Reader = struct {
534536
535 fn chunkedRead(537 fn chunkedRead(
536 ctx: ?*anyopaque,538 ctx: ?*anyopaque,
537 bw: *std.io.BufferedWriter,539 bw: *Writer,
538 limit: std.io.Limit,540 limit: std.io.Limit,
539 ) std.io.Reader.StreamError!usize {541 ) std.io.Reader.StreamError!usize {
540 const reader: *Reader = @alignCast(@ptrCast(ctx));542 const reader: *Reader = @alignCast(@ptrCast(ctx));
...@@ -559,7 +561,7 @@ pub const Reader = struct {...@@ -559,7 +561,7 @@ pub const Reader = struct {
559561
560 fn chunkedReadEndless(562 fn chunkedReadEndless(
561 reader: *Reader,563 reader: *Reader,
562 bw: *std.io.BufferedWriter,564 bw: *Writer,
563 limit: std.io.Limit,565 limit: std.io.Limit,
564 chunk_len_ptr: *RemainingChunkLen,566 chunk_len_ptr: *RemainingChunkLen,
565 ) (BodyError || std.io.Reader.StreamError)!usize {567 ) (BodyError || std.io.Reader.StreamError)!usize {
...@@ -747,11 +749,12 @@ pub const Decompressor = struct {...@@ -747,11 +749,12 @@ pub const Decompressor = struct {
747pub const BodyWriter = struct {749pub const BodyWriter = struct {
748 /// Until the lifetime of `BodyWriter` ends, it is illegal to modify the750 /// Until the lifetime of `BodyWriter` ends, it is illegal to modify the
749 /// state of this other than via methods of `BodyWriter`.751 /// state of this other than via methods of `BodyWriter`.
750 http_protocol_output: *std.io.BufferedWriter,752 http_protocol_output: *Writer,
751 state: State,753 state: State,
752 elide: bool,754 elide: bool,
755 interface: Writer,
753756
754 pub const WriteError = std.io.Writer.Error;757 pub const Error = Writer.Error;
755758
756 /// How many zeroes to reserve for hex-encoded chunk length.759 /// How many zeroes to reserve for hex-encoded chunk length.
757 const chunk_len_digits = 8;760 const chunk_len_digits = 8;
...@@ -787,7 +790,7 @@ pub const BodyWriter = struct {...@@ -787,7 +790,7 @@ pub const BodyWriter = struct {
787 };790 };
788791
789 /// Sends all buffered data across `BodyWriter.http_protocol_output`.792 /// Sends all buffered data across `BodyWriter.http_protocol_output`.
790 pub fn flush(w: *BodyWriter) WriteError!void {793 pub fn flush(w: *BodyWriter) Error!void {
791 const out = w.http_protocol_output;794 const out = w.http_protocol_output;
792 switch (w.state) {795 switch (w.state) {
793 .end, .none, .content_length => return out.flush(),796 .end, .none, .content_length => return out.flush(),
...@@ -820,7 +823,7 @@ pub const BodyWriter = struct {...@@ -820,7 +823,7 @@ pub const BodyWriter = struct {
820 /// See also:823 /// See also:
821 /// * `endUnflushed`824 /// * `endUnflushed`
822 /// * `endChunked`825 /// * `endChunked`
823 pub fn end(w: *BodyWriter) WriteError!void {826 pub fn end(w: *BodyWriter) Error!void {
824 try endUnflushed(w);827 try endUnflushed(w);
825 try w.http_protocol_output.flush();828 try w.http_protocol_output.flush();
826 }829 }
...@@ -836,7 +839,7 @@ pub const BodyWriter = struct {...@@ -836,7 +839,7 @@ pub const BodyWriter = struct {
836 /// See also:839 /// See also:
837 /// * `end`840 /// * `end`
838 /// * `endChunked`841 /// * `endChunked`
839 pub fn endUnflushed(w: *BodyWriter) WriteError!void {842 pub fn endUnflushed(w: *BodyWriter) Error!void {
840 switch (w.state) {843 switch (w.state) {
841 .end => unreachable,844 .end => unreachable,
842 .content_length => |len| {845 .content_length => |len| {
...@@ -862,7 +865,7 @@ pub const BodyWriter = struct {...@@ -862,7 +865,7 @@ pub const BodyWriter = struct {
862 /// See also:865 /// See also:
863 /// * `endChunkedUnflushed`866 /// * `endChunkedUnflushed`
864 /// * `end`867 /// * `end`
865 pub fn endChunked(w: *BodyWriter, options: EndChunkedOptions) WriteError!void {868 pub fn endChunked(w: *BodyWriter, options: EndChunkedOptions) Error!void {
866 try endChunkedUnflushed(w, options);869 try endChunkedUnflushed(w, options);
867 try w.http_protocol_output.flush();870 try w.http_protocol_output.flush();
868 }871 }
...@@ -879,7 +882,7 @@ pub const BodyWriter = struct {...@@ -879,7 +882,7 @@ pub const BodyWriter = struct {
879 /// * `endChunked`882 /// * `endChunked`
880 /// * `endUnflushed`883 /// * `endUnflushed`
881 /// * `end`884 /// * `end`
882 pub fn endChunkedUnflushed(w: *BodyWriter, options: EndChunkedOptions) WriteError!void {885 pub fn endChunkedUnflushed(w: *BodyWriter, options: EndChunkedOptions) Error!void {
883 const chunked = &w.state.chunked;886 const chunked = &w.state.chunked;
884 if (w.elide) {887 if (w.elide) {
885 w.state = .end;888 w.state = .end;
...@@ -910,138 +913,78 @@ pub const BodyWriter = struct {...@@ -910,138 +913,78 @@ pub const BodyWriter = struct {
910 w.state = .end;913 w.state = .end;
911 }914 }
912915
913 fn contentLengthWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) WriteError!usize {916 fn contentLengthDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
914 const w: *BodyWriter = @alignCast(@ptrCast(context));917 const bw: *BodyWriter = @fieldParentPtr("interface", w);
915 const n = if (w.elide) countSplat(data, splat) else try w.http_protocol_output.writeSplat(data, splat);918 assert(!bw.elide);
919 const out = w.http_protocol_output;
920 const n = try w.drainTo(out, data, splat);
916 w.state.content_length -= n;921 w.state.content_length -= n;
917 return n;922 return n;
918 }923 }
919924
920 fn noneWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) WriteError!usize {925 fn noneDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
921 const w: *BodyWriter = @alignCast(@ptrCast(context));926 const bw: *BodyWriter = @fieldParentPtr("interface", w);
922 if (w.elide) return countSplat(data, splat);927 assert(!bw.elide);
923 return w.http_protocol_output.writeSplat(data, splat);928 const out = w.http_protocol_output;
924 }929 return try w.drainTo(out, data, splat);
925
926 fn countSplat(data: []const []const u8, splat: usize) usize {
927 if (data.len == 0) return 0;
928 var total: usize = 0;
929 for (data[0 .. data.len - 1]) |buf| total += buf.len;
930 total += data[data.len - 1].len * splat;
931 return total;
932 }
933
934 fn elideWriteFile(
935 file_reader: *std.fs.File.Reader,
936 limit: std.io.Limit,
937 headers_and_trailers: []const []const u8,
938 headers_len: usize,
939 ) error{ReadFailed}!usize {
940 var source = file_reader.readable(&.{});
941 var n = source.discard(limit) catch |err| switch (err) {
942 error.ReadFailed => return error.ReadFailed,
943 error.EndOfStream => {
944 var n: usize = 0;
945 for (headers_and_trailers) |bytes| n += bytes.len;
946 return n;
947 },
948 };
949 if (file_reader.size) |size| {
950 if (size - file_reader.pos == 0) {
951 // End of file reached.
952 for (headers_and_trailers) |bytes| n += bytes.len;
953 return n;
954 }
955 }
956 for (headers_and_trailers[0..headers_len]) |bytes| n += bytes.len;
957 return n;
958 }930 }
959931
960 /// Returns `null` if size cannot be computed without making any syscalls.932 /// Returns `null` if size cannot be computed without making any syscalls.
961 fn countWriteFile(933 fn noneSendFile(w: *Writer, file_reader: *File.Reader, limit: std.io.Limit) Writer.FileError!usize {
962 file_reader: *std.fs.File.Reader,934 const bw: *BodyWriter = @fieldParentPtr("interface", w);
963 limit: std.io.Limit,935 assert(!bw.elide);
964 headers_and_trailers: []const []const u8,936 return w.sendFileTo(bw.http_protocol_output, file_reader, limit);
965 ) ?usize {
966 var total: u64 = @min(@intFromEnum(limit), file_reader.getSize() orelse return null);
967 for (headers_and_trailers) |bytes| total += bytes.len;
968 return std.math.lossyCast(usize, total);
969 }
970
971 fn noneWriteFile(
972 context: ?*anyopaque,
973 file_reader: *std.fs.File.Reader,
974 limit: std.io.Limit,
975 headers_and_trailers: []const []const u8,
976 headers_len: usize,
977 ) std.io.Writer.FileError!usize {
978 const w: *BodyWriter = @alignCast(@ptrCast(context));
979 if (w.elide) return elideWriteFile(file_reader, limit, headers_and_trailers, headers_len);
980 return w.http_protocol_output.writeFile(file_reader, limit, headers_and_trailers, headers_len);
981 }937 }
982938
983 fn contentLengthWriteFile(939 fn contentLengthSendFile(w: *Writer, file_reader: *File.Reader, limit: std.io.Limit) Writer.FileError!usize {
984 context: ?*anyopaque,940 const bw: *BodyWriter = @fieldParentPtr("interface", w);
985 file_reader: *std.fs.File.Reader,941 assert(!bw.elide);
986 limit: std.io.Limit,942 const n = try w.sendFileTo(bw.http_protocol_output, file_reader, limit);
987 headers_and_trailers: []const []const u8,943 bw.state.content_length -= n;
988 headers_len: usize,
989 ) std.io.Writer.FileError!usize {
990 const w: *BodyWriter = @alignCast(@ptrCast(context));
991 if (w.elide) return elideWriteFile(file_reader, limit, headers_and_trailers, headers_len);
992 const n = try w.http_protocol_output.writeFile(file_reader, limit, headers_and_trailers, headers_len);
993 w.state.content_length -= n;
994 return n;944 return n;
995 }945 }
996946
997 fn chunkedWriteFile(947 fn chunkedSendFile(w: *Writer, file_reader: *File.Reader, limit: std.io.Limit) Writer.FileError!usize {
998 context: ?*anyopaque,948 const bw: *BodyWriter = @fieldParentPtr("interface", w);
999 file_reader: *std.fs.File.Reader,949 assert(!bw.elide);
1000 limit: std.io.Limit,950 const data_len = w.countSendFileUpperBound(file_reader, limit) orelse {
1001 headers_and_trailers: []const []const u8,
1002 headers_len: usize,
1003 ) std.io.Writer.FileError!usize {
1004 const w: *BodyWriter = @alignCast(@ptrCast(context));
1005 if (w.elide) return elideWriteFile(file_reader, limit, headers_and_trailers, headers_len);
1006 if (limit == .nothing) return chunkedWriteSplat(context, headers_and_trailers, 1);
1007 const data_len = countWriteFile(file_reader, headers_and_trailers) orelse {
1008 // If the file size is unknown, we cannot lower to a `writeFile` since we would951 // If the file size is unknown, we cannot lower to a `writeFile` since we would
1009 // have to flush the chunk header before knowing the chunk length.952 // have to flush the chunk header before knowing the chunk length.
1010 return error.Unimplemented;953 return error.Unimplemented;
1011 };954 };
1012 const bw = w.http_protocol_output;955 const out = bw.http_protocol_output;
1013 const chunked = &w.state.chunked;956 const chunked = &bw.state.chunked;
1014 state: switch (chunked.*) {957 state: switch (chunked.*) {
1015 .offset => |off| {958 .offset => |off| {
1016 // TODO: is it better perf to read small files into the buffer?959 // TODO: is it better perf to read small files into the buffer?
1017 const buffered_len = bw.end - off - chunk_header_template.len;960 const buffered_len = out.end - off - chunk_header_template.len;
1018 const chunk_len = data_len + buffered_len;961 const chunk_len = data_len + buffered_len;
1019 writeHex(bw.buffer[off..][0..chunk_len_digits], chunk_len);962 writeHex(out.buffer[off..][0..chunk_len_digits], chunk_len);
1020 const n = try bw.writeFile(file_reader, limit, headers_and_trailers, headers_len);963 const n = try w.sendFileTo(out, file_reader, limit);
1021 chunked.* = .{ .chunk_len = data_len + 2 - n };964 chunked.* = .{ .chunk_len = data_len + 2 - n };
1022 return n;965 return n;
1023 },966 },
1024 .chunk_len => |chunk_len| l: switch (chunk_len) {967 .chunk_len => |chunk_len| l: switch (chunk_len) {
1025 0 => {968 0 => {
1026 const off = bw.end;969 const off = out.end;
1027 const header_buf = try bw.writableArray(chunk_header_template.len);970 const header_buf = try out.writableArray(chunk_header_template.len);
1028 @memcpy(header_buf, chunk_header_template);971 @memcpy(header_buf, chunk_header_template);
1029 chunked.* = .{ .offset = off };972 chunked.* = .{ .offset = off };
1030 continue :state .{ .offset = off };973 continue :state .{ .offset = off };
1031 },974 },
1032 1 => {975 1 => {
1033 try bw.writeByte('\n');976 try out.writeByte('\n');
1034 chunked.chunk_len = 0;977 chunked.chunk_len = 0;
1035 continue :l 0;978 continue :l 0;
1036 },979 },
1037 2 => {980 2 => {
1038 try bw.writeByte('\r');981 try out.writeByte('\r');
1039 chunked.chunk_len = 1;982 chunked.chunk_len = 1;
1040 continue :l 1;983 continue :l 1;
1041 },984 },
1042 else => {985 else => {
1043 const new_limit = limit.min(.limited(chunk_len - 2));986 const new_limit = limit.min(.limited(chunk_len - 2));
1044 const n = try bw.writeFile(file_reader, new_limit, headers_and_trailers, headers_len);987 const n = try w.sendFileTo(out, file_reader, new_limit);
1045 chunked.chunk_len = chunk_len - n;988 chunked.chunk_len = chunk_len - n;
1046 return n;989 return n;
1047 },990 },
...@@ -1049,47 +992,45 @@ pub const BodyWriter = struct {...@@ -1049,47 +992,45 @@ pub const BodyWriter = struct {
1049 }992 }
1050 }993 }
1051994
1052 fn chunkedWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) WriteError!usize {995 fn chunkedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
1053 const w: *BodyWriter = @alignCast(@ptrCast(context));996 const bw: *BodyWriter = @fieldParentPtr("interface", w);
1054 const data_len = countSplat(data, splat);997 assert(!bw.elide);
1055 if (w.elide) return data_len;998 const out = w.http_protocol_output;
1056999 const data_len = Writer.countSplat(w.end, data, splat);
1057 const bw = w.http_protocol_output;1000 const chunked = &bw.state.chunked;
1058 const chunked = &w.state.chunked;
1059
1060 state: switch (chunked.*) {1001 state: switch (chunked.*) {
1061 .offset => |offset| {1002 .offset => |offset| {
1062 if (bw.unusedCapacitySlice().len >= data_len) {1003 if (out.unusedCapacityLen() >= data_len) {
1063 assert(data_len == (bw.writeSplat(data, splat) catch unreachable));1004 assert(data_len == (w.drainTo(out, data, splat) catch unreachable));
1064 return data_len;1005 return data_len;
1065 }1006 }
1066 const buffered_len = bw.end - offset - chunk_header_template.len;1007 const buffered_len = out.end - offset - chunk_header_template.len;
1067 const chunk_len = data_len + buffered_len;1008 const chunk_len = data_len + buffered_len;
1068 writeHex(bw.buffer[offset..][0..chunk_len_digits], chunk_len);1009 writeHex(out.buffer[offset..][0..chunk_len_digits], chunk_len);
1069 const n = try bw.writeSplat(data, splat);1010 const n = try w.drainTo(w, data, splat);
1070 chunked.* = .{ .chunk_len = data_len + 2 - n };1011 chunked.* = .{ .chunk_len = data_len + 2 - n };
1071 return n;1012 return n;
1072 },1013 },
1073 .chunk_len => |chunk_len| l: switch (chunk_len) {1014 .chunk_len => |chunk_len| l: switch (chunk_len) {
1074 0 => {1015 0 => {
1075 const offset = bw.end;1016 const offset = out.end;
1076 const header_buf = try bw.writableArray(chunk_header_template.len);1017 const header_buf = try out.writableArray(chunk_header_template.len);
1077 @memcpy(header_buf, chunk_header_template);1018 @memcpy(header_buf, chunk_header_template);
1078 chunked.* = .{ .offset = offset };1019 chunked.* = .{ .offset = offset };
1079 continue :state .{ .offset = offset };1020 continue :state .{ .offset = offset };
1080 },1021 },
1081 1 => {1022 1 => {
1082 try bw.writeByte('\n');1023 try out.writeByte('\n');
1083 chunked.chunk_len = 0;1024 chunked.chunk_len = 0;
1084 continue :l 0;1025 continue :l 0;
1085 },1026 },
1086 2 => {1027 2 => {
1087 try bw.writeByte('\r');1028 try out.writeByte('\r');
1088 chunked.chunk_len = 1;1029 chunked.chunk_len = 1;
1089 continue :l 1;1030 continue :l 1;
1090 },1031 },
1091 else => {1032 else => {
1092 const n = try bw.writeSplatLimit(data, splat, .limited(chunk_len - 2));1033 const n = try w.drainToLimit(data, splat, .limited(chunk_len - 2));
1093 chunked.chunk_len = chunk_len - n;1034 chunked.chunk_len = chunk_len - n;
1094 return n;1035 return n;
1095 },1036 },
...@@ -1112,21 +1053,21 @@ pub const BodyWriter = struct {...@@ -1112,21 +1053,21 @@ pub const BodyWriter = struct {
1112 }1053 }
1113 }1054 }
11141055
1115 pub fn writer(w: *BodyWriter) std.io.Writer {1056 pub fn writer(w: *BodyWriter) Writer {
1116 return .{1057 return if (w.elide) .discarding else .{
1117 .context = w,1058 .context = w,
1118 .vtable = switch (w.state) {1059 .vtable = switch (w.state) {
1119 .none => &.{1060 .none => &.{
1120 .writeSplat = noneWriteSplat,1061 .drain = noneDrain,
1121 .writeFile = noneWriteFile,1062 .sendFile = noneSendFile,
1122 },1063 },
1123 .content_length => &.{1064 .content_length => &.{
1124 .writeSplat = contentLengthWriteSplat,1065 .drain = contentLengthDrain,
1125 .writeFile = contentLengthWriteFile,1066 .sendFile = contentLengthSendFile,
1126 },1067 },
1127 .chunked => &.{1068 .chunked => &.{
1128 .writeSplat = chunkedWriteSplat,1069 .drain = chunkedDrain,
1129 .writeFile = chunkedWriteFile,1070 .sendFile = chunkedSendFile,
1130 },1071 },
1131 .end => unreachable,1072 .end => unreachable,
1132 },1073 },
lib/std/http/Client.zig+14-15
...@@ -13,6 +13,7 @@ const net = std.net;...@@ -13,6 +13,7 @@ const net = std.net;
13const Uri = std.Uri;13const Uri = std.Uri;
14const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
15const assert = std.debug.assert;15const assert = std.debug.assert;
16const Writer = std.io.Writer;
1617
17const Client = @This();18const Client = @This();
1819
...@@ -229,7 +230,7 @@ pub const Connection = struct {...@@ -229,7 +230,7 @@ pub const Connection = struct {
229 stream_reader: net.Stream.Reader,230 stream_reader: net.Stream.Reader,
230 /// HTTP protocol from client to server.231 /// HTTP protocol from client to server.
231 /// This either goes directly to `stream_writer`, or to a TLS client.232 /// This either goes directly to `stream_writer`, or to a TLS client.
232 writer: std.io.BufferedWriter,233 writer: Writer,
233 /// HTTP protocol from server to client.234 /// HTTP protocol from server to client.
234 /// This either comes directly from `stream_reader`, or from a TLS client.235 /// This either comes directly from `stream_reader`, or from a TLS client.
235 reader: std.io.Reader,236 reader: std.io.Reader,
...@@ -297,7 +298,7 @@ pub const Connection = struct {...@@ -297,7 +298,7 @@ pub const Connection = struct {
297298
298 const Tls = struct {299 const Tls = struct {
299 /// Data from `client` to `Connection.stream`.300 /// Data from `client` to `Connection.stream`.
300 writer: std.io.BufferedWriter,301 writer: Writer,
301 /// Data from `Connection.stream` to `client`.302 /// Data from `Connection.stream` to `client`.
302 reader: std.io.Reader,303 reader: std.io.Reader,
303 client: std.crypto.tls.Client,304 client: std.crypto.tls.Client,
...@@ -403,7 +404,7 @@ pub const Connection = struct {...@@ -403,7 +404,7 @@ pub const Connection = struct {
403 }404 }
404 }405 }
405406
406 pub fn flush(c: *Connection) std.io.Writer.Error!void {407 pub fn flush(c: *Connection) Writer.Error!void {
407 try c.writer.flush();408 try c.writer.flush();
408 if (c.protocol == .tls) {409 if (c.protocol == .tls) {
409 if (disable_tls) unreachable;410 if (disable_tls) unreachable;
...@@ -415,7 +416,7 @@ pub const Connection = struct {...@@ -415,7 +416,7 @@ pub const Connection = struct {
415 /// If the connection is a TLS connection, sends the close_notify alert.416 /// If the connection is a TLS connection, sends the close_notify alert.
416 ///417 ///
417 /// Flushes all buffers.418 /// Flushes all buffers.
418 pub fn end(c: *Connection) std.io.Writer.Error!void {419 pub fn end(c: *Connection) Writer.Error!void {
419 try c.writer.flush();420 try c.writer.flush();
420 if (c.protocol == .tls) {421 if (c.protocol == .tls) {
421 if (disable_tls) unreachable;422 if (disable_tls) unreachable;
...@@ -818,13 +819,13 @@ pub const Request = struct {...@@ -818,13 +819,13 @@ pub const Request = struct {
818 }819 }
819820
820 /// Sends and flushes a complete request as only HTTP head, no body.821 /// Sends and flushes a complete request as only HTTP head, no body.
821 pub fn sendBodiless(r: *Request) std.io.Writer.Error!void {822 pub fn sendBodiless(r: *Request) Writer.Error!void {
822 try sendBodilessUnflushed(r);823 try sendBodilessUnflushed(r);
823 try r.connection.?.flush();824 try r.connection.?.flush();
824 }825 }
825826
826 /// Sends but does not flush a complete request as only HTTP head, no body.827 /// Sends but does not flush a complete request as only HTTP head, no body.
827 pub fn sendBodilessUnflushed(r: *Request) std.io.Writer.Error!void {828 pub fn sendBodilessUnflushed(r: *Request) Writer.Error!void {
828 assert(r.transfer_encoding == .none);829 assert(r.transfer_encoding == .none);
829 assert(!r.method.requestHasBody());830 assert(!r.method.requestHasBody());
830 try sendHead(r);831 try sendHead(r);
...@@ -834,7 +835,7 @@ pub const Request = struct {...@@ -834,7 +835,7 @@ pub const Request = struct {
834 ///835 ///
835 /// See also:836 /// See also:
836 /// * `sendBodyUnflushed`837 /// * `sendBodyUnflushed`
837 pub fn sendBody(r: *Request) std.io.Writer.Error!http.BodyWriter {838 pub fn sendBody(r: *Request) Writer.Error!http.BodyWriter {
838 const result = try sendBodyUnflushed(r);839 const result = try sendBodyUnflushed(r);
839 try r.connection.?.flush();840 try r.connection.?.flush();
840 return result;841 return result;
...@@ -845,7 +846,7 @@ pub const Request = struct {...@@ -845,7 +846,7 @@ pub const Request = struct {
845 ///846 ///
846 /// See also:847 /// See also:
847 /// * `sendBody`848 /// * `sendBody`
848 pub fn sendBodyUnflushed(r: *Request) std.io.Writer.Error!http.BodyWriter {849 pub fn sendBodyUnflushed(r: *Request) Writer.Error!http.BodyWriter {
849 assert(r.method.requestHasBody());850 assert(r.method.requestHasBody());
850 try sendHead(r);851 try sendHead(r);
851 return .{852 return .{
...@@ -860,7 +861,7 @@ pub const Request = struct {...@@ -860,7 +861,7 @@ pub const Request = struct {
860 }861 }
861862
862 /// Sends HTTP headers without flushing.863 /// Sends HTTP headers without flushing.
863 fn sendHead(r: *Request) std.io.Writer.Error!void {864 fn sendHead(r: *Request) Writer.Error!void {
864 const uri = r.uri;865 const uri = r.uri;
865 const connection = r.connection.?;866 const connection = r.connection.?;
866 const w = &connection.writer;867 const w = &connection.writer;
...@@ -1134,7 +1135,7 @@ pub const Request = struct {...@@ -1134,7 +1135,7 @@ pub const Request = struct {
11341135
1135 /// Returns true if the default behavior is required, otherwise handles1136 /// Returns true if the default behavior is required, otherwise handles
1136 /// writing (or not writing) the header.1137 /// writing (or not writing) the header.
1137 fn emitOverridableHeader(prefix: []const u8, v: Headers.Value, bw: *std.io.BufferedWriter) std.io.Writer.Error!bool {1138 fn emitOverridableHeader(prefix: []const u8, v: Headers.Value, bw: *Writer) Writer.Error!bool {
1138 switch (v) {1139 switch (v) {
1139 .default => return true,1140 .default => return true,
1140 .omit => return false,1141 .omit => return false,
...@@ -1242,16 +1243,14 @@ pub const basic_authorization = struct {...@@ -1242,16 +1243,14 @@ pub const basic_authorization = struct {
1242 }1243 }
12431244
1244 pub fn value(uri: Uri, out: []u8) []u8 {1245 pub fn value(uri: Uri, out: []u8) []u8 {
1245 var bw: std.io.BufferedWriter = undefined;1246 var bw: Writer = .fixed(out);
1246 bw.initFixed(out);
1247 write(uri, &bw) catch unreachable;1247 write(uri, &bw) catch unreachable;
1248 return bw.getWritten();1248 return bw.getWritten();
1249 }1249 }
12501250
1251 pub fn write(uri: Uri, out: *std.io.BufferedWriter) std.io.Writer.Error!void {1251 pub fn write(uri: Uri, out: *Writer) Writer.Error!void {
1252 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;1252 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
1253 var bw: std.io.BufferedWriter = undefined;1253 var bw: Writer = .fixed(&buf);
1254 bw.initFixed(&buf);
1255 bw.print("{fuser}:{fpassword}", .{1254 bw.print("{fuser}:{fpassword}", .{
1256 uri.user orelse Uri.Component.empty,1255 uri.user orelse Uri.Component.empty,
1257 uri.password orelse Uri.Component.empty,1256 uri.password orelse Uri.Component.empty,
lib/std/http/Server.zig+11-10
...@@ -6,11 +6,12 @@ const mem = std.mem;...@@ -6,11 +6,12 @@ const mem = std.mem;
6const Uri = std.Uri;6const Uri = std.Uri;
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const testing = std.testing;8const testing = std.testing;
9const Writer = std.io.Writer;
910
10const Server = @This();11const Server = @This();
1112
12/// Data from the HTTP server to the HTTP client.13/// Data from the HTTP server to the HTTP client.
13out: *std.io.BufferedWriter,14out: *Writer,
14reader: http.Reader,15reader: http.Reader,
1516
16/// Initialize an HTTP server that can respond to multiple requests on the same17/// Initialize an HTTP server that can respond to multiple requests on the same
...@@ -20,7 +21,7 @@ reader: http.Reader,...@@ -20,7 +21,7 @@ reader: http.Reader,
20/// header, otherwise `receiveHead` returns `error.HttpHeadersOversize`.21/// header, otherwise `receiveHead` returns `error.HttpHeadersOversize`.
21///22///
22/// The returned `Server` is ready for `receiveHead` to be called.23/// The returned `Server` is ready for `receiveHead` to be called.
23pub fn init(in: *std.io.Reader, out: *std.io.BufferedWriter) Server {24pub fn init(in: *std.io.Reader, out: *Writer) Server {
24 return .{25 return .{
25 .reader = .{26 .reader = .{
26 .in = in,27 .in = in,
...@@ -397,7 +398,7 @@ pub const Request = struct {...@@ -397,7 +398,7 @@ pub const Request = struct {
397 /// be done to satisfy the request.398 /// be done to satisfy the request.
398 ///399 ///
399 /// Asserts status is not `continue`.400 /// Asserts status is not `continue`.
400 pub fn respondStreaming(request: *Request, options: RespondStreamingOptions) std.io.Writer.Error!http.BodyWriter {401 pub fn respondStreaming(request: *Request, options: RespondStreamingOptions) Writer.Error!http.BodyWriter {
401 try writeExpectContinue(request);402 try writeExpectContinue(request);
402 const o = options.respond_options;403 const o = options.respond_options;
403 assert(o.status != .@"continue");404 assert(o.status != .@"continue");
...@@ -485,7 +486,7 @@ pub const Request = struct {...@@ -485,7 +486,7 @@ pub const Request = struct {
485486
486 /// The header is not guaranteed to be sent until `WebSocket.flush` is487 /// The header is not guaranteed to be sent until `WebSocket.flush` is
487 /// called on the returned struct.488 /// called on the returned struct.
488 pub fn respondWebSocket(request: *Request, options: WebSocketOptions) std.io.Writer.Error!WebSocket {489 pub fn respondWebSocket(request: *Request, options: WebSocketOptions) Writer.Error!WebSocket {
489 if (request.head.expect != null) return error.HttpExpectationFailed;490 if (request.head.expect != null) return error.HttpExpectationFailed;
490491
491 const out = request.server.out;492 const out = request.server.out;
...@@ -611,7 +612,7 @@ pub const Request = struct {...@@ -611,7 +612,7 @@ pub const Request = struct {
611pub const WebSocket = struct {612pub const WebSocket = struct {
612 key: []const u8,613 key: []const u8,
613 input: *std.io.Reader,614 input: *std.io.Reader,
614 output: *std.io.BufferedWriter,615 output: *Writer,
615616
616 pub const Header0 = packed struct(u8) {617 pub const Header0 = packed struct(u8) {
617 opcode: Opcode,618 opcode: Opcode,
...@@ -701,21 +702,21 @@ pub const WebSocket = struct {...@@ -701,21 +702,21 @@ pub const WebSocket = struct {
701 }702 }
702 }703 }
703704
704 pub fn writeMessage(ws: *WebSocket, data: []const u8, op: Opcode) std.io.Writer.Error!void {705 pub fn writeMessage(ws: *WebSocket, data: []const u8, op: Opcode) Writer.Error!void {
705 try writeMessageVecUnflushed(ws, &.{data}, op);706 try writeMessageVecUnflushed(ws, &.{data}, op);
706 try ws.output.flush();707 try ws.output.flush();
707 }708 }
708709
709 pub fn writeMessageUnflushed(ws: *WebSocket, data: []const u8, op: Opcode) std.io.Writer.Error!void {710 pub fn writeMessageUnflushed(ws: *WebSocket, data: []const u8, op: Opcode) Writer.Error!void {
710 try writeMessageVecUnflushed(ws, &.{data}, op);711 try writeMessageVecUnflushed(ws, &.{data}, op);
711 }712 }
712713
713 pub fn writeMessageVec(ws: *WebSocket, data: []const []const u8, op: Opcode) std.io.Writer.Error!void {714 pub fn writeMessageVec(ws: *WebSocket, data: []const []const u8, op: Opcode) Writer.Error!void {
714 try writeMessageVecUnflushed(ws, data, op);715 try writeMessageVecUnflushed(ws, data, op);
715 try ws.output.flush();716 try ws.output.flush();
716 }717 }
717718
718 pub fn writeMessageVecUnflushed(ws: *WebSocket, data: []const []const u8, op: Opcode) std.io.Writer.Error!void {719 pub fn writeMessageVecUnflushed(ws: *WebSocket, data: []const []const u8, op: Opcode) Writer.Error!void {
719 const total_len = l: {720 const total_len = l: {
720 var total_len: u64 = 0;721 var total_len: u64 = 0;
721 for (data) |iovec| total_len += iovec.len;722 for (data) |iovec| total_len += iovec.len;
...@@ -749,7 +750,7 @@ pub const WebSocket = struct {...@@ -749,7 +750,7 @@ pub const WebSocket = struct {
749 try out.writeVecAll(data);750 try out.writeVecAll(data);
750 }751 }
751752
752 pub fn flush(ws: *WebSocket) std.io.Writer.Error!void {753 pub fn flush(ws: *WebSocket) Writer.Error!void {
753 try ws.output.flush();754 try ws.output.flush();
754 }755 }
755};756};
lib/std/io.zig-3
...@@ -72,8 +72,6 @@ pub const Limit = enum(usize) {...@@ -72,8 +72,6 @@ pub const Limit = enum(usize) {
72pub const Reader = @import("io/Reader.zig");72pub const Reader = @import("io/Reader.zig");
73pub const Writer = @import("io/Writer.zig");73pub const Writer = @import("io/Writer.zig");
7474
75pub const AllocatingWriter = @import("io/AllocatingWriter.zig");
76
77pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream;75pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream;
78pub const changeDetectionStream = @import("io/change_detection_stream.zig").changeDetectionStream;76pub const changeDetectionStream = @import("io/change_detection_stream.zig").changeDetectionStream;
7977
...@@ -485,7 +483,6 @@ pub fn PollFiles(comptime StreamEnum: type) type {...@@ -485,7 +483,6 @@ pub fn PollFiles(comptime StreamEnum: type) type {
485}483}
486484
487test {485test {
488 _ = AllocatingWriter;
489 _ = Reader;486 _ = Reader;
490 _ = Writer;487 _ = Writer;
491 _ = @import("io/test.zig");488 _ = @import("io/test.zig");
lib/std/io/AllocatingWriter.zig deleted-215
...@@ -1,215 +0,0 @@
1//! While it is possible to use `std.ArrayList` as the underlying writer when
2//! using `std.io.BufferedWriter` by populating the `std.io.Writer` interface
3//! and then using an empty buffer, it means that every use of
4//! `std.io.BufferedWriter` will go through the vtable, including for
5//! functions such as `writeByte`. This API instead maintains
6//! `std.io.BufferedWriter` state such that it writes to the unused capacity of
7//! an array list, filling it up completely before making a call through the
8//! vtable, causing a resize. Consequently, the same, optimized, non-generic
9//! machine code that uses `std.io.Reader`, such as formatted printing,
10//! takes the hot paths when using this API.
11
12const std = @import("../std.zig");
13const AllocatingWriter = @This();
14const assert = std.debug.assert;
15
16/// This is missing the data stored in `buffered_writer`. See `getWritten` for
17/// returning a slice that includes both.
18written: []u8,
19allocator: std.mem.Allocator,
20/// When using this API, it is not necessary to call
21/// `std.io.BufferedWriter.flush`.
22buffered_writer: std.io.BufferedWriter,
23
24const vtable: std.io.Writer.VTable = .{
25 .writeSplat = writeSplat,
26 .writeFile = writeFile,
27};
28
29/// Sets the `AllocatingWriter` to an empty state.
30pub fn init(aw: *AllocatingWriter, allocator: std.mem.Allocator) void {
31 aw.initOwnedSlice(allocator, &.{});
32}
33
34pub fn initCapacity(aw: *AllocatingWriter, allocator: std.mem.Allocator, capacity: usize) error{OutOfMemory}!void {
35 const initial_buffer = try allocator.alloc(u8, capacity);
36 aw.initOwnedSlice(allocator, initial_buffer);
37}
38
39pub fn initOwnedSlice(aw: *AllocatingWriter, allocator: std.mem.Allocator, slice: []u8) void {
40 aw.* = .{
41 .written = slice[0..0],
42 .allocator = allocator,
43 .buffered_writer = .{
44 .unbuffered_writer = .{
45 .context = aw,
46 .vtable = &vtable,
47 },
48 .buffer = slice,
49 },
50 };
51}
52
53pub fn deinit(aw: *AllocatingWriter) void {
54 const written = aw.written;
55 aw.allocator.free(written.ptr[0 .. written.len + aw.buffered_writer.buffer.len]);
56 aw.* = undefined;
57}
58
59/// Replaces `array_list` with empty, taking ownership of the memory.
60pub fn fromArrayList(
61 aw: *AllocatingWriter,
62 allocator: std.mem.Allocator,
63 array_list: *std.ArrayListUnmanaged(u8),
64) *std.io.BufferedWriter {
65 aw.* = .{
66 .written = array_list.items,
67 .allocator = allocator,
68 .buffered_writer = .{
69 .unbuffered_writer = .{
70 .context = aw,
71 .vtable = &vtable,
72 },
73 .buffer = array_list.unusedCapacitySlice(),
74 },
75 };
76 array_list.* = .empty;
77 return &aw.buffered_writer;
78}
79
80/// Returns an array list that takes ownership of the allocated memory.
81/// Resets the `AllocatingWriter` to an empty state.
82pub fn toArrayList(aw: *AllocatingWriter) std.ArrayListUnmanaged(u8) {
83 const bw = &aw.buffered_writer;
84 const written = aw.written;
85 const result: std.ArrayListUnmanaged(u8) = .{
86 .items = written.ptr[0 .. written.len + bw.end],
87 .capacity = written.len + bw.buffer.len,
88 };
89 aw.written = &.{};
90 bw.buffer = &.{};
91 bw.end = 0;
92 return result;
93}
94
95pub fn toOwnedSlice(aw: *AllocatingWriter) error{OutOfMemory}![]u8 {
96 var list = aw.toArrayList();
97 return list.toOwnedSlice(aw.allocator);
98}
99
100pub fn toOwnedSliceSentinel(aw: *AllocatingWriter, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 {
101 const gpa = aw.allocator;
102 var list = toArrayList(aw);
103 return list.toOwnedSliceSentinel(gpa, sentinel);
104}
105
106fn setArrayList(aw: *AllocatingWriter, list: std.ArrayListUnmanaged(u8)) void {
107 aw.written = list.items;
108 aw.buffered_writer.buffer = list.unusedCapacitySlice();
109}
110
111pub fn getWritten(aw: *AllocatingWriter) []u8 {
112 const bw = &aw.buffered_writer;
113 const end = aw.buffered_writer.end;
114 const written = aw.written.ptr[0 .. aw.written.len + end];
115 aw.written = written;
116 bw.buffer = bw.buffer[end..];
117 bw.end = 0;
118 return written;
119}
120
121pub fn shrinkRetainingCapacity(aw: *AllocatingWriter, new_len: usize) void {
122 const bw = &aw.buffered_writer;
123 bw.buffer = aw.written.ptr[new_len .. aw.written.len + bw.buffer.len];
124 bw.end = 0;
125 aw.written.len = new_len;
126}
127
128pub fn clearRetainingCapacity(aw: *AllocatingWriter) void {
129 aw.shrinkRetainingCapacity(0);
130}
131
132fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
133 assert(data.len != 0);
134 const aw: *AllocatingWriter = @alignCast(@ptrCast(context));
135 const start_len = aw.written.len;
136 const bw = &aw.buffered_writer;
137 const skip_first = data[0].ptr == aw.written.ptr + start_len;
138 const items_len = if (skip_first) start_len + data[0].len else start_len;
139 var list: std.ArrayListUnmanaged(u8) = .{
140 .items = aw.written.ptr[0..items_len],
141 .capacity = start_len + bw.buffer.len,
142 };
143 defer setArrayList(aw, list);
144 const rest = if (splat == 0) data[1 .. data.len - 1] else data[1..];
145 const pattern = data[data.len - 1];
146 const remaining_splat = splat - 1;
147 var new_capacity: usize = list.capacity + pattern.len * remaining_splat;
148 for (rest) |bytes| new_capacity += bytes.len;
149 list.ensureTotalCapacity(aw.allocator, new_capacity + 1) catch return error.WriteFailed;
150 for (rest) |bytes| list.appendSliceAssumeCapacity(bytes);
151 if (pattern.len == 1) {
152 list.appendNTimesAssumeCapacity(pattern[0], remaining_splat);
153 } else {
154 for (0..remaining_splat) |_| list.appendSliceAssumeCapacity(pattern);
155 }
156 aw.written = list.items;
157 bw.buffer = list.unusedCapacitySlice();
158 return list.items.len - start_len;
159}
160
161fn writeFile(
162 context: ?*anyopaque,
163 file_reader: *std.fs.File.Reader,
164 limit: std.io.Limit,
165 headers_and_trailers_full: []const []const u8,
166 headers_len_full: usize,
167) std.io.Writer.FileError!usize {
168 if (std.fs.File.Handle == void) return error.Unimplemented;
169 const aw: *AllocatingWriter = @alignCast(@ptrCast(context));
170 const gpa = aw.allocator;
171 var list = aw.toArrayList();
172 defer setArrayList(aw, list);
173 const start_len = list.items.len;
174 const headers_and_trailers, const headers_len = if (headers_len_full >= 1) b: {
175 assert(headers_and_trailers_full[0].ptr == list.items.ptr + start_len);
176 list.items.len += headers_and_trailers_full[0].len;
177 break :b .{ headers_and_trailers_full[1..], headers_len_full - 1 };
178 } else .{ headers_and_trailers_full, headers_len_full };
179 const trailers = headers_and_trailers[headers_len..];
180 const pos = file_reader.pos;
181
182 const additional = if (file_reader.getSize()) |size| size - pos else |_| std.atomic.cache_line;
183 var new_capacity: usize = list.capacity + limit.minInt(additional);
184 for (headers_and_trailers) |bytes| new_capacity += bytes.len;
185 list.ensureTotalCapacity(gpa, new_capacity) catch return error.WriteFailed;
186 for (headers_and_trailers[0..headers_len]) |bytes| list.appendSliceAssumeCapacity(bytes);
187 const dest = limit.slice(list.items.ptr[list.items.len..list.capacity]);
188 const n = file_reader.read(dest) catch |err| switch (err) {
189 error.ReadFailed => return error.ReadFailed,
190 error.EndOfStream => 0,
191 };
192 const is_end = if (file_reader.getSize()) |size| n >= size - pos else |_| n == 0;
193 if (is_end) {
194 new_capacity = list.capacity;
195 for (trailers) |bytes| new_capacity += bytes.len;
196 list.ensureTotalCapacity(gpa, new_capacity) catch return error.WriteFailed;
197 for (trailers) |bytes| list.appendSliceAssumeCapacity(bytes);
198 } else {
199 list.items.len += n;
200 }
201 return list.items.len - start_len;
202}
203
204test AllocatingWriter {
205 var aw: AllocatingWriter = undefined;
206 aw.init(std.testing.allocator);
207 defer aw.deinit();
208 const bw = &aw.buffered_writer;
209
210 const x: i32 = 42;
211 const y: i32 = 1234;
212 try bw.print("x: {}\ny: {}\n", .{ x, y });
213
214 try std.testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", aw.getWritten());
215}
lib/std/io/BufferedWriter.zig deleted-1859
...@@ -1,1859 +0,0 @@
1const std = @import("../std.zig");
2const BufferedWriter = @This();
3const assert = std.debug.assert;
4const native_endian = @import("builtin").target.cpu.arch.endian();
5const Writer = std.io.Writer;
6const Allocator = std.mem.Allocator;
7const testing = std.testing;
8const Limit = std.io.Limit;
9const File = std.fs.File;
10
11/// Underlying stream to send bytes to.
12///
13/// A write will only be sent here if it could not fit into `buffer`, or if it
14/// is a `writeFile`.
15///
16/// `unbuffered_writer` may modify `buffer` if the number of bytes returned
17/// equals number of bytes provided. This property is exploited by
18/// `std.io.AllocatingWriter` for example.
19unbuffered_writer: Writer,
20/// If this has length zero, the writer is unbuffered, and `flush` is a no-op.
21buffer: []u8,
22/// In `buffer` before this are buffered bytes, after this is `undefined`.
23end: usize = 0,
24/// Tracks total number of bytes written to this `BufferedWriter`. This value
25/// only increases. In the case of fixed mode, this value always equals `end`.
26count: usize = 0,
27
28/// Number of slices to store on the stack, when trying to send as many byte
29/// vectors through the underlying write calls as possible.
30pub const max_buffers_len = 8;
31
32/// Although `BufferedWriter` can easily satisfy the `Writer` interface, it's
33/// generally more practical to pass a `BufferedWriter` instance itself around,
34/// since it will result in fewer calls across vtable boundaries.
35pub fn writer(bw: *BufferedWriter) Writer {
36 return .{
37 .context = bw,
38 .vtable = &.{
39 .writeSplat = passthruWriteSplat,
40 .writeFile = passthruWriteFile,
41 },
42 };
43}
44
45const fixed_vtable: Writer.VTable = .{
46 .writeSplat = fixedWriteSplat,
47 .writeFile = Writer.unimplementedWriteFile,
48};
49
50/// Replaces the `BufferedWriter` with one that writes to `buffer` and returns
51/// `error.WriteFailed` when it is full. `end` and `count` will always be
52/// equal.
53pub fn initFixed(bw: *BufferedWriter, buffer: []u8) void {
54 bw.* = .{
55 .unbuffered_writer = .{
56 .context = bw,
57 .vtable = &fixed_vtable,
58 },
59 .buffer = buffer,
60 };
61}
62
63pub fn hashed(bw: *BufferedWriter, hasher: anytype) Writer.Hashed(@TypeOf(hasher)) {
64 return .{ .out = bw, .hasher = hasher };
65}
66
67/// This function is available when using `initFixed`.
68pub fn getWritten(bw: *const BufferedWriter) []u8 {
69 assert(bw.unbuffered_writer.vtable == &fixed_vtable);
70 return bw.buffer[0..bw.end];
71}
72
73/// This function is available when using `initFixed`.
74pub fn reset(bw: *BufferedWriter) void {
75 assert(bw.unbuffered_writer.vtable == &fixed_vtable);
76 bw.end = 0;
77 bw.count = 0;
78}
79
80pub fn flush(bw: *BufferedWriter) Writer.Error!void {
81 const send_buffer = bw.buffer[0..bw.end];
82 var index: usize = 0;
83 while (index < send_buffer.len) index += try bw.unbuffered_writer.writeVec(&.{send_buffer[index..]});
84 bw.end = 0;
85}
86
87pub fn flushLimit(bw: *BufferedWriter, limit: Limit) Writer.Error!void {
88 const buffer = limit.slice(bw.buffer[0..bw.end]);
89 var index: usize = 0;
90 while (index < buffer.len) index += try bw.unbuffered_writer.writeVec(&.{buffer[index..]});
91 const remainder = bw.buffer[index..];
92 std.mem.copyForwards(u8, bw.buffer[0..remainder.len], remainder);
93 bw.end = remainder.len;
94}
95
96pub fn unusedCapacitySlice(bw: *const BufferedWriter) []u8 {
97 return bw.buffer[bw.end..];
98}
99
100/// Asserts the provided buffer has total capacity enough for `len`.
101///
102/// Advances the buffer end position by `len`.
103pub fn writableArray(bw: *BufferedWriter, comptime len: usize) Writer.Error!*[len]u8 {
104 const big_slice = try bw.writableSliceGreedy(len);
105 advance(bw, len);
106 return big_slice[0..len];
107}
108
109/// Asserts the provided buffer has total capacity enough for `len`.
110///
111/// Advances the buffer end position by `len`.
112pub fn writableSlice(bw: *BufferedWriter, len: usize) Writer.Error![]u8 {
113 const big_slice = try bw.writableSliceGreedy(len);
114 advance(bw, len);
115 return big_slice[0..len];
116}
117
118/// Asserts the provided buffer has total capacity enough for `minimum_length`.
119///
120/// Does not `advance` the buffer end position.
121///
122/// If `minimum_length` is zero, this is equivalent to `unusedCapacitySlice`.
123pub fn writableSliceGreedy(bw: *BufferedWriter, minimum_length: usize) Writer.Error![]u8 {
124 assert(bw.buffer.len >= minimum_length);
125 const cap_slice = bw.buffer[bw.end..];
126 if (cap_slice.len >= minimum_length) {
127 @branchHint(.likely);
128 return cap_slice;
129 }
130 const buffer = bw.buffer[0..bw.end];
131 const n = try bw.unbuffered_writer.writeVec(&.{buffer});
132 if (n == buffer.len) {
133 @branchHint(.likely);
134 bw.end = 0;
135 return bw.buffer;
136 }
137 if (n > 0) {
138 const remainder = buffer[n..];
139 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
140 bw.end = remainder.len;
141 }
142 return bw.buffer[bw.end..];
143}
144
145pub fn ensureUnusedCapacity(bw: *BufferedWriter, n: usize) Writer.Error!void {
146 _ = try writableSliceGreedy(bw, n);
147}
148
149pub fn undo(bw: *BufferedWriter, n: usize) void {
150 bw.end -= n;
151 bw.count -= n;
152}
153
154/// After calling `writableSliceGreedy`, this function tracks how many bytes
155/// were written to it.
156///
157/// This is not needed when using `writableSlice` or `writableArray`.
158pub fn advance(bw: *BufferedWriter, n: usize) void {
159 const new_end = bw.end + n;
160 assert(new_end <= bw.buffer.len);
161 bw.end = new_end;
162 bw.count += n;
163}
164
165/// The `data` parameter is mutable because this function needs to mutate the
166/// fields in order to handle partial writes from `Writer.VTable.writeSplat`.
167pub fn writeVecAll(bw: *BufferedWriter, data: [][]const u8) Writer.Error!void {
168 var index: usize = 0;
169 var truncate: usize = 0;
170 while (index < data.len) {
171 {
172 const untruncated = data[index];
173 data[index] = untruncated[truncate..];
174 defer data[index] = untruncated;
175 truncate += try bw.writeVec(data[index..]);
176 }
177 while (index < data.len and truncate >= data[index].len) {
178 truncate -= data[index].len;
179 index += 1;
180 }
181 }
182}
183
184/// The `data` parameter is mutable because this function needs to mutate the
185/// fields in order to handle partial writes from `Writer.VTable.writeSplat`.
186pub fn writeSplatAll(bw: *BufferedWriter, data: [][]const u8, splat: usize) Writer.Error!void {
187 var index: usize = 0;
188 var truncate: usize = 0;
189 var remaining_splat = splat;
190 while (index + 1 < data.len) {
191 {
192 const untruncated = data[index];
193 data[index] = untruncated[truncate..];
194 defer data[index] = untruncated;
195 truncate += try bw.writeSplat(data[index..], remaining_splat);
196 }
197 while (truncate >= data[index].len) {
198 if (index + 1 < data.len) {
199 truncate -= data[index].len;
200 index += 1;
201 } else {
202 const last = data[data.len - 1];
203 remaining_splat -= @divExact(truncate, last.len);
204 while (remaining_splat > 0) {
205 const n = try bw.writeSplat(data[data.len - 1 ..][0..1], remaining_splat);
206 remaining_splat -= @divExact(n, last.len);
207 }
208 return;
209 }
210 }
211 }
212}
213
214/// If the number of bytes to write based on `data` and `splat` fits inside
215/// `unusedCapacitySlice`, this function is guaranteed to not fail, not call
216/// into the underlying writer, and return the full number of bytes.
217pub fn writeSplat(bw: *BufferedWriter, data: []const []const u8, splat: usize) Writer.Error!usize {
218 return passthruWriteSplat(bw, data, splat);
219}
220
221/// If the total number of bytes of `data` fits inside `unusedCapacitySlice`,
222/// this function is guaranteed to not fail, not call into the underlying
223/// writer, and return the total bytes inside `data`.
224pub fn writeVec(bw: *BufferedWriter, data: []const []const u8) Writer.Error!usize {
225 return passthruWriteSplat(bw, data, 1);
226}
227
228/// Equivalent to `writeSplat` but writes at most `limit` bytes.
229pub fn writeSplatLimit(
230 bw: *BufferedWriter,
231 data: []const []const u8,
232 splat: usize,
233 limit: Limit,
234) Writer.Error!usize {
235 _ = bw;
236 _ = data;
237 _ = splat;
238 _ = limit;
239 @panic("TODO");
240}
241
242fn passthruWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {
243 const bw: *BufferedWriter = @alignCast(@ptrCast(context));
244 const buffer = bw.buffer;
245 const start_end = bw.end;
246
247 var buffers: [max_buffers_len][]const u8 = undefined;
248 var end = start_end;
249 for (data, 0..) |bytes, i| {
250 const new_end = end + bytes.len;
251 if (new_end <= buffer.len) {
252 @branchHint(.likely);
253 @memcpy(buffer[end..new_end], bytes);
254 end = new_end;
255 continue;
256 }
257 if (end == 0) return track(&bw.count, try bw.unbuffered_writer.writeSplat(data, splat));
258 buffers[0] = buffer[0..end];
259 const remaining_data = data[i..];
260 const remaining_buffers = buffers[1..];
261 const len: usize = @min(remaining_data.len, remaining_buffers.len);
262 @memcpy(remaining_buffers[0..len], remaining_data[0..len]);
263 const send_buffers = buffers[0 .. len + 1];
264 if (len >= remaining_data.len) {
265 @branchHint(.likely);
266 // Made it past the headers, so we can enable splatting.
267 const n = try bw.unbuffered_writer.writeSplat(send_buffers, splat);
268 if (n < end) {
269 @branchHint(.unlikely);
270 const remainder = buffer[n..end];
271 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
272 bw.end = remainder.len;
273 return track(&bw.count, end - start_end);
274 }
275 bw.end = 0;
276 return track(&bw.count, n - start_end);
277 }
278 const n = try bw.unbuffered_writer.writeSplat(send_buffers, 1);
279 if (n < end) {
280 @branchHint(.unlikely);
281 const remainder = buffer[n..end];
282 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
283 bw.end = remainder.len;
284 return track(&bw.count, end - start_end);
285 }
286 bw.end = 0;
287 return track(&bw.count, n - start_end);
288 }
289
290 const pattern = data[data.len - 1];
291
292 if (splat == 0) {
293 @branchHint(.unlikely);
294 // It was added in the loop above; undo it here.
295 end -= pattern.len;
296 bw.end = end;
297 return track(&bw.count, end - start_end);
298 }
299
300 const remaining_splat = splat - 1;
301
302 switch (pattern.len) {
303 0 => {
304 bw.end = end;
305 return track(&bw.count, end - start_end);
306 },
307 1 => {
308 const new_end = end + remaining_splat;
309 if (new_end <= buffer.len) {
310 @branchHint(.likely);
311 @memset(buffer[end..new_end], pattern[0]);
312 bw.end = new_end;
313 return track(&bw.count, new_end - start_end);
314 }
315 buffers[0] = buffer[0..end];
316 buffers[1] = pattern;
317 const n = try bw.unbuffered_writer.writeSplat(buffers[0..2], remaining_splat);
318 if (n < end) {
319 @branchHint(.unlikely);
320 const remainder = buffer[n..end];
321 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
322 bw.end = remainder.len;
323 return track(&bw.count, end - start_end);
324 }
325 bw.end = 0;
326 return track(&bw.count, n - start_end);
327 },
328 else => {
329 const new_end = end + pattern.len * remaining_splat;
330 if (new_end <= buffer.len) {
331 @branchHint(.likely);
332 while (end < new_end) : (end += pattern.len) {
333 @memcpy(buffer[end..][0..pattern.len], pattern);
334 }
335 bw.end = new_end;
336 return track(&bw.count, new_end - start_end);
337 }
338 buffers[0] = buffer[0..end];
339 buffers[1] = pattern;
340 const n = try bw.unbuffered_writer.writeSplat(buffers[0..2], remaining_splat);
341 if (n < end) {
342 @branchHint(.unlikely);
343 const remainder = buffer[n..end];
344 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
345 bw.end = remainder.len;
346 return track(&bw.count, end - start_end);
347 }
348 bw.end = 0;
349 return track(&bw.count, n - start_end);
350 },
351 }
352}
353
354fn track(count: *usize, n: usize) usize {
355 count.* += n;
356 return n;
357}
358
359/// When this function is called it means the buffer got full, so it's time
360/// to return an error. However, we still need to make sure all of the
361/// available buffer has been filled.
362fn fixedWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {
363 const bw: *BufferedWriter = @alignCast(@ptrCast(context));
364 for (data) |bytes| {
365 const dest = bw.buffer[bw.end..];
366 if (dest.len == 0) return error.WriteFailed;
367 const len = @min(bytes.len, dest.len);
368 @memcpy(dest[0..len], bytes[0..len]);
369 bw.end += len;
370 bw.count = bw.end;
371 }
372 const pattern = data[data.len - 1];
373 const dest = bw.buffer[bw.end..];
374 switch (pattern.len) {
375 0 => unreachable,
376 1 => @memset(dest, pattern[0]),
377 else => for (0..splat - 1) |i| @memcpy(dest[i * pattern.len ..][0..pattern.len], pattern),
378 }
379 bw.end = bw.buffer.len;
380 bw.count = bw.end;
381 return error.WriteFailed;
382}
383
384pub fn write(bw: *BufferedWriter, bytes: []const u8) Writer.Error!usize {
385 const buffer = bw.buffer;
386 const end = bw.end;
387 const new_end = end + bytes.len;
388 if (new_end > buffer.len) {
389 var data: [2][]const u8 = .{ buffer[0..end], bytes };
390 const n = try bw.unbuffered_writer.writeVec(&data);
391 if (n < end) {
392 @branchHint(.unlikely);
393 const remainder = buffer[n..end];
394 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
395 bw.end = remainder.len;
396 return 0;
397 }
398 bw.end = 0;
399 return track(&bw.count, n - end);
400 }
401 @memcpy(buffer[end..new_end], bytes);
402 bw.end = new_end;
403 return track(&bw.count, bytes.len);
404}
405
406/// Calls `write` as many times as necessary such that all of `bytes` are
407/// transferred.
408pub fn writeAll(bw: *BufferedWriter, bytes: []const u8) Writer.Error!void {
409 var index: usize = 0;
410 while (index < bytes.len) index += try bw.write(bytes[index..]);
411}
412
413pub fn print(bw: *BufferedWriter, comptime format: []const u8, args: anytype) Writer.Error!void {
414 try std.fmt.format(bw, format, args);
415}
416
417pub fn writeByte(bw: *BufferedWriter, byte: u8) Writer.Error!void {
418 const buffer = bw.buffer[0..bw.end];
419 if (buffer.len < bw.buffer.len) {
420 @branchHint(.likely);
421 buffer.ptr[buffer.len] = byte;
422 bw.end = buffer.len + 1;
423 bw.count += 1;
424 return;
425 }
426 var buffers: [2][]const u8 = .{ buffer, &.{byte} };
427 while (true) {
428 const n = try bw.unbuffered_writer.writeVec(&buffers);
429 if (n == 0) {
430 @branchHint(.unlikely);
431 continue;
432 }
433 bw.count += 1;
434 if (n >= buffer.len) {
435 @branchHint(.likely);
436 if (n > buffer.len) {
437 @branchHint(.likely);
438 bw.end = 0;
439 return;
440 } else {
441 buffer[0] = byte;
442 bw.end = 1;
443 return;
444 }
445 }
446 const remainder = buffer[n..];
447 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
448 buffer[remainder.len] = byte;
449 bw.end = remainder.len + 1;
450 return;
451 }
452}
453
454/// Writes the same byte many times, performing the underlying write call as
455/// many times as necessary.
456pub fn splatByteAll(bw: *BufferedWriter, byte: u8, n: usize) Writer.Error!void {
457 var remaining: usize = n;
458 while (remaining > 0) remaining -= try bw.splatByte(byte, remaining);
459}
460
461/// Writes the same byte many times, allowing short writes.
462///
463/// Does maximum of one underlying `Writer.VTable.writeSplat`.
464pub fn splatByte(bw: *BufferedWriter, byte: u8, n: usize) Writer.Error!usize {
465 return passthruWriteSplat(bw, &.{&.{byte}}, n);
466}
467
468/// Writes the same slice many times, performing the underlying write call as
469/// many times as necessary.
470pub fn splatBytesAll(bw: *BufferedWriter, bytes: []const u8, splat: usize) Writer.Error!void {
471 var remaining_bytes: usize = bytes.len * splat;
472 remaining_bytes -= try bw.splatBytes(bytes, splat);
473 while (remaining_bytes > 0) {
474 const leftover = remaining_bytes % bytes.len;
475 const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover ..], bytes };
476 remaining_bytes -= try bw.splatBytes(&buffers, splat);
477 }
478}
479
480/// Writes the same slice many times, allowing short writes.
481///
482/// Does maximum of one underlying `Writer.VTable.writeSplat`.
483pub fn splatBytes(bw: *BufferedWriter, bytes: []const u8, n: usize) Writer.Error!usize {
484 return passthruWriteSplat(bw, &.{bytes}, n);
485}
486
487/// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes.
488pub inline fn writeInt(bw: *BufferedWriter, comptime T: type, value: T, endian: std.builtin.Endian) Writer.Error!void {
489 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
490 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
491 return bw.writeAll(&bytes);
492}
493
494pub fn writeStruct(bw: *BufferedWriter, value: anytype) Writer.Error!void {
495 // Only extern and packed structs have defined in-memory layout.
496 comptime assert(@typeInfo(@TypeOf(value)).@"struct".layout != .auto);
497 return bw.writeAll(std.mem.asBytes(&value));
498}
499
500/// The function is inline to avoid the dead code in case `endian` is
501/// comptime-known and matches host endianness.
502/// TODO: make sure this value is not a reference type
503pub inline fn writeStructEndian(bw: *BufferedWriter, value: anytype, endian: std.builtin.Endian) Writer.Error!void {
504 if (native_endian == endian) {
505 return bw.writeStruct(value);
506 } else {
507 var copy = value;
508 std.mem.byteSwapAllFields(@TypeOf(value), &copy);
509 return bw.writeStruct(copy);
510 }
511}
512
513pub inline fn writeSliceEndian(
514 bw: *BufferedWriter,
515 Elem: type,
516 slice: []const Elem,
517 endian: std.builtin.Endian,
518) Writer.Error!void {
519 if (native_endian == endian) {
520 return writeAll(bw, @ptrCast(slice));
521 } else {
522 return bw.writeArraySwap(bw, Elem, slice);
523 }
524}
525
526/// Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
527pub fn writeSliceSwap(bw: *BufferedWriter, Elem: type, slice: []const Elem) Writer.Error!void {
528 // copy to storage first, then swap in place
529 _ = bw;
530 _ = slice;
531 @panic("TODO");
532}
533
534/// Unlike `writeSplat` and `writeVec`, this function will call into the
535/// underlying writer even if there is enough buffer capacity for the file
536/// contents.
537///
538/// Although it would be possible to eliminate `error.Unimplemented` from
539/// the error set by reading directly into the buffer in such case,
540/// this is not done because it is more efficient to do it in `writeFileAll`
541/// so that the error does not occur with each write.
542///
543/// See `writeFileReading` for an alternative that does not have
544/// `error.Unimplemented` in the error set.
545pub fn writeFile(
546 bw: *BufferedWriter,
547 file_reader: *File.Reader,
548 limit: Limit,
549 headers_and_trailers: []const []const u8,
550 headers_len: usize,
551) Writer.FileError!usize {
552 return passthruWriteFile(bw, file_reader, limit, headers_and_trailers, headers_len);
553}
554
555/// Returning zero bytes means end of stream.
556///
557/// Asserts nonzero buffer capacity.
558pub fn writeFileReading(
559 bw: *BufferedWriter,
560 file_reader: *File.Reader,
561 limit: Limit,
562) Writer.ReadingFileError!usize {
563 const dest = limit.slice(try bw.writableSliceGreedy(1));
564 const n = file_reader.read(dest) catch |err| switch (err) {
565 error.EndOfStream => 0,
566 error.ReadFailed => return error.ReadFailed,
567 };
568 bw.advance(n);
569 return n;
570}
571
572fn passthruWriteFile(
573 context: ?*anyopaque,
574 file_reader: *File.Reader,
575 limit: Limit,
576 headers_and_trailers: []const []const u8,
577 headers_len: usize,
578) Writer.FileError!usize {
579 const bw: *BufferedWriter = @alignCast(@ptrCast(context));
580 const buffer = bw.buffer;
581 if (buffer.len == 0) return track(
582 &bw.count,
583 try bw.unbuffered_writer.writeFile(file_reader, limit, headers_and_trailers, headers_len),
584 );
585 const start_end = bw.end;
586 const headers = headers_and_trailers[0..headers_len];
587 const trailers = headers_and_trailers[headers_len..];
588 var buffers: [max_buffers_len][]const u8 = undefined;
589 var end = start_end;
590 for (headers, 0..) |header, i| {
591 const new_end = end + header.len;
592 if (new_end <= buffer.len) {
593 @branchHint(.likely);
594 @memcpy(buffer[end..new_end], header);
595 end = new_end;
596 continue;
597 }
598 buffers[0] = buffer[0..end];
599 const remaining_headers = headers[i..];
600 const remaining_buffers = buffers[1..];
601 const buffers_len: usize = @min(remaining_headers.len, remaining_buffers.len);
602 @memcpy(remaining_buffers[0..buffers_len], remaining_headers[0..buffers_len]);
603 if (buffers_len >= remaining_headers.len) {
604 // Made it past the headers, so we can call `writeFile`.
605 const remaining_buffers_for_trailers = remaining_buffers[buffers_len..];
606 const send_trailers_len: usize = @min(trailers.len, remaining_buffers_for_trailers.len);
607 @memcpy(remaining_buffers_for_trailers[0..send_trailers_len], trailers[0..send_trailers_len]);
608 const send_headers_len = 1 + buffers_len;
609 const send_buffers = buffers[0 .. send_headers_len + send_trailers_len];
610 const n = try bw.unbuffered_writer.writeFile(file_reader, limit, send_buffers, send_headers_len);
611 if (n < end) {
612 @branchHint(.unlikely);
613 const remainder = buffer[n..end];
614 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
615 bw.end = remainder.len;
616 return track(&bw.count, end - start_end);
617 }
618 bw.end = 0;
619 return track(&bw.count, n - start_end);
620 }
621 // Have not made it past the headers yet; must call `writeVec`.
622 const n = try bw.unbuffered_writer.writeVec(buffers[0 .. buffers_len + 1]);
623 if (n < end) {
624 @branchHint(.unlikely);
625 const remainder = buffer[n..end];
626 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
627 bw.end = remainder.len;
628 return track(&bw.count, end - start_end);
629 }
630 bw.end = 0;
631 return track(&bw.count, n - start_end);
632 }
633 // All headers written to buffer.
634 buffers[0] = buffer[0..end];
635 const remaining_buffers = buffers[1..];
636 const send_trailers_len: usize = @min(trailers.len, remaining_buffers.len);
637 @memcpy(remaining_buffers[0..send_trailers_len], trailers[0..send_trailers_len]);
638 const send_headers_len = @intFromBool(end != 0);
639 const send_buffers = buffers[1 - send_headers_len .. 1 + send_trailers_len];
640 const n = try bw.unbuffered_writer.writeFile(file_reader, limit, send_buffers, send_headers_len);
641 if (n < end) {
642 @branchHint(.unlikely);
643 const remainder = buffer[n..end];
644 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
645 bw.end = remainder.len;
646 return track(&bw.count, end - start_end);
647 }
648 bw.end = 0;
649 return track(&bw.count, n - start_end);
650}
651
652pub const WriteFileOptions = struct {
653 limit: Limit = .unlimited,
654 /// Headers and trailers must be passed together so that in case `len` is
655 /// zero, they can be forwarded directly to `Writer.VTable.writeSplat`.
656 ///
657 /// The parameter is mutable because this function needs to mutate the
658 /// fields in order to handle partial writes from `Writer.VTable.writeFile`.
659 headers_and_trailers: [][]const u8 = &.{},
660 /// The number of trailers is inferred from
661 /// `headers_and_trailers.len - headers_len`.
662 headers_len: usize = 0,
663};
664
665pub fn writeFileAll(
666 bw: *BufferedWriter,
667 file_reader: *std.fs.File.Reader,
668 options: WriteFileOptions,
669) Writer.ReadingFileError!void {
670 const headers_and_trailers = options.headers_and_trailers;
671 const headers = headers_and_trailers[0..options.headers_len];
672 var remaining = options.limit;
673 var i: usize = 0;
674 while (true) {
675 const before_pos = file_reader.pos;
676 var n = bw.writeFile(file_reader, remaining, headers_and_trailers[i..], headers.len - i) catch |err| switch (err) {
677 error.ReadFailed => return error.ReadFailed,
678 error.WriteFailed => return error.WriteFailed,
679 error.Unimplemented => {
680 file_reader.mode = file_reader.mode.toReading();
681 try bw.writeVecAll(headers[i..]);
682 try bw.writeFileReadingAll(file_reader, remaining);
683 try bw.writeVecAll(headers_and_trailers[headers.len..]);
684 return;
685 },
686 };
687 while (i < headers.len and n >= headers[i].len) {
688 n -= headers[i].len;
689 i += 1;
690 }
691 if (i < headers.len) {
692 headers[i] = headers[i][n..];
693 continue;
694 }
695 const file_bytes_consumed = file_reader.pos - before_pos;
696 remaining = remaining.subtract(file_bytes_consumed).?;
697 const size = file_reader.size orelse continue; // End of file not yet reached.
698 if (file_reader.pos < size) continue; // End of file not yet reached.
699 n -= file_bytes_consumed; // Trailers reached.
700 while (i < headers_and_trailers.len and n >= headers_and_trailers[i].len) {
701 n -= headers_and_trailers[i].len;
702 i += 1;
703 }
704 if (i < headers_and_trailers.len) {
705 headers_and_trailers[i] = headers_and_trailers[i][n..];
706 try bw.writeVecAll(headers_and_trailers[i..]);
707 return;
708 }
709 return;
710 }
711}
712
713/// Equivalent to `writeFileAll` but uses direct `pread` and `read` calls on
714/// `file` rather than `Writer.writeFile`. This is generally used as a fallback
715/// when the underlying implementation returns `error.Unimplemented`, which is
716/// why that error code does not appear in this function's error set.
717///
718/// Asserts nonzero buffer capacity.
719pub fn writeFileReadingAll(
720 bw: *BufferedWriter,
721 file_reader: *File.Reader,
722 limit: Limit,
723) Writer.ReadingFileError!void {
724 var remaining = limit;
725 while (remaining.nonzero()) {
726 const n = try writeFileReading(bw, file_reader, remaining);
727 if (n == 0) return;
728 remaining = remaining.subtract(n).?;
729 }
730}
731
732pub fn alignBuffer(
733 bw: *BufferedWriter,
734 buffer: []const u8,
735 width: usize,
736 alignment: std.fmt.Alignment,
737 fill: u8,
738) Writer.Error!void {
739 const padding = if (buffer.len < width) width - buffer.len else 0;
740 if (padding == 0) {
741 @branchHint(.likely);
742 return bw.writeAll(buffer);
743 }
744 switch (alignment) {
745 .left => {
746 try bw.writeAll(buffer);
747 try bw.splatByteAll(fill, padding);
748 },
749 .center => {
750 const left_padding = padding / 2;
751 const right_padding = (padding + 1) / 2;
752 try bw.splatByteAll(fill, left_padding);
753 try bw.writeAll(buffer);
754 try bw.splatByteAll(fill, right_padding);
755 },
756 .right => {
757 try bw.splatByteAll(fill, padding);
758 try bw.writeAll(buffer);
759 },
760 }
761}
762
763pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std.fmt.Options) Writer.Error!void {
764 return bw.alignBuffer(buffer, options.width orelse buffer.len, options.alignment, options.fill);
765}
766
767pub fn printAddress(bw: *BufferedWriter, value: anytype) Writer.Error!void {
768 const T = @TypeOf(value);
769 switch (@typeInfo(T)) {
770 .pointer => |info| {
771 try bw.writeAll(@typeName(info.child) ++ "@");
772 if (info.size == .slice)
773 try bw.printIntOptions(@intFromPtr(value.ptr), 16, .lower, .{})
774 else
775 try bw.printIntOptions(@intFromPtr(value), 16, .lower, .{});
776 return;
777 },
778 .optional => |info| {
779 if (@typeInfo(info.child) == .pointer) {
780 try bw.writeAll(@typeName(info.child) ++ "@");
781 try bw.printIntOptions(@intFromPtr(value), 16, .lower, .{});
782 return;
783 }
784 },
785 else => {},
786 }
787
788 @compileError("cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
789}
790
791pub fn printValue(
792 bw: *BufferedWriter,
793 comptime fmt: []const u8,
794 options: std.fmt.Options,
795 value: anytype,
796 max_depth: usize,
797) Writer.Error!void {
798 const T = @TypeOf(value);
799
800 if (comptime std.mem.eql(u8, fmt, "*")) {
801 return bw.printAddress(value);
802 }
803
804 const is_any = comptime std.mem.eql(u8, fmt, ANY);
805 if (!is_any and std.meta.hasMethod(T, "format")) {
806 if (fmt.len > 0 and fmt[0] == 'f') {
807 return value.format(bw, fmt[1..]);
808 } else if (fmt.len == 0) {
809 // after 0.15.0 is tagged, delete the hasMethod condition and this compile error
810 @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
811 }
812 }
813
814 switch (@typeInfo(T)) {
815 .float, .comptime_float => return bw.printFloat(if (is_any) "d" else fmt, options, value),
816 .int, .comptime_int => return bw.printInt(if (is_any) "d" else fmt, options, value),
817 .bool => {
818 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
819 return bw.alignBufferOptions(if (value) "true" else "false", options);
820 },
821 .void => {
822 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
823 return bw.alignBufferOptions("void", options);
824 },
825 .optional => {
826 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?')
827 stripOptionalOrErrorUnionSpec(fmt)
828 else if (is_any)
829 ANY
830 else
831 @compileError("cannot print optional without a specifier (i.e. {?} or {any})");
832 if (value) |payload| {
833 return bw.printValue(remaining_fmt, options, payload, max_depth);
834 } else {
835 return bw.alignBufferOptions("null", options);
836 }
837 },
838 .error_union => {
839 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '!')
840 stripOptionalOrErrorUnionSpec(fmt)
841 else if (is_any)
842 ANY
843 else
844 @compileError("cannot print error union without a specifier (i.e. {!} or {any})");
845 if (value) |payload| {
846 return bw.printValue(remaining_fmt, options, payload, max_depth);
847 } else |err| {
848 return bw.printValue("", options, err, max_depth);
849 }
850 },
851 .error_set => {
852 if (fmt.len == 1 and fmt[0] == 's') return bw.writeAll(@errorName(value));
853 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
854 try printErrorSet(bw, value);
855 },
856 .@"enum" => {
857 if (fmt.len == 1 and fmt[0] == 's') {
858 try bw.writeAll(@tagName(value));
859 return;
860 }
861 if (!is_any) {
862 if (fmt.len != 0) return printValue(bw, fmt, options, @intFromEnum(value), max_depth);
863 return printValue(bw, ANY, options, value, max_depth);
864 }
865 const enum_info = @typeInfo(T).@"enum";
866 if (enum_info.is_exhaustive) {
867 var vecs: [3][]const u8 = .{ @typeName(T), ".", @tagName(value) };
868 try bw.writeVecAll(&vecs);
869 return;
870 }
871 try bw.writeAll(@typeName(T));
872 @setEvalBranchQuota(3 * enum_info.fields.len);
873 inline for (enum_info.fields) |field| {
874 if (@intFromEnum(value) == field.value) {
875 try bw.writeAll(".");
876 try bw.writeAll(@tagName(value));
877 return;
878 }
879 }
880 try bw.writeByte('(');
881 try bw.printValue(ANY, options, @intFromEnum(value), max_depth);
882 try bw.writeByte(')');
883 },
884 .@"union" => |info| {
885 if (!is_any) {
886 if (fmt.len != 0) invalidFmtError(fmt, value);
887 return printValue(bw, ANY, options, value, max_depth);
888 }
889 try bw.writeAll(@typeName(T));
890 if (max_depth == 0) {
891 try bw.writeAll("{ ... }");
892 return;
893 }
894 if (info.tag_type) |UnionTagType| {
895 try bw.writeAll("{ .");
896 try bw.writeAll(@tagName(@as(UnionTagType, value)));
897 try bw.writeAll(" = ");
898 inline for (info.fields) |u_field| {
899 if (value == @field(UnionTagType, u_field.name)) {
900 try bw.printValue(ANY, options, @field(value, u_field.name), max_depth - 1);
901 }
902 }
903 try bw.writeAll(" }");
904 } else {
905 try bw.writeByte('@');
906 try bw.printIntOptions(@intFromPtr(&value), 16, .lower, options);
907 }
908 },
909 .@"struct" => |info| {
910 if (!is_any) {
911 if (fmt.len != 0) invalidFmtError(fmt, value);
912 return printValue(bw, ANY, options, value, max_depth);
913 }
914 if (info.is_tuple) {
915 // Skip the type and field names when formatting tuples.
916 if (max_depth == 0) {
917 try bw.writeAll("{ ... }");
918 return;
919 }
920 try bw.writeAll("{");
921 inline for (info.fields, 0..) |f, i| {
922 if (i == 0) {
923 try bw.writeAll(" ");
924 } else {
925 try bw.writeAll(", ");
926 }
927 try bw.printValue(ANY, options, @field(value, f.name), max_depth - 1);
928 }
929 try bw.writeAll(" }");
930 return;
931 }
932 try bw.writeAll(@typeName(T));
933 if (max_depth == 0) {
934 try bw.writeAll("{ ... }");
935 return;
936 }
937 try bw.writeAll("{");
938 inline for (info.fields, 0..) |f, i| {
939 if (i == 0) {
940 try bw.writeAll(" .");
941 } else {
942 try bw.writeAll(", .");
943 }
944 try bw.writeAll(f.name);
945 try bw.writeAll(" = ");
946 try bw.printValue(ANY, options, @field(value, f.name), max_depth - 1);
947 }
948 try bw.writeAll(" }");
949 },
950 .pointer => |ptr_info| switch (ptr_info.size) {
951 .one => switch (@typeInfo(ptr_info.child)) {
952 .array, .@"enum", .@"union", .@"struct" => {
953 return bw.printValue(fmt, options, value.*, max_depth);
954 },
955 else => {
956 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
957 try bw.writeVecAll(&buffers);
958 try bw.printIntOptions(@intFromPtr(value), 16, .lower, options);
959 return;
960 },
961 },
962 .many, .c => {
963 if (ptr_info.sentinel() != null)
964 return bw.printValue(fmt, options, std.mem.span(value), max_depth);
965 if (fmt.len == 1 and fmt[0] == 's' and ptr_info.child == u8)
966 return bw.alignBufferOptions(std.mem.span(value), options);
967 if (!is_any and fmt.len == 0)
968 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
969 if (!is_any and fmt.len != 0)
970 invalidFmtError(fmt, value);
971 try bw.printAddress(value);
972 },
973 .slice => {
974 if (!is_any and fmt.len == 0)
975 @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})");
976 if (max_depth == 0)
977 return bw.writeAll("{ ... }");
978 if (ptr_info.child == u8) switch (fmt.len) {
979 1 => switch (fmt[0]) {
980 's' => return bw.alignBufferOptions(value, options),
981 'x' => return bw.printHex(value, .lower),
982 'X' => return bw.printHex(value, .upper),
983 else => {},
984 },
985 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') {
986 return bw.printBase64(value);
987 },
988 else => {},
989 };
990 try bw.writeAll("{ ");
991 for (value, 0..) |elem, i| {
992 try bw.printValue(fmt, options, elem, max_depth - 1);
993 if (i != value.len - 1) {
994 try bw.writeAll(", ");
995 }
996 }
997 try bw.writeAll(" }");
998 },
999 },
1000 .array => |info| {
1001 if (fmt.len == 0)
1002 @compileError("cannot format array without a specifier (i.e. {s} or {any})");
1003 if (max_depth == 0) {
1004 return bw.writeAll("{ ... }");
1005 }
1006 if (info.child == u8) {
1007 if (fmt[0] == 's') {
1008 return bw.alignBufferOptions(&value, options);
1009 } else if (fmt[0] == 'x') {
1010 return bw.printHex(&value, .lower);
1011 } else if (fmt[0] == 'X') {
1012 return bw.printHex(&value, .upper);
1013 }
1014 }
1015 try bw.writeAll("{ ");
1016 for (value, 0..) |elem, i| {
1017 try bw.printValue(fmt, options, elem, max_depth - 1);
1018 if (i < value.len - 1) {
1019 try bw.writeAll(", ");
1020 }
1021 }
1022 try bw.writeAll(" }");
1023 },
1024 .vector => |info| {
1025 if (max_depth == 0) {
1026 return bw.writeAll("{ ... }");
1027 }
1028 try bw.writeAll("{ ");
1029 var i: usize = 0;
1030 while (i < info.len) : (i += 1) {
1031 try bw.printValue(fmt, options, value[i], max_depth - 1);
1032 if (i < info.len - 1) {
1033 try bw.writeAll(", ");
1034 }
1035 }
1036 try bw.writeAll(" }");
1037 },
1038 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),
1039 .type => {
1040 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1041 return bw.alignBufferOptions(@typeName(value), options);
1042 },
1043 .enum_literal => {
1044 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1045 const buffer = [_]u8{'.'} ++ @tagName(value);
1046 return bw.alignBufferOptions(buffer, options);
1047 },
1048 .null => {
1049 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1050 return bw.alignBufferOptions("null", options);
1051 },
1052 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
1053 }
1054}
1055
1056fn printErrorSet(bw: *BufferedWriter, error_set: anyerror) Writer.Error!void {
1057 var vecs: [2][]const u8 = .{ "error.", @errorName(error_set) };
1058 try bw.writeVecAll(&vecs);
1059}
1060
1061pub fn printInt(
1062 bw: *BufferedWriter,
1063 comptime fmt: []const u8,
1064 options: std.fmt.Options,
1065 value: anytype,
1066) Writer.Error!void {
1067 const int_value = if (@TypeOf(value) == comptime_int) blk: {
1068 const Int = std.math.IntFittingRange(value, value);
1069 break :blk @as(Int, value);
1070 } else value;
1071
1072 switch (fmt.len) {
1073 0 => return bw.printIntOptions(int_value, 10, .lower, options),
1074 1 => switch (fmt[0]) {
1075 'd' => return bw.printIntOptions(int_value, 10, .lower, options),
1076 'c' => {
1077 if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) {
1078 return bw.printAsciiChar(@as(u8, int_value), options);
1079 } else {
1080 @compileError("cannot print integer that is larger than 8 bits as an ASCII character");
1081 }
1082 },
1083 'u' => {
1084 if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) {
1085 return bw.printUnicodeCodepoint(@as(u21, int_value), options);
1086 } else {
1087 @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");
1088 }
1089 },
1090 'b' => return bw.printIntOptions(int_value, 2, .lower, options),
1091 'x' => return bw.printIntOptions(int_value, 16, .lower, options),
1092 'X' => return bw.printIntOptions(int_value, 16, .upper, options),
1093 'o' => return bw.printIntOptions(int_value, 8, .lower, options),
1094 'B' => return bw.printByteSize(int_value, .decimal, options),
1095 'D' => return bw.printDuration(int_value, options),
1096 else => invalidFmtError(fmt, value),
1097 },
1098 2 => {
1099 if (fmt[0] == 'B' and fmt[1] == 'i') {
1100 return bw.printByteSize(int_value, .binary, options);
1101 } else {
1102 invalidFmtError(fmt, value);
1103 }
1104 },
1105 else => invalidFmtError(fmt, value),
1106 }
1107 comptime unreachable;
1108}
1109
1110pub fn printAsciiChar(bw: *BufferedWriter, c: u8, options: std.fmt.Options) Writer.Error!void {
1111 return bw.alignBufferOptions(@as(*const [1]u8, &c), options);
1112}
1113
1114pub fn printAscii(bw: *BufferedWriter, bytes: []const u8, options: std.fmt.Options) Writer.Error!void {
1115 return bw.alignBufferOptions(bytes, options);
1116}
1117
1118pub fn printUnicodeCodepoint(bw: *BufferedWriter, c: u21, options: std.fmt.Options) Writer.Error!void {
1119 var buf: [4]u8 = undefined;
1120 const len = try std.unicode.utf8Encode(c, &buf);
1121 return bw.alignBufferOptions(buf[0..len], options);
1122}
1123
1124pub fn printIntOptions(
1125 bw: *BufferedWriter,
1126 value: anytype,
1127 base: u8,
1128 case: std.fmt.Case,
1129 options: std.fmt.Options,
1130) Writer.Error!void {
1131 assert(base >= 2);
1132
1133 const int_value = if (@TypeOf(value) == comptime_int) blk: {
1134 const Int = std.math.IntFittingRange(value, value);
1135 break :blk @as(Int, value);
1136 } else value;
1137
1138 const value_info = @typeInfo(@TypeOf(int_value)).int;
1139
1140 // The type must have the same size as `base` or be wider in order for the
1141 // division to work
1142 const min_int_bits = comptime @max(value_info.bits, 8);
1143 const MinInt = std.meta.Int(.unsigned, min_int_bits);
1144
1145 const abs_value = @abs(int_value);
1146 // The worst case in terms of space needed is base 2, plus 1 for the sign
1147 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
1148
1149 var a: MinInt = abs_value;
1150 var index: usize = buf.len;
1151
1152 if (base == 10) {
1153 while (a >= 100) : (a = @divTrunc(a, 100)) {
1154 index -= 2;
1155 buf[index..][0..2].* = std.fmt.digits2(@intCast(a % 100));
1156 }
1157
1158 if (a < 10) {
1159 index -= 1;
1160 buf[index] = '0' + @as(u8, @intCast(a));
1161 } else {
1162 index -= 2;
1163 buf[index..][0..2].* = std.fmt.digits2(@intCast(a));
1164 }
1165 } else {
1166 while (true) {
1167 const digit = a % base;
1168 index -= 1;
1169 buf[index] = std.fmt.digitToChar(@intCast(digit), case);
1170 a /= base;
1171 if (a == 0) break;
1172 }
1173 }
1174
1175 if (value_info.signedness == .signed) {
1176 if (value < 0) {
1177 // Negative integer
1178 index -= 1;
1179 buf[index] = '-';
1180 } else if (options.width == null or options.width.? == 0) {
1181 // Positive integer, omit the plus sign
1182 } else {
1183 // Positive integer
1184 index -= 1;
1185 buf[index] = '+';
1186 }
1187 }
1188
1189 return bw.alignBufferOptions(buf[index..], options);
1190}
1191
1192pub fn printFloat(
1193 bw: *BufferedWriter,
1194 comptime fmt: []const u8,
1195 options: std.fmt.Options,
1196 value: anytype,
1197) Writer.Error!void {
1198 var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined;
1199
1200 if (fmt.len > 1) invalidFmtError(fmt, value);
1201 switch (if (fmt.len == 0) 'e' else fmt[0]) {
1202 'e' => {
1203 const s = std.fmt.float.render(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) {
1204 error.BufferTooSmall => "(float)",
1205 };
1206 return bw.alignBufferOptions(s, options);
1207 },
1208 'd' => {
1209 const s = std.fmt.float.render(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1210 error.BufferTooSmall => "(float)",
1211 };
1212 return bw.alignBufferOptions(s, options);
1213 },
1214 'x' => {
1215 var sub_bw: BufferedWriter = undefined;
1216 sub_bw.initFixed(&buf);
1217 sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable;
1218 return bw.alignBufferOptions(sub_bw.getWritten(), options);
1219 },
1220 else => invalidFmtError(fmt, value),
1221 }
1222}
1223
1224pub fn printFloatHexadecimal(bw: *BufferedWriter, value: anytype, opt_precision: ?usize) Writer.Error!void {
1225 if (std.math.signbit(value)) try bw.writeByte('-');
1226 if (std.math.isNan(value)) return bw.writeAll("nan");
1227 if (std.math.isInf(value)) return bw.writeAll("inf");
1228
1229 const T = @TypeOf(value);
1230 const TU = std.meta.Int(.unsigned, @bitSizeOf(T));
1231
1232 const mantissa_bits = std.math.floatMantissaBits(T);
1233 const fractional_bits = std.math.floatFractionalBits(T);
1234 const exponent_bits = std.math.floatExponentBits(T);
1235 const mantissa_mask = (1 << mantissa_bits) - 1;
1236 const exponent_mask = (1 << exponent_bits) - 1;
1237 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
1238
1239 const as_bits: TU = @bitCast(value);
1240 var mantissa = as_bits & mantissa_mask;
1241 var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask));
1242
1243 const is_denormal = exponent == 0 and mantissa != 0;
1244 const is_zero = exponent == 0 and mantissa == 0;
1245
1246 if (is_zero) {
1247 // Handle this case here to simplify the logic below.
1248 try bw.writeAll("0x0");
1249 if (opt_precision) |precision| {
1250 if (precision > 0) {
1251 try bw.writeAll(".");
1252 try bw.splatByteAll('0', precision);
1253 }
1254 } else {
1255 try bw.writeAll(".0");
1256 }
1257 try bw.writeAll("p0");
1258 return;
1259 }
1260
1261 if (is_denormal) {
1262 // Adjust the exponent for printing.
1263 exponent += 1;
1264 } else {
1265 if (fractional_bits == mantissa_bits)
1266 mantissa |= 1 << fractional_bits; // Add the implicit integer bit.
1267 }
1268
1269 const mantissa_digits = (fractional_bits + 3) / 4;
1270 // Fill in zeroes to round the fraction width to a multiple of 4.
1271 mantissa <<= mantissa_digits * 4 - fractional_bits;
1272
1273 if (opt_precision) |precision| {
1274 // Round if needed.
1275 if (precision < mantissa_digits) {
1276 // We always have at least 4 extra bits.
1277 var extra_bits = (mantissa_digits - precision) * 4;
1278 // The result LSB is the Guard bit, we need two more (Round and
1279 // Sticky) to round the value.
1280 while (extra_bits > 2) {
1281 mantissa = (mantissa >> 1) | (mantissa & 1);
1282 extra_bits -= 1;
1283 }
1284 // Round to nearest, tie to even.
1285 mantissa |= @intFromBool(mantissa & 0b100 != 0);
1286 mantissa += 1;
1287 // Drop the excess bits.
1288 mantissa >>= 2;
1289 // Restore the alignment.
1290 mantissa <<= @as(std.math.Log2Int(TU), @intCast((mantissa_digits - precision) * 4));
1291
1292 const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0;
1293 // Prefer a normalized result in case of overflow.
1294 if (overflow) {
1295 mantissa >>= 1;
1296 exponent += 1;
1297 }
1298 }
1299 }
1300
1301 // +1 for the decimal part.
1302 var buf: [1 + mantissa_digits]u8 = undefined;
1303 assert(std.fmt.printInt(&buf, mantissa, 16, .lower, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len);
1304
1305 try bw.writeAll("0x");
1306 try bw.writeByte(buf[0]);
1307 const trimmed = std.mem.trimRight(u8, buf[1..], "0");
1308 if (opt_precision) |precision| {
1309 if (precision > 0) try bw.writeAll(".");
1310 } else if (trimmed.len > 0) {
1311 try bw.writeAll(".");
1312 }
1313 try bw.writeAll(trimmed);
1314 // Add trailing zeros if explicitly requested.
1315 if (opt_precision) |precision| if (precision > 0) {
1316 if (precision > trimmed.len)
1317 try bw.splatByteAll('0', precision - trimmed.len);
1318 };
1319 try bw.writeAll("p");
1320 try bw.printIntOptions(exponent - exponent_bias, 10, .lower, .{});
1321}
1322
1323pub const ByteSizeUnits = enum {
1324 /// This formatter represents the number as multiple of 1000 and uses the SI
1325 /// measurement units (kB, MB, GB, ...).
1326 decimal,
1327 /// This formatter represents the number as multiple of 1024 and uses the IEC
1328 /// measurement units (KiB, MiB, GiB, ...).
1329 binary,
1330};
1331
1332/// Format option `precision` is ignored when `value` is less than 1kB
1333pub fn printByteSize(
1334 bw: *std.io.BufferedWriter,
1335 value: u64,
1336 comptime units: ByteSizeUnits,
1337 options: std.fmt.Options,
1338) Writer.Error!void {
1339 if (value == 0) return bw.alignBufferOptions("0B", options);
1340 // The worst case in terms of space needed is 32 bytes + 3 for the suffix.
1341 var buf: [std.fmt.float.min_buffer_size + 3]u8 = undefined;
1342
1343 const mags_si = " kMGTPEZY";
1344 const mags_iec = " KMGTPEZY";
1345
1346 const log2 = std.math.log2(value);
1347 const base = switch (units) {
1348 .decimal => 1000,
1349 .binary => 1024,
1350 };
1351 const magnitude = switch (units) {
1352 .decimal => @min(log2 / comptime std.math.log2(1000), mags_si.len - 1),
1353 .binary => @min(log2 / 10, mags_iec.len - 1),
1354 };
1355 const new_value = std.math.lossyCast(f64, value) / std.math.pow(f64, std.math.lossyCast(f64, base), std.math.lossyCast(f64, magnitude));
1356 const suffix = switch (units) {
1357 .decimal => mags_si[magnitude],
1358 .binary => mags_iec[magnitude],
1359 };
1360
1361 const s = switch (magnitude) {
1362 0 => buf[0..std.fmt.printInt(&buf, value, 10, .lower, .{})],
1363 else => std.fmt.float.render(&buf, new_value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1364 error.BufferTooSmall => unreachable,
1365 },
1366 };
1367
1368 var i: usize = s.len;
1369 if (suffix == ' ') {
1370 buf[i] = 'B';
1371 i += 1;
1372 } else switch (units) {
1373 .decimal => {
1374 buf[i..][0..2].* = [_]u8{ suffix, 'B' };
1375 i += 2;
1376 },
1377 .binary => {
1378 buf[i..][0..3].* = [_]u8{ suffix, 'i', 'B' };
1379 i += 3;
1380 },
1381 }
1382
1383 return bw.alignBufferOptions(buf[0..i], options);
1384}
1385
1386// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
1387const ANY = "any";
1388
1389fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 {
1390 return if (std.mem.eql(u8, fmt[1..], ANY))
1391 ANY
1392 else
1393 fmt[1..];
1394}
1395
1396pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) noreturn {
1397 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
1398}
1399
1400pub fn printDurationSigned(bw: *BufferedWriter, ns: i64) Writer.Error!void {
1401 if (ns < 0) try bw.writeByte('-');
1402 return bw.printDurationUnsigned(@abs(ns));
1403}
1404
1405pub fn printDurationUnsigned(bw: *BufferedWriter, ns: u64) Writer.Error!void {
1406 var ns_remaining = ns;
1407 inline for (.{
1408 .{ .ns = 365 * std.time.ns_per_day, .sep = 'y' },
1409 .{ .ns = std.time.ns_per_week, .sep = 'w' },
1410 .{ .ns = std.time.ns_per_day, .sep = 'd' },
1411 .{ .ns = std.time.ns_per_hour, .sep = 'h' },
1412 .{ .ns = std.time.ns_per_min, .sep = 'm' },
1413 }) |unit| {
1414 if (ns_remaining >= unit.ns) {
1415 const units = ns_remaining / unit.ns;
1416 try bw.printIntOptions(units, 10, .lower, .{});
1417 try bw.writeByte(unit.sep);
1418 ns_remaining -= units * unit.ns;
1419 if (ns_remaining == 0) return;
1420 }
1421 }
1422
1423 inline for (.{
1424 .{ .ns = std.time.ns_per_s, .sep = "s" },
1425 .{ .ns = std.time.ns_per_ms, .sep = "ms" },
1426 .{ .ns = std.time.ns_per_us, .sep = "us" },
1427 }) |unit| {
1428 const kunits = ns_remaining * 1000 / unit.ns;
1429 if (kunits >= 1000) {
1430 try bw.printIntOptions(kunits / 1000, 10, .lower, .{});
1431 const frac = kunits % 1000;
1432 if (frac > 0) {
1433 // Write up to 3 decimal places
1434 var decimal_buf = [_]u8{ '.', 0, 0, 0 };
1435 var inner: BufferedWriter = undefined;
1436 inner.initFixed(decimal_buf[1..]);
1437 inner.printIntOptions(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable;
1438 var end: usize = 4;
1439 while (end > 1) : (end -= 1) {
1440 if (decimal_buf[end - 1] != '0') break;
1441 }
1442 try bw.writeAll(decimal_buf[0..end]);
1443 }
1444 return bw.writeAll(unit.sep);
1445 }
1446 }
1447
1448 try bw.printIntOptions(ns_remaining, 10, .lower, .{});
1449 try bw.writeAll("ns");
1450}
1451
1452/// Writes number of nanoseconds according to its signed magnitude:
1453/// `[#y][#w][#d][#h][#m]#[.###][n|u|m]s`
1454/// `nanoseconds` must be an integer that coerces into `u64` or `i64`.
1455pub fn printDuration(bw: *BufferedWriter, nanoseconds: anytype, options: std.fmt.Options) Writer.Error!void {
1456 // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24
1457 var buf: [24]u8 = undefined;
1458 var sub_bw: BufferedWriter = undefined;
1459 sub_bw.initFixed(&buf);
1460 switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) {
1461 .signed => sub_bw.printDurationSigned(nanoseconds) catch unreachable,
1462 .unsigned => sub_bw.printDurationUnsigned(nanoseconds) catch unreachable,
1463 }
1464 return bw.alignBufferOptions(sub_bw.getWritten(), options);
1465}
1466
1467pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) Writer.Error!void {
1468 const charset = switch (case) {
1469 .upper => "0123456789ABCDEF",
1470 .lower => "0123456789abcdef",
1471 };
1472 for (bytes) |c| {
1473 try bw.writeByte(charset[c >> 4]);
1474 try bw.writeByte(charset[c & 15]);
1475 }
1476}
1477
1478pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) Writer.Error!void {
1479 var chunker = std.mem.window(u8, bytes, 3, 3);
1480 var temp: [5]u8 = undefined;
1481 while (chunker.next()) |chunk| {
1482 try bw.writeAll(std.base64.standard.Encoder.encode(&temp, chunk));
1483 }
1484}
1485
1486/// Write a single unsigned integer as LEB128 to the given writer.
1487pub fn writeUleb128(bw: *BufferedWriter, value: anytype) Writer.Error!void {
1488 try bw.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1489 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
1490 .int => |value_info| switch (value_info.signedness) {
1491 .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)),
1492 .unsigned => value,
1493 },
1494 else => comptime unreachable,
1495 });
1496}
1497
1498/// Write a single signed integer as LEB128 to the given writer.
1499pub fn writeSleb128(bw: *BufferedWriter, value: anytype) Writer.Error!void {
1500 try bw.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1501 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
1502 .int => |value_info| switch (value_info.signedness) {
1503 .signed => value,
1504 .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value),
1505 },
1506 else => comptime unreachable,
1507 });
1508}
1509
1510/// Write a single integer as LEB128 to the given writer.
1511pub fn writeLeb128(bw: *BufferedWriter, value: anytype) Writer.Error!void {
1512 const value_info = @typeInfo(@TypeOf(value)).int;
1513 try bw.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{
1514 .signedness = value_info.signedness,
1515 .bits = std.mem.alignForwardAnyAlign(u16, value_info.bits, 7),
1516 } }), value));
1517}
1518
1519fn writeMultipleOf7Leb128(bw: *BufferedWriter, value: anytype) Writer.Error!void {
1520 const value_info = @typeInfo(@TypeOf(value)).int;
1521 comptime assert(value_info.bits % 7 == 0);
1522 var remaining = value;
1523 while (true) {
1524 const buffer: []packed struct(u8) { bits: u7, more: bool } = @ptrCast(try bw.writableSliceGreedy(1));
1525 for (buffer, 1..) |*byte, len| {
1526 const more = switch (value_info.signedness) {
1527 .signed => remaining >> 6 != remaining >> (value_info.bits - 1),
1528 .unsigned => remaining > std.math.maxInt(u7),
1529 };
1530 byte.* = if (@inComptime()) @typeInfo(@TypeOf(buffer)).pointer.child{
1531 .bits = @bitCast(@as(@Type(.{ .int = .{
1532 .signedness = value_info.signedness,
1533 .bits = 7,
1534 } }), @truncate(remaining))),
1535 .more = more,
1536 } else .{
1537 .bits = @bitCast(@as(@Type(.{ .int = .{
1538 .signedness = value_info.signedness,
1539 .bits = 7,
1540 } }), @truncate(remaining))),
1541 .more = more,
1542 };
1543 if (value_info.bits > 7) remaining >>= 7;
1544 if (!more) return bw.advance(len);
1545 }
1546 bw.advance(buffer.len);
1547 }
1548}
1549
1550test "formatValue max_depth" {
1551 const Vec2 = struct {
1552 const SelfType = @This();
1553 x: f32,
1554 y: f32,
1555
1556 pub fn format(
1557 self: SelfType,
1558 comptime fmt: []const u8,
1559 options: std.fmt.Options,
1560 bw: *BufferedWriter,
1561 ) Writer.Error!void {
1562 _ = options;
1563 if (fmt.len == 0) {
1564 return bw.print("({d:.3},{d:.3})", .{ self.x, self.y });
1565 } else {
1566 @compileError("unknown format string: '" ++ fmt ++ "'");
1567 }
1568 }
1569 };
1570 const E = enum {
1571 One,
1572 Two,
1573 Three,
1574 };
1575 const TU = union(enum) {
1576 const SelfType = @This();
1577 float: f32,
1578 int: u32,
1579 ptr: ?*SelfType,
1580 };
1581 const S = struct {
1582 const SelfType = @This();
1583 a: ?*SelfType,
1584 tu: TU,
1585 e: E,
1586 vec: Vec2,
1587 };
1588
1589 var inst = S{
1590 .a = null,
1591 .tu = TU{ .ptr = null },
1592 .e = E.Two,
1593 .vec = Vec2{ .x = 10.2, .y = 2.22 },
1594 };
1595 inst.a = &inst;
1596 inst.tu.ptr = &inst.tu;
1597
1598 var buf: [1000]u8 = undefined;
1599 var bw: BufferedWriter = undefined;
1600 bw.initFixed(&buf);
1601 try bw.printValue("", .{}, inst, 0);
1602 try testing.expectEqualStrings("io.BufferedWriter.test.printValue max_depth.S{ ... }", bw.getWritten());
1603
1604 bw.reset();
1605 try bw.printValue("", .{}, inst, 1);
1606 try testing.expectEqualStrings("io.BufferedWriter.test.printValue max_depth.S{ .a = io.BufferedWriter.test.printValue max_depth.S{ ... }, .tu = io.BufferedWriter.test.printValue max_depth.TU{ ... }, .e = io.BufferedWriter.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", bw.getWritten());
1607
1608 bw.reset();
1609 try bw.printValue("", .{}, inst, 2);
1610 try testing.expectEqualStrings("io.BufferedWriter.test.printValue max_depth.S{ .a = io.BufferedWriter.test.printValue max_depth.S{ .a = io.BufferedWriter.test.printValue max_depth.S{ ... }, .tu = io.BufferedWriter.test.printValue max_depth.TU{ ... }, .e = io.BufferedWriter.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.BufferedWriter.test.printValue max_depth.TU{ .ptr = io.BufferedWriter.test.printValue max_depth.TU{ ... } }, .e = io.BufferedWriter.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", bw.getWritten());
1611
1612 bw.reset();
1613 try bw.printValue("", .{}, inst, 3);
1614 try testing.expectEqualStrings("io.BufferedWriter.test.printValue max_depth.S{ .a = io.BufferedWriter.test.printValue max_depth.S{ .a = io.BufferedWriter.test.printValue max_depth.S{ .a = io.BufferedWriter.test.printValue max_depth.S{ ... }, .tu = io.BufferedWriter.test.printValue max_depth.TU{ ... }, .e = io.BufferedWriter.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.BufferedWriter.test.printValue max_depth.TU{ .ptr = io.BufferedWriter.test.printValue max_depth.TU{ ... } }, .e = io.BufferedWriter.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.BufferedWriter.test.printValue max_depth.TU{ .ptr = io.BufferedWriter.test.printValue max_depth.TU{ .ptr = io.BufferedWriter.test.printValue max_depth.TU{ ... } } }, .e = io.BufferedWriter.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", bw.getWritten());
1615
1616 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
1617 bw.reset();
1618 try bw.printValue("", .{}, vec, 0);
1619 try testing.expectEqualStrings("{ ... }", bw.getWritten());
1620
1621 bw.reset();
1622 try bw.printValue("", .{}, vec, 1);
1623 try testing.expectEqualStrings("{ 1, 2, 3, 4 }", bw.getWritten());
1624}
1625
1626test printDuration {
1627 testDurationCase("0ns", 0);
1628 testDurationCase("1ns", 1);
1629 testDurationCase("999ns", std.time.ns_per_us - 1);
1630 testDurationCase("1us", std.time.ns_per_us);
1631 testDurationCase("1.45us", 1450);
1632 testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
1633 testDurationCase("14.5us", 14500);
1634 testDurationCase("145us", 145000);
1635 testDurationCase("999.999us", std.time.ns_per_ms - 1);
1636 testDurationCase("1ms", std.time.ns_per_ms + 1);
1637 testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
1638 testDurationCase("1.11ms", 1110000);
1639 testDurationCase("1.111ms", 1111000);
1640 testDurationCase("1.111ms", 1111100);
1641 testDurationCase("999.999ms", std.time.ns_per_s - 1);
1642 testDurationCase("1s", std.time.ns_per_s);
1643 testDurationCase("59.999s", std.time.ns_per_min - 1);
1644 testDurationCase("1m", std.time.ns_per_min);
1645 testDurationCase("1h", std.time.ns_per_hour);
1646 testDurationCase("1d", std.time.ns_per_day);
1647 testDurationCase("1w", std.time.ns_per_week);
1648 testDurationCase("1y", 365 * std.time.ns_per_day);
1649 testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
1650 testDurationCase("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1651 testDurationCase("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1652 testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1653 testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1654 testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1655 testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1656 testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
1657
1658 testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1659 testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1660 testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
1661}
1662
1663test printDurationSigned {
1664 testDurationCaseSigned("0ns", 0);
1665 testDurationCaseSigned("1ns", 1);
1666 testDurationCaseSigned("-1ns", -(1));
1667 testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
1668 testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
1669 testDurationCaseSigned("1us", std.time.ns_per_us);
1670 testDurationCaseSigned("-1us", -(std.time.ns_per_us));
1671 testDurationCaseSigned("1.45us", 1450);
1672 testDurationCaseSigned("-1.45us", -(1450));
1673 testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
1674 testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
1675 testDurationCaseSigned("14.5us", 14500);
1676 testDurationCaseSigned("-14.5us", -(14500));
1677 testDurationCaseSigned("145us", 145000);
1678 testDurationCaseSigned("-145us", -(145000));
1679 testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
1680 testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
1681 testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
1682 testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
1683 testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
1684 testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
1685 testDurationCaseSigned("1.11ms", 1110000);
1686 testDurationCaseSigned("-1.11ms", -(1110000));
1687 testDurationCaseSigned("1.111ms", 1111000);
1688 testDurationCaseSigned("-1.111ms", -(1111000));
1689 testDurationCaseSigned("1.111ms", 1111100);
1690 testDurationCaseSigned("-1.111ms", -(1111100));
1691 testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
1692 testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
1693 testDurationCaseSigned("1s", std.time.ns_per_s);
1694 testDurationCaseSigned("-1s", -(std.time.ns_per_s));
1695 testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
1696 testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
1697 testDurationCaseSigned("1m", std.time.ns_per_min);
1698 testDurationCaseSigned("-1m", -(std.time.ns_per_min));
1699 testDurationCaseSigned("1h", std.time.ns_per_hour);
1700 testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
1701 testDurationCaseSigned("1d", std.time.ns_per_day);
1702 testDurationCaseSigned("-1d", -(std.time.ns_per_day));
1703 testDurationCaseSigned("1w", std.time.ns_per_week);
1704 testDurationCaseSigned("-1w", -(std.time.ns_per_week));
1705 testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
1706 testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
1707 testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
1708 testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
1709 testDurationCaseSigned("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1710 testDurationCaseSigned("-1y1h1.001s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms));
1711 testDurationCaseSigned("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1712 testDurationCaseSigned("-1y1h1s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us));
1713 testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1714 testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
1715 testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1716 testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
1717 testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1718 testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
1719 testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1720 testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
1721 testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
1722 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
1723 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
1724
1725 testing.expectFmt("=======0ns", "{s:=>10}", .{0});
1726 testing.expectFmt("1ns=======", "{s:=<10}", .{1});
1727 testing.expectFmt("-1ns======", "{s:=<10}", .{-(1)});
1728 testing.expectFmt(" -999ns ", "{s:^10}", .{-(std.time.ns_per_us - 1)});
1729}
1730
1731fn testDurationCase(expected: []const u8, input: u64) !void {
1732 var buf: [24]u8 = undefined;
1733 var bw: BufferedWriter = undefined;
1734 bw.initFixed(&buf);
1735 try bw.printDurationUnsigned(input);
1736 try testing.expectEqualStrings(expected, bw.getWritten());
1737}
1738
1739fn testDurationCaseSigned(expected: []const u8, input: i64) !void {
1740 var buf: [24]u8 = undefined;
1741 var bw: BufferedWriter = undefined;
1742 bw.initFixed(&buf);
1743 try bw.printDurationSigned(input);
1744 try testing.expectEqualStrings(expected, bw.getWritten());
1745}
1746
1747test printIntOptions {
1748 try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{});
1749
1750 try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{});
1751 try testPrintIntCase("-12345678", @as(i32, -12345678), 10, .lower, .{});
1752 try testPrintIntCase("-bc614e", @as(i32, -12345678), 16, .lower, .{});
1753 try testPrintIntCase("-BC614E", @as(i32, -12345678), 16, .upper, .{});
1754
1755 try testPrintIntCase("12345678", @as(u32, 12345678), 10, .upper, .{});
1756
1757 try testPrintIntCase(" 666", @as(u32, 666), 10, .lower, .{ .width = 6 });
1758 try testPrintIntCase(" 1234", @as(u32, 0x1234), 16, .lower, .{ .width = 6 });
1759 try testPrintIntCase("1234", @as(u32, 0x1234), 16, .lower, .{ .width = 1 });
1760
1761 try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 });
1762 try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 });
1763}
1764
1765test "printInt with comptime_int" {
1766 var buf: [20]u8 = undefined;
1767 var bw: BufferedWriter = undefined;
1768 bw.initFixed(&buf);
1769 try bw.printInt(@as(comptime_int, 123456789123456789), "", .{});
1770 try std.testing.expectEqualStrings("123456789123456789", bw.getWritten());
1771}
1772
1773test "printFloat with comptime_float" {
1774 var buf: [20]u8 = undefined;
1775 var bw: BufferedWriter = undefined;
1776 bw.initFixed(&buf);
1777 try bw.printFloat("", .{}, @as(comptime_float, 1.0));
1778 try std.testing.expectEqualStrings(bw.getWritten(), "1e0");
1779 try std.testing.expectFmt("1e0", "{}", .{1.0});
1780}
1781
1782fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
1783 var buffer: [100]u8 = undefined;
1784 var bw: BufferedWriter = undefined;
1785 bw.initFixed(&buffer);
1786 bw.printIntOptions(value, base, case, options);
1787 try testing.expectEqualStrings(expected, bw.getWritten());
1788}
1789
1790test printByteSize {
1791 try testing.expectFmt("file size: 42B\n", "file size: {B}\n", .{42});
1792 try testing.expectFmt("file size: 42B\n", "file size: {Bi}\n", .{42});
1793 try testing.expectFmt("file size: 63MB\n", "file size: {B}\n", .{63 * 1000 * 1000});
1794 try testing.expectFmt("file size: 63MiB\n", "file size: {Bi}\n", .{63 * 1024 * 1024});
1795 try testing.expectFmt("file size: 42B\n", "file size: {B:.2}\n", .{42});
1796 try testing.expectFmt("file size: 42B\n", "file size: {B:>9.2}\n", .{42});
1797 try testing.expectFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{63 * 1024 * 1024});
1798 try testing.expectFmt("file size: 60.08MiB\n", "file size: {Bi:.2}\n", .{63 * 1000 * 1000});
1799 try testing.expectFmt("file size: =66.06MB=\n", "file size: {B:=^9.2}\n", .{63 * 1024 * 1024});
1800 try testing.expectFmt("file size: 66.06MB\n", "file size: {B: >9.2}\n", .{63 * 1024 * 1024});
1801 try testing.expectFmt("file size: 66.06MB \n", "file size: {B: <9.2}\n", .{63 * 1024 * 1024});
1802 try testing.expectFmt("file size: 0.01844674407370955ZB\n", "file size: {B}\n", .{std.math.maxInt(u64)});
1803}
1804
1805test "bytes.hex" {
1806 const some_bytes = "\xCA\xFE\xBA\xBE";
1807 try std.testing.expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
1808 try std.testing.expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
1809 try std.testing.expectFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
1810 try std.testing.expectFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
1811 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
1812 try std.testing.expectFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
1813}
1814
1815test initFixed {
1816 {
1817 var buf: [255]u8 = undefined;
1818 var bw: BufferedWriter = undefined;
1819 bw.initFixed(&buf);
1820 try bw.print("{s}{s}!", .{ "Hello", "World" });
1821 try testing.expectEqualStrings("HelloWorld!", bw.getWritten());
1822 }
1823
1824 comptime {
1825 var buf: [255]u8 = undefined;
1826 var bw: BufferedWriter = undefined;
1827 bw.initFixed(&buf);
1828 try bw.print("{s}{s}!", .{ "Hello", "World" });
1829 try testing.expectEqualStrings("HelloWorld!", bw.getWritten());
1830 }
1831}
1832
1833test "fixed output" {
1834 var buffer: [10]u8 = undefined;
1835 var bw: BufferedWriter = undefined;
1836 bw.initFixed(&buffer);
1837
1838 try bw.writeAll("Hello");
1839 try testing.expect(std.mem.eql(u8, bw.getWritten(), "Hello"));
1840
1841 try bw.writeAll("world");
1842 try testing.expect(std.mem.eql(u8, bw.getWritten(), "Helloworld"));
1843
1844 try testing.expectError(error.WriteStreamEnd, bw.writeAll("!"));
1845 try testing.expect(std.mem.eql(u8, bw.getWritten(), "Helloworld"));
1846
1847 bw.reset();
1848 try testing.expect(bw.getWritten().len == 0);
1849
1850 try testing.expectError(error.WriteStreamEnd, bw.writeAll("Hello world!"));
1851 try testing.expect(std.mem.eql(u8, bw.getWritten(), "Hello worl"));
1852
1853 try bw.seekTo((try bw.getEndPos()) + 1);
1854 try testing.expectError(error.WriteStreamEnd, bw.writeAll("H"));
1855}
1856
1857test flushLimit {
1858 return error.Unimplemented;
1859}
lib/std/io/Reader.zig+3-6
...@@ -1149,8 +1149,7 @@ pub fn restitute(r: *Reader, n: usize) void {...@@ -1149,8 +1149,7 @@ pub fn restitute(r: *Reader, n: usize) void {
1149}1149}
11501150
1151test fixed {1151test fixed {
1152 var r: Reader = undefined;1152 var r: Reader = .fixed("a\x02");
1153 r.initFixed("a\x02");
1154 try testing.expect((try r.takeByte()) == 'a');1153 try testing.expect((try r.takeByte()) == 'a');
1155 try testing.expect((try r.takeEnum(enum(u8) {1154 try testing.expect((try r.takeEnum(enum(u8) {
1156 a = 0,1155 a = 0,
...@@ -1186,8 +1185,7 @@ test peekArray {...@@ -1186,8 +1185,7 @@ test peekArray {
1186}1185}
11871186
1188test discardAll {1187test discardAll {
1189 var r: Reader = undefined;1188 var r: Reader = .fixed("foobar");
1190 r.initFixed("foobar");
1191 try r.discard(3);1189 try r.discard(3);
1192 try testing.expectEqualStrings("bar", try r.take(3));1190 try testing.expectEqualStrings("bar", try r.take(3));
1193 try r.discard(0);1191 try r.discard(0);
...@@ -1300,8 +1298,7 @@ test readVec {...@@ -1300,8 +1298,7 @@ test readVec {
13001298
1301test "expected error.EndOfStream" {1299test "expected error.EndOfStream" {
1302 // Unit test inspired by https://github.com/ziglang/zig/issues/177331300 // Unit test inspired by https://github.com/ziglang/zig/issues/17733
1303 var r: std.io.Reader = undefined;1301 var r: std.io.Reader = .fixed("");
1304 r.initFixed("");
1305 try std.testing.expectError(error.EndOfStream, r.readEnum(enum(u8) { a, b }, .little));1302 try std.testing.expectError(error.EndOfStream, r.readEnum(enum(u8) { a, b }, .little));
1306 try std.testing.expectError(error.EndOfStream, r.isBytes("foo"));1303 try std.testing.expectError(error.EndOfStream, r.isBytes("foo"));
1307}1304}
lib/std/io/Reader/Limited.zig+3-3
...@@ -2,7 +2,7 @@ const Limited = @This();...@@ -2,7 +2,7 @@ const Limited = @This();
22
3const std = @import("../../std.zig");3const std = @import("../../std.zig");
4const Reader = std.io.Reader;4const Reader = std.io.Reader;
5const BufferedWriter = std.io.BufferedWriter;5const Writer = std.io.Writer;
6const Limit = std.io.Limit;6const Limit = std.io.Limit;
77
8unlimited: *Reader,8unlimited: *Reader,
...@@ -25,10 +25,10 @@ pub fn init(reader: *Reader, limit: Limit, buffer: []u8) Limited {...@@ -25,10 +25,10 @@ pub fn init(reader: *Reader, limit: Limit, buffer: []u8) Limited {
25 };25 };
26}26}
2727
28fn stream(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.StreamError!usize {28fn stream(context: ?*anyopaque, w: *Writer, limit: Limit) Reader.StreamError!usize {
29 const l: *Limited = @alignCast(@ptrCast(context));29 const l: *Limited = @alignCast(@ptrCast(context));
30 const combined_limit = limit.min(l.remaining);30 const combined_limit = limit.min(l.remaining);
31 const n = try l.unlimited_reader.read(bw, combined_limit);31 const n = try l.unlimited_reader.read(w, combined_limit);
32 l.remaining = l.remaining.subtract(n).?;32 l.remaining = l.remaining.subtract(n).?;
33 return n;33 return n;
34}34}
lib/std/io/Writer.zig+1836-130
...@@ -1,51 +1,71 @@...@@ -1,51 +1,71 @@
1const builtin = @import("builtin");
2const native_endian = builtin.target.cpu.arch.endian();
3
4const Writer = @This();
1const std = @import("../std.zig");5const std = @import("../std.zig");
2const assert = std.debug.assert;6const assert = std.debug.assert;
3const Writer = @This();
4const Limit = std.io.Limit;7const Limit = std.io.Limit;
5const File = std.fs.File;8const File = std.fs.File;
9const testing = std.testing;
10const Allocator = std.mem.Allocator;
611
7context: ?*anyopaque,12context: ?*anyopaque,
8vtable: *const VTable,13vtable: *const VTable,
14/// If this has length zero, the writer is unbuffered, and `flush` is a no-op.
15buffer: []u8,
16/// In `buffer` before this are buffered bytes, after this is `undefined`.
17end: usize = 0,
18/// Tracks total number of bytes written to this `Writer`. This value
19/// only increases. In the case of fixed mode, this value always equals `end`.
20///
21/// This value is maintained by the interface; `VTable` function
22/// implementations need not modify it.
23count: usize = 0,
924
10pub const VTable = struct {25pub const VTable = struct {
11 /// Each slice in `data` is written in order.26 /// Sends bytes to the logical sink. A write will only be sent here if it
27 /// could not fit into `buffer`.
28 ///
29 /// `buffer[0..end]` is consumed first, followed by each slice of `data` in
30 /// order. Elements of `data` may alias each other but may not alias
31 /// `buffer`.
32 ///
33 /// This function modifies `Writer` state.
12 ///34 ///
13 /// `data.len` must be greater than zero, and the last element of `data` is35 /// `data.len` must be greater than zero, and the last element of `data` is
14 /// special. It is repeated as necessary so that it is written `splat`36 /// special. It is repeated as necessary so that it is written `splat`
15 /// number of times.37 /// number of times, which may be zero.
16 ///38 ///
17 /// Number of bytes actually written is returned.39 /// Number of bytes actually written is returned, excluding bytes from
40 /// `buffer`. Bytes from `buffer` are tracked by modifying `end`.
18 ///41 ///
19 /// Number of bytes returned may be zero, which does not mean42 /// Number of bytes returned may be zero, which does not mean
20 /// end-of-stream. A subsequent call may return nonzero, or may signal end43 /// end-of-stream. A subsequent call may return nonzero, or signal end of
21 /// of stream via `error.WriteFailed`.44 /// stream via `error.WriteFailed`.
22 writeSplat: *const fn (ctx: ?*anyopaque, data: []const []const u8, splat: usize) Error!usize,45 drain: *const fn (w: *Writer, data: []const []const u8, splat: usize) Error!usize,
2346
24 /// Writes contents from an open file. `headers` are written first, then47 /// Copies contents from an open file to the logical sink. `buffer[0..end]`
25 /// `limit` bytes of `file` starting from `offset`, then `trailers`.48 /// is consumed first, followed by `limit` bytes from `file_reader`.
26 ///49 ///
27 /// Number of bytes actually written is returned, which may lie within50 /// Number of bytes actually written is returned, excluding bytes from
28 /// headers, the file, trailers, or anywhere in between.51 /// `buffer`. Bytes from `buffer` are tracked by modifying `end`.
29 ///52 ///
30 /// Number of bytes returned may be zero, which does not mean53 /// Number of bytes returned may be zero, which does not necessarily mean
31 /// end-of-stream. A subsequent call may return nonzero, or may signal end54 /// end-of-stream. A subsequent call may return nonzero, or signal end of
32 /// of stream via `error.WriteFailed`.55 /// stream via `error.WriteFailed`. Caller must check `file_reader` state
56 /// (`File.Reader.atEnd`) to disambiguate between a zero-length read or
57 /// write, and whether the file reached the end.
33 ///58 ///
34 /// `error.Unimplemented` indicates the callee cannot offer a more59 /// `error.Unimplemented` indicates the callee cannot offer a more
35 /// efficient implementation than the caller performing its own reads.60 /// efficient implementation than the caller performing its own reads.
36 writeFile: *const fn (61 sendFile: *const fn (
37 ctx: ?*anyopaque,62 w: *Writer,
38 file_reader: *File.Reader,63 file_reader: *File.Reader,
39 /// Maximum amount of bytes to read from the file. Implementations may64 /// Maximum amount of bytes to read from the file. Implementations may
40 /// assume that the file size does not exceed this amount.65 /// assume that the file size does not exceed this amount. Data from
41 ///66 /// `buffer` does not count towards this limit.
42 /// `headers_and_trailers` do not count towards this limit.
43 limit: Limit,67 limit: Limit,
44 /// Headers and trailers must be passed together so that in case `len` is68 ) FileError!usize = unimplementedSendFile,
45 /// zero, they can be forwarded directly as one contiguous slice of memory.
46 headers_and_trailers: []const []const u8,
47 headers_len: usize,
48 ) FileError!usize,
49};69};
5070
51pub const Error = error{71pub const Error = error{
...@@ -70,97 +90,1602 @@ pub const FileError = error{...@@ -70,97 +90,1602 @@ pub const FileError = error{
70 Unimplemented,90 Unimplemented,
71};91};
7292
73pub fn writeVec(w: Writer, data: []const []const u8) Error!usize {93/// Writes to `buffer` and returns `error.WriteFailed` when it is full. Unless
94/// modified externally, `count` will always equal `end`.
95pub fn fixed(buffer: []u8) Writer {
96 return .{
97 .context = undefined,
98 .vtable = &.{ .drain = fixedDrain },
99 .buffer = buffer,
100 };
101}
102
103pub fn hashed(w: *Writer, hasher: anytype) Hashed(@TypeOf(hasher)) {
104 return .{ .out = w, .hasher = hasher };
105}
106
107pub const failing: Writer = .{
108 .context = undefined,
109 .vtable = &.{
110 .drain = failingDrain,
111 .sendFile = failingSendFile,
112 },
113};
114
115pub fn discarding(buffer: []u8) Writer {
116 return .{
117 .context = undefined,
118 .vtable = &.{
119 .drain = discardingDrain,
120 .sendFile = discardingSendFile,
121 },
122 .buffer = buffer,
123 };
124}
125
126/// Returns the contents not yet drained.
127pub fn buffered(w: *const Writer) []u8 {
128 return w.buffer[0..w.end];
129}
130
131pub fn countSplat(n: usize, data: []const []const u8, splat: usize) usize {
74 assert(data.len > 0);132 assert(data.len > 0);
75 return w.vtable.writeSplat(w.context, data, 1);133 var total: usize = n;
134 for (data[0 .. data.len - 1]) |buf| total += buf.len;
135 total += data[data.len - 1].len * splat;
136 return total;
76}137}
77138
78pub fn writeSplat(w: Writer, data: []const []const u8, splat: usize) Error!usize {139pub fn countSendFileUpperBound(n: usize, file_reader: *File.Reader, limit: Limit) ?usize {
140 const total: u64 = @min(@intFromEnum(limit), file_reader.getSize() orelse return null);
141 return std.math.lossyCast(usize, total + n);
142}
143
144/// If the total number of bytes of `data` fits inside `unusedCapacitySlice`,
145/// this function is guaranteed to not fail, not call into `VTable`, and return
146/// the total bytes inside `data`.
147pub fn writeVec(w: *Writer, data: []const []const u8) Error!usize {
148 return writeSplat(w, data, 1);
149}
150
151/// If the number of bytes to write based on `data` and `splat` fits inside
152/// `unusedCapacitySlice`, this function is guaranteed to not fail, not call
153/// into `VTable`, and return the full number of bytes.
154pub fn writeSplat(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
79 assert(data.len > 0);155 assert(data.len > 0);
80 return w.vtable.writeSplat(w.context, data, splat);156 const buffer = w.buffer;
157 const count = countSplat(0, data, splat);
158 if (w.end + count > buffer.len) {
159 const end = w.end;
160 const n = try w.vtable.drain(w, data, splat);
161 return n -| end;
162 }
163 w.count += count;
164 for (data) |bytes| {
165 @memcpy(buffer[w.end..][0..bytes.len], bytes);
166 w.end += bytes.len;
167 }
168 const pattern = data[data.len - 1];
169 if (splat == 0) {
170 @branchHint(.unlikely);
171 // It was added in the loop above; undo it here.
172 w.end -= pattern.len;
173 return count;
174 }
175 const remaining_splat = splat - 1;
176 switch (pattern.len) {
177 0 => {},
178 1 => {
179 @memset(buffer[w.end..][0..remaining_splat], pattern[0]);
180 w.end += remaining_splat;
181 },
182 else => {
183 const new_end = w.end + pattern.len * remaining_splat;
184 while (w.end < new_end) : (w.end += pattern.len) {
185 @memcpy(buffer[w.end..][0..pattern.len], pattern);
186 }
187 },
188 }
189 return count;
81}190}
82191
83pub fn writeFile(192/// Equivalent to `writeSplat` but writes at most `limit` bytes.
84 w: Writer,193pub fn writeSplatLimit(
85 file_reader: *File.Reader,194 w: *Writer,
195 data: []const []const u8,
196 splat: usize,
86 limit: Limit,197 limit: Limit,
87 headers_and_trailers: []const []const u8,198) Error!usize {
88 headers_len: usize,199 _ = w;
89) FileError!usize {200 _ = data;
90 return w.vtable.writeFile(w.context, file_reader, limit, headers_and_trailers, headers_len);201 _ = splat;
202 _ = limit;
203 @panic("TODO");
91}204}
92205
93pub fn buffered(w: Writer, buffer: []u8) std.io.BufferedWriter {206/// Drains all remaining buffered data.
94 return .{207pub fn flush(w: *Writer) Error!void {
95 .buffer = buffer,208 const drainFn = w.vtable.drain;
96 .unbuffered_writer = w,209 // This implementation allows for drain functions that do not modify `end`,
210 // such as `fixedDrain`.
211 var remaining = w.end;
212 while (remaining != 0) remaining -= try drainFn(w, &.{""}, 1);
213}
214
215pub fn unusedCapacitySlice(w: *const Writer) []u8 {
216 return w.buffer[w.end..];
217}
218
219pub fn unusedCapacityLen(w: *const Writer) usize {
220 return w.buffer.len - w.end;
221}
222
223/// Asserts the provided buffer has total capacity enough for `len`.
224///
225/// Advances the buffer end position by `len`.
226pub fn writableArray(w: *Writer, comptime len: usize) Error!*[len]u8 {
227 const big_slice = try w.writableSliceGreedy(len);
228 advance(w, len);
229 return big_slice[0..len];
230}
231
232/// Asserts the provided buffer has total capacity enough for `len`.
233///
234/// Advances the buffer end position by `len`.
235pub fn writableSlice(w: *Writer, len: usize) Error![]u8 {
236 const big_slice = try w.writableSliceGreedy(len);
237 advance(w, len);
238 return big_slice[0..len];
239}
240
241/// Asserts the provided buffer has total capacity enough for `minimum_length`.
242///
243/// Does not `advance` the buffer end position.
244///
245/// If `minimum_length` is zero, this is equivalent to `unusedCapacitySlice`.
246pub fn writableSliceGreedy(w: *Writer, minimum_length: usize) Error![]u8 {
247 assert(w.buffer.len >= minimum_length);
248 const cap_slice = w.buffer[w.end..];
249 if (cap_slice.len >= minimum_length) {
250 @branchHint(.likely);
251 return cap_slice;
252 }
253 const buffer = w.buffer[0..w.end];
254 const n = try w.unbuffered_writer.writeVec(&.{buffer});
255 if (n == buffer.len) {
256 @branchHint(.likely);
257 w.end = 0;
258 return w.buffer;
259 }
260 if (n > 0) {
261 const remainder = buffer[n..];
262 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
263 w.end = remainder.len;
264 }
265 return w.buffer[w.end..];
266}
267
268pub fn ensureUnusedCapacity(w: *Writer, n: usize) Error!void {
269 _ = try writableSliceGreedy(w, n);
270}
271
272pub fn undo(w: *Writer, n: usize) void {
273 w.end -= n;
274 w.count -= n;
275}
276
277/// After calling `writableSliceGreedy`, this function tracks how many bytes
278/// were written to it.
279///
280/// This is not needed when using `writableSlice` or `writableArray`.
281pub fn advance(w: *Writer, n: usize) void {
282 const new_end = w.end + n;
283 assert(new_end <= w.buffer.len);
284 w.end = new_end;
285 w.count += n;
286}
287
288/// The `data` parameter is mutable because this function needs to mutate the
289/// fields in order to handle partial writes from `VTable.writeSplat`.
290pub fn writeVecAll(w: *Writer, data: [][]const u8) Error!void {
291 var index: usize = 0;
292 var truncate: usize = 0;
293 while (index < data.len) {
294 {
295 const untruncated = data[index];
296 data[index] = untruncated[truncate..];
297 defer data[index] = untruncated;
298 truncate += try w.writeVec(data[index..]);
299 }
300 while (index < data.len and truncate >= data[index].len) {
301 truncate -= data[index].len;
302 index += 1;
303 }
304 }
305}
306
307/// The `data` parameter is mutable because this function needs to mutate the
308/// fields in order to handle partial writes from `VTable.writeSplat`.
309pub fn writeSplatAll(w: *Writer, data: [][]const u8, splat: usize) Error!void {
310 var index: usize = 0;
311 var truncate: usize = 0;
312 var remaining_splat = splat;
313 while (index + 1 < data.len) {
314 {
315 const untruncated = data[index];
316 data[index] = untruncated[truncate..];
317 defer data[index] = untruncated;
318 truncate += try w.writeSplat(data[index..], remaining_splat);
319 }
320 while (truncate >= data[index].len) {
321 if (index + 1 < data.len) {
322 truncate -= data[index].len;
323 index += 1;
324 } else {
325 const last = data[data.len - 1];
326 remaining_splat -= @divExact(truncate, last.len);
327 while (remaining_splat > 0) {
328 const n = try w.writeSplat(data[data.len - 1 ..][0..1], remaining_splat);
329 remaining_splat -= @divExact(n, last.len);
330 }
331 return;
332 }
333 }
334 }
335}
336
337pub fn write(w: *Writer, bytes: []const u8) Error!usize {
338 if (w.end + bytes.len <= w.buffer.len) {
339 @memcpy(w.buffer[w.end..][0..bytes.len], bytes);
340 w.end += bytes.len;
341 w.count += bytes.len;
342 return bytes.len;
343 }
344 const end = w.end;
345 const n = try w.vtable.drain(w, &.{bytes}, 1);
346 return n -| end;
347}
348
349/// Calls `write` as many times as necessary such that all of `bytes` are
350/// transferred.
351pub fn writeAll(w: *Writer, bytes: []const u8) Error!void {
352 var index: usize = 0;
353 while (index < bytes.len) index += try w.write(bytes[index..]);
354}
355
356pub fn print(w: *Writer, comptime format: []const u8, args: anytype) Error!void {
357 try std.fmt.format(w, format, args);
358}
359
360pub fn writeByte(w: *Writer, byte: u8) Error!void {
361 const buffer = w.buffer[0..w.end];
362 if (buffer.len < w.buffer.len) {
363 @branchHint(.likely);
364 buffer.ptr[buffer.len] = byte;
365 w.end = buffer.len + 1;
366 w.count += 1;
367 return;
368 }
369 var buffers: [2][]const u8 = .{ buffer, &.{byte} };
370 while (true) {
371 const n = try w.unbuffered_writer.writeVec(&buffers);
372 if (n == 0) {
373 @branchHint(.unlikely);
374 continue;
375 }
376 w.count += 1;
377 if (n >= buffer.len) {
378 @branchHint(.likely);
379 if (n > buffer.len) {
380 @branchHint(.likely);
381 w.end = 0;
382 return;
383 } else {
384 buffer[0] = byte;
385 w.end = 1;
386 return;
387 }
388 }
389 const remainder = buffer[n..];
390 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
391 buffer[remainder.len] = byte;
392 w.end = remainder.len + 1;
393 return;
394 }
395}
396
397/// Writes the same byte many times, performing the underlying write call as
398/// many times as necessary.
399pub fn splatByteAll(w: *Writer, byte: u8, n: usize) Error!void {
400 var remaining: usize = n;
401 while (remaining > 0) remaining -= try w.splatByte(byte, remaining);
402}
403
404/// Writes the same byte many times, allowing short writes.
405///
406/// Does maximum of one underlying `VTable.drain`.
407pub fn splatByte(w: *Writer, byte: u8, n: usize) Error!usize {
408 return writeSplat(w, &.{&.{byte}}, n);
409}
410
411/// Writes the same slice many times, performing the underlying write call as
412/// many times as necessary.
413pub fn splatBytesAll(w: *Writer, bytes: []const u8, splat: usize) Error!void {
414 var remaining_bytes: usize = bytes.len * splat;
415 remaining_bytes -= try w.splatBytes(bytes, splat);
416 while (remaining_bytes > 0) {
417 const leftover = remaining_bytes % bytes.len;
418 const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover ..], bytes };
419 remaining_bytes -= try w.splatBytes(&buffers, splat);
420 }
421}
422
423/// Writes the same slice many times, allowing short writes.
424///
425/// Does maximum of one underlying `VTable.writeSplat`.
426pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize {
427 return writeSplat(w, &.{bytes}, n);
428}
429
430/// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes.
431pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void {
432 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
433 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
434 return w.writeAll(&bytes);
435}
436
437pub fn writeStruct(w: *Writer, value: anytype) Error!void {
438 // Only extern and packed structs have defined in-memory layout.
439 comptime assert(@typeInfo(@TypeOf(value)).@"struct".layout != .auto);
440 return w.writeAll(std.mem.asBytes(&value));
441}
442
443/// The function is inline to avoid the dead code in case `endian` is
444/// comptime-known and matches host endianness.
445/// TODO: make sure this value is not a reference type
446pub inline fn writeStructEndian(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void {
447 if (native_endian == endian) {
448 return w.writeStruct(value);
449 } else {
450 var copy = value;
451 std.mem.byteSwapAllFields(@TypeOf(value), &copy);
452 return w.writeStruct(copy);
453 }
454}
455
456pub inline fn writeSliceEndian(
457 w: *Writer,
458 Elem: type,
459 slice: []const Elem,
460 endian: std.builtin.Endian,
461) Error!void {
462 if (native_endian == endian) {
463 return writeAll(w, @ptrCast(slice));
464 } else {
465 return w.writeArraySwap(w, Elem, slice);
466 }
467}
468
469/// Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
470pub fn writeSliceSwap(w: *Writer, Elem: type, slice: []const Elem) Error!void {
471 // copy to storage first, then swap in place
472 _ = w;
473 _ = slice;
474 @panic("TODO");
475}
476
477/// Unlike `writeSplat` and `writeVec`, this function will call into `VTable`
478/// even if there is enough buffer capacity for the file contents.
479///
480/// Although it would be possible to eliminate `error.Unimplemented` from the
481/// error set by reading directly into the buffer in such case, this is not
482/// done because it is more efficient to do it higher up the call stack so that
483/// the error does not occur with each write.
484///
485/// See `sendFileReading` for an alternative that does not have
486/// `error.Unimplemented` in the error set.
487pub fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
488 const end = w.end;
489 const n = try w.vtable.sendFile(w, file_reader, limit);
490 return n -| end;
491}
492
493/// Asserts nonzero buffer capacity.
494pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingFileError!usize {
495 const dest = limit.slice(try w.writableSliceGreedy(1));
496 const n = file_reader.read(dest) catch |err| switch (err) {
497 error.EndOfStream => 0,
498 error.ReadFailed => return error.ReadFailed,
97 };499 };
500 w.advance(n);
501 return n;
502}
503
504pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingFileError!usize {
505 var remaining = @intFromEnum(limit);
506 while (remaining > 0) {
507 const n = sendFile(w, file_reader, .limited(remaining)) catch |err| switch (err) {
508 error.EndOfStream => return 0,
509 error.ReadFailed => return error.ReadFailed,
510 error.WriteFailed => return error.WriteFailed,
511 error.Unimplemented => {
512 file_reader.mode = file_reader.mode.toReading();
513 try w.sendFileReadingAll(file_reader, remaining);
514 return;
515 },
516 };
517 remaining -= n;
518 }
519 return @intFromEnum(limit) - remaining;
520}
521
522/// Equivalent to `sendFileAll` but uses direct `pread` and `read` calls on
523/// `file` rather than `sendFile`. This is generally used as a fallback when
524/// the underlying implementation returns `error.Unimplemented`, which is why
525/// that error code does not appear in this function's error set.
526///
527/// Asserts nonzero buffer capacity.
528pub fn sendFileReadingAll(w: *Writer, file_reader: *File.Reader, limit: Limit) ReadingFileError!void {
529 var remaining = limit;
530 while (remaining.nonzero()) {
531 const n = try sendFileReading(w, file_reader, remaining);
532 if (n == 0) return;
533 remaining = remaining.subtract(n).?;
534 }
535}
536
537pub fn alignBuffer(
538 w: *Writer,
539 buffer: []const u8,
540 width: usize,
541 alignment: std.fmt.Alignment,
542 fill: u8,
543) Error!void {
544 const padding = if (buffer.len < width) width - buffer.len else 0;
545 if (padding == 0) {
546 @branchHint(.likely);
547 return w.writeAll(buffer);
548 }
549 switch (alignment) {
550 .left => {
551 try w.writeAll(buffer);
552 try w.splatByteAll(fill, padding);
553 },
554 .center => {
555 const left_padding = padding / 2;
556 const right_padding = (padding + 1) / 2;
557 try w.splatByteAll(fill, left_padding);
558 try w.writeAll(buffer);
559 try w.splatByteAll(fill, right_padding);
560 },
561 .right => {
562 try w.splatByteAll(fill, padding);
563 try w.writeAll(buffer);
564 },
565 }
566}
567
568pub fn alignBufferOptions(w: *Writer, buffer: []const u8, options: std.fmt.Options) Error!void {
569 return w.alignBuffer(buffer, options.width orelse buffer.len, options.alignment, options.fill);
570}
571
572pub fn printAddress(w: *Writer, value: anytype) Error!void {
573 const T = @TypeOf(value);
574 switch (@typeInfo(T)) {
575 .pointer => |info| {
576 try w.writeAll(@typeName(info.child) ++ "@");
577 if (info.size == .slice)
578 try w.printIntOptions(@intFromPtr(value.ptr), 16, .lower, .{})
579 else
580 try w.printIntOptions(@intFromPtr(value), 16, .lower, .{});
581 return;
582 },
583 .optional => |info| {
584 if (@typeInfo(info.child) == .pointer) {
585 try w.writeAll(@typeName(info.child) ++ "@");
586 try w.printIntOptions(@intFromPtr(value), 16, .lower, .{});
587 return;
588 }
589 },
590 else => {},
591 }
592
593 @compileError("cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
594}
595
596pub fn printValue(
597 w: *Writer,
598 comptime fmt: []const u8,
599 options: std.fmt.Options,
600 value: anytype,
601 max_depth: usize,
602) Error!void {
603 const T = @TypeOf(value);
604
605 if (comptime std.mem.eql(u8, fmt, "*")) {
606 return w.printAddress(value);
607 }
608
609 const is_any = comptime std.mem.eql(u8, fmt, ANY);
610 if (!is_any and std.meta.hasMethod(T, "format")) {
611 if (fmt.len > 0 and fmt[0] == 'f') {
612 return value.format(w, fmt[1..]);
613 } else if (fmt.len == 0) {
614 // after 0.15.0 is tagged, delete the hasMethod condition and this compile error
615 @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
616 }
617 }
618
619 switch (@typeInfo(T)) {
620 .float, .comptime_float => return w.printFloat(if (is_any) "d" else fmt, options, value),
621 .int, .comptime_int => return w.printInt(if (is_any) "d" else fmt, options, value),
622 .bool => {
623 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
624 return w.alignBufferOptions(if (value) "true" else "false", options);
625 },
626 .void => {
627 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
628 return w.alignBufferOptions("void", options);
629 },
630 .optional => {
631 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?')
632 stripOptionalOrErrorUnionSpec(fmt)
633 else if (is_any)
634 ANY
635 else
636 @compileError("cannot print optional without a specifier (i.e. {?} or {any})");
637 if (value) |payload| {
638 return w.printValue(remaining_fmt, options, payload, max_depth);
639 } else {
640 return w.alignBufferOptions("null", options);
641 }
642 },
643 .error_union => {
644 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '!')
645 stripOptionalOrErrorUnionSpec(fmt)
646 else if (is_any)
647 ANY
648 else
649 @compileError("cannot print error union without a specifier (i.e. {!} or {any})");
650 if (value) |payload| {
651 return w.printValue(remaining_fmt, options, payload, max_depth);
652 } else |err| {
653 return w.printValue("", options, err, max_depth);
654 }
655 },
656 .error_set => {
657 if (fmt.len == 1 and fmt[0] == 's') return w.writeAll(@errorName(value));
658 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
659 try printErrorSet(w, value);
660 },
661 .@"enum" => {
662 if (fmt.len == 1 and fmt[0] == 's') {
663 try w.writeAll(@tagName(value));
664 return;
665 }
666 if (!is_any) {
667 if (fmt.len != 0) return printValue(w, fmt, options, @intFromEnum(value), max_depth);
668 return printValue(w, ANY, options, value, max_depth);
669 }
670 const enum_info = @typeInfo(T).@"enum";
671 if (enum_info.is_exhaustive) {
672 var vecs: [3][]const u8 = .{ @typeName(T), ".", @tagName(value) };
673 try w.writeVecAll(&vecs);
674 return;
675 }
676 try w.writeAll(@typeName(T));
677 @setEvalBranchQuota(3 * enum_info.fields.len);
678 inline for (enum_info.fields) |field| {
679 if (@intFromEnum(value) == field.value) {
680 try w.writeAll(".");
681 try w.writeAll(@tagName(value));
682 return;
683 }
684 }
685 try w.writeByte('(');
686 try w.printValue(ANY, options, @intFromEnum(value), max_depth);
687 try w.writeByte(')');
688 },
689 .@"union" => |info| {
690 if (!is_any) {
691 if (fmt.len != 0) invalidFmtError(fmt, value);
692 return printValue(w, ANY, options, value, max_depth);
693 }
694 try w.writeAll(@typeName(T));
695 if (max_depth == 0) {
696 try w.writeAll("{ ... }");
697 return;
698 }
699 if (info.tag_type) |UnionTagType| {
700 try w.writeAll("{ .");
701 try w.writeAll(@tagName(@as(UnionTagType, value)));
702 try w.writeAll(" = ");
703 inline for (info.fields) |u_field| {
704 if (value == @field(UnionTagType, u_field.name)) {
705 try w.printValue(ANY, options, @field(value, u_field.name), max_depth - 1);
706 }
707 }
708 try w.writeAll(" }");
709 } else {
710 try w.writeByte('@');
711 try w.printIntOptions(@intFromPtr(&value), 16, .lower, options);
712 }
713 },
714 .@"struct" => |info| {
715 if (!is_any) {
716 if (fmt.len != 0) invalidFmtError(fmt, value);
717 return printValue(w, ANY, options, value, max_depth);
718 }
719 if (info.is_tuple) {
720 // Skip the type and field names when formatting tuples.
721 if (max_depth == 0) {
722 try w.writeAll("{ ... }");
723 return;
724 }
725 try w.writeAll("{");
726 inline for (info.fields, 0..) |f, i| {
727 if (i == 0) {
728 try w.writeAll(" ");
729 } else {
730 try w.writeAll(", ");
731 }
732 try w.printValue(ANY, options, @field(value, f.name), max_depth - 1);
733 }
734 try w.writeAll(" }");
735 return;
736 }
737 try w.writeAll(@typeName(T));
738 if (max_depth == 0) {
739 try w.writeAll("{ ... }");
740 return;
741 }
742 try w.writeAll("{");
743 inline for (info.fields, 0..) |f, i| {
744 if (i == 0) {
745 try w.writeAll(" .");
746 } else {
747 try w.writeAll(", .");
748 }
749 try w.writeAll(f.name);
750 try w.writeAll(" = ");
751 try w.printValue(ANY, options, @field(value, f.name), max_depth - 1);
752 }
753 try w.writeAll(" }");
754 },
755 .pointer => |ptr_info| switch (ptr_info.size) {
756 .one => switch (@typeInfo(ptr_info.child)) {
757 .array, .@"enum", .@"union", .@"struct" => {
758 return w.printValue(fmt, options, value.*, max_depth);
759 },
760 else => {
761 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
762 try w.writeVecAll(&buffers);
763 try w.printIntOptions(@intFromPtr(value), 16, .lower, options);
764 return;
765 },
766 },
767 .many, .c => {
768 if (ptr_info.sentinel() != null)
769 return w.printValue(fmt, options, std.mem.span(value), max_depth);
770 if (fmt.len == 1 and fmt[0] == 's' and ptr_info.child == u8)
771 return w.alignBufferOptions(std.mem.span(value), options);
772 if (!is_any and fmt.len == 0)
773 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
774 if (!is_any and fmt.len != 0)
775 invalidFmtError(fmt, value);
776 try w.printAddress(value);
777 },
778 .slice => {
779 if (!is_any and fmt.len == 0)
780 @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})");
781 if (max_depth == 0)
782 return w.writeAll("{ ... }");
783 if (ptr_info.child == u8) switch (fmt.len) {
784 1 => switch (fmt[0]) {
785 's' => return w.alignBufferOptions(value, options),
786 'x' => return w.printHex(value, .lower),
787 'X' => return w.printHex(value, .upper),
788 else => {},
789 },
790 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') {
791 return w.printBase64(value);
792 },
793 else => {},
794 };
795 try w.writeAll("{ ");
796 for (value, 0..) |elem, i| {
797 try w.printValue(fmt, options, elem, max_depth - 1);
798 if (i != value.len - 1) {
799 try w.writeAll(", ");
800 }
801 }
802 try w.writeAll(" }");
803 },
804 },
805 .array => |info| {
806 if (fmt.len == 0)
807 @compileError("cannot format array without a specifier (i.e. {s} or {any})");
808 if (max_depth == 0) {
809 return w.writeAll("{ ... }");
810 }
811 if (info.child == u8) {
812 if (fmt[0] == 's') {
813 return w.alignBufferOptions(&value, options);
814 } else if (fmt[0] == 'x') {
815 return w.printHex(&value, .lower);
816 } else if (fmt[0] == 'X') {
817 return w.printHex(&value, .upper);
818 }
819 }
820 try w.writeAll("{ ");
821 for (value, 0..) |elem, i| {
822 try w.printValue(fmt, options, elem, max_depth - 1);
823 if (i < value.len - 1) {
824 try w.writeAll(", ");
825 }
826 }
827 try w.writeAll(" }");
828 },
829 .vector => |info| {
830 if (max_depth == 0) {
831 return w.writeAll("{ ... }");
832 }
833 try w.writeAll("{ ");
834 var i: usize = 0;
835 while (i < info.len) : (i += 1) {
836 try w.printValue(fmt, options, value[i], max_depth - 1);
837 if (i < info.len - 1) {
838 try w.writeAll(", ");
839 }
840 }
841 try w.writeAll(" }");
842 },
843 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),
844 .type => {
845 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
846 return w.alignBufferOptions(@typeName(value), options);
847 },
848 .enum_literal => {
849 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
850 const buffer = [_]u8{'.'} ++ @tagName(value);
851 return w.alignBufferOptions(buffer, options);
852 },
853 .null => {
854 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
855 return w.alignBufferOptions("null", options);
856 },
857 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
858 }
98}859}
99860
100pub fn unbuffered(w: Writer) std.io.BufferedWriter {861fn printErrorSet(w: *Writer, error_set: anyerror) Error!void {
101 return w.buffered(&.{});862 var vecs: [2][]const u8 = .{ "error.", @errorName(error_set) };
863 try w.writeVecAll(&vecs);
102}864}
103865
104pub fn failingWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Error!usize {866pub fn printInt(
105 _ = context;867 w: *Writer,
868 comptime fmt: []const u8,
869 options: std.fmt.Options,
870 value: anytype,
871) Error!void {
872 const int_value = if (@TypeOf(value) == comptime_int) blk: {
873 const Int = std.math.IntFittingRange(value, value);
874 break :blk @as(Int, value);
875 } else value;
876
877 switch (fmt.len) {
878 0 => return w.printIntOptions(int_value, 10, .lower, options),
879 1 => switch (fmt[0]) {
880 'd' => return w.printIntOptions(int_value, 10, .lower, options),
881 'c' => {
882 if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) {
883 return w.printAsciiChar(@as(u8, int_value), options);
884 } else {
885 @compileError("cannot print integer that is larger than 8 bits as an ASCII character");
886 }
887 },
888 'u' => {
889 if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) {
890 return w.printUnicodeCodepoint(@as(u21, int_value), options);
891 } else {
892 @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");
893 }
894 },
895 'b' => return w.printIntOptions(int_value, 2, .lower, options),
896 'x' => return w.printIntOptions(int_value, 16, .lower, options),
897 'X' => return w.printIntOptions(int_value, 16, .upper, options),
898 'o' => return w.printIntOptions(int_value, 8, .lower, options),
899 'B' => return w.printByteSize(int_value, .decimal, options),
900 'D' => return w.printDuration(int_value, options),
901 else => invalidFmtError(fmt, value),
902 },
903 2 => {
904 if (fmt[0] == 'B' and fmt[1] == 'i') {
905 return w.printByteSize(int_value, .binary, options);
906 } else {
907 invalidFmtError(fmt, value);
908 }
909 },
910 else => invalidFmtError(fmt, value),
911 }
912 comptime unreachable;
913}
914
915pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void {
916 return w.alignBufferOptions(@as(*const [1]u8, &c), options);
917}
918
919pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void {
920 return w.alignBufferOptions(bytes, options);
921}
922
923pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {
924 var buf: [4]u8 = undefined;
925 const len = try std.unicode.utf8Encode(c, &buf);
926 return w.alignBufferOptions(buf[0..len], options);
927}
928
929pub fn printIntOptions(
930 w: *Writer,
931 value: anytype,
932 base: u8,
933 case: std.fmt.Case,
934 options: std.fmt.Options,
935) Error!void {
936 assert(base >= 2);
937
938 const int_value = if (@TypeOf(value) == comptime_int) blk: {
939 const Int = std.math.IntFittingRange(value, value);
940 break :blk @as(Int, value);
941 } else value;
942
943 const value_info = @typeInfo(@TypeOf(int_value)).int;
944
945 // The type must have the same size as `base` or be wider in order for the
946 // division to work
947 const min_int_bits = comptime @max(value_info.bits, 8);
948 const MinInt = std.meta.Int(.unsigned, min_int_bits);
949
950 const abs_value = @abs(int_value);
951 // The worst case in terms of space needed is base 2, plus 1 for the sign
952 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
953
954 var a: MinInt = abs_value;
955 var index: usize = buf.len;
956
957 if (base == 10) {
958 while (a >= 100) : (a = @divTrunc(a, 100)) {
959 index -= 2;
960 buf[index..][0..2].* = std.fmt.digits2(@intCast(a % 100));
961 }
962
963 if (a < 10) {
964 index -= 1;
965 buf[index] = '0' + @as(u8, @intCast(a));
966 } else {
967 index -= 2;
968 buf[index..][0..2].* = std.fmt.digits2(@intCast(a));
969 }
970 } else {
971 while (true) {
972 const digit = a % base;
973 index -= 1;
974 buf[index] = std.fmt.digitToChar(@intCast(digit), case);
975 a /= base;
976 if (a == 0) break;
977 }
978 }
979
980 if (value_info.signedness == .signed) {
981 if (value < 0) {
982 // Negative integer
983 index -= 1;
984 buf[index] = '-';
985 } else if (options.width == null or options.width.? == 0) {
986 // Positive integer, omit the plus sign
987 } else {
988 // Positive integer
989 index -= 1;
990 buf[index] = '+';
991 }
992 }
993
994 return w.alignBufferOptions(buf[index..], options);
995}
996
997pub fn printFloat(
998 w: *Writer,
999 comptime fmt: []const u8,
1000 options: std.fmt.Options,
1001 value: anytype,
1002) Error!void {
1003 var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined;
1004
1005 if (fmt.len > 1) invalidFmtError(fmt, value);
1006 switch (if (fmt.len == 0) 'e' else fmt[0]) {
1007 'e' => {
1008 const s = std.fmt.float.render(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) {
1009 error.BufferTooSmall => "(float)",
1010 };
1011 return w.alignBufferOptions(s, options);
1012 },
1013 'd' => {
1014 const s = std.fmt.float.render(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1015 error.BufferTooSmall => "(float)",
1016 };
1017 return w.alignBufferOptions(s, options);
1018 },
1019 'x' => {
1020 var sub_bw: Writer = .fixed(&buf);
1021 sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable;
1022 return w.alignBufferOptions(sub_bw.buffered(), options);
1023 },
1024 else => invalidFmtError(fmt, value),
1025 }
1026}
1027
1028pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) Error!void {
1029 if (std.math.signbit(value)) try w.writeByte('-');
1030 if (std.math.isNan(value)) return w.writeAll("nan");
1031 if (std.math.isInf(value)) return w.writeAll("inf");
1032
1033 const T = @TypeOf(value);
1034 const TU = std.meta.Int(.unsigned, @bitSizeOf(T));
1035
1036 const mantissa_bits = std.math.floatMantissaBits(T);
1037 const fractional_bits = std.math.floatFractionalBits(T);
1038 const exponent_bits = std.math.floatExponentBits(T);
1039 const mantissa_mask = (1 << mantissa_bits) - 1;
1040 const exponent_mask = (1 << exponent_bits) - 1;
1041 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
1042
1043 const as_bits: TU = @bitCast(value);
1044 var mantissa = as_bits & mantissa_mask;
1045 var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask));
1046
1047 const is_denormal = exponent == 0 and mantissa != 0;
1048 const is_zero = exponent == 0 and mantissa == 0;
1049
1050 if (is_zero) {
1051 // Handle this case here to simplify the logic below.
1052 try w.writeAll("0x0");
1053 if (opt_precision) |precision| {
1054 if (precision > 0) {
1055 try w.writeAll(".");
1056 try w.splatByteAll('0', precision);
1057 }
1058 } else {
1059 try w.writeAll(".0");
1060 }
1061 try w.writeAll("p0");
1062 return;
1063 }
1064
1065 if (is_denormal) {
1066 // Adjust the exponent for printing.
1067 exponent += 1;
1068 } else {
1069 if (fractional_bits == mantissa_bits)
1070 mantissa |= 1 << fractional_bits; // Add the implicit integer bit.
1071 }
1072
1073 const mantissa_digits = (fractional_bits + 3) / 4;
1074 // Fill in zeroes to round the fraction width to a multiple of 4.
1075 mantissa <<= mantissa_digits * 4 - fractional_bits;
1076
1077 if (opt_precision) |precision| {
1078 // Round if needed.
1079 if (precision < mantissa_digits) {
1080 // We always have at least 4 extra bits.
1081 var extra_bits = (mantissa_digits - precision) * 4;
1082 // The result LSB is the Guard bit, we need two more (Round and
1083 // Sticky) to round the value.
1084 while (extra_bits > 2) {
1085 mantissa = (mantissa >> 1) | (mantissa & 1);
1086 extra_bits -= 1;
1087 }
1088 // Round to nearest, tie to even.
1089 mantissa |= @intFromBool(mantissa & 0b100 != 0);
1090 mantissa += 1;
1091 // Drop the excess bits.
1092 mantissa >>= 2;
1093 // Restore the alignment.
1094 mantissa <<= @as(std.math.Log2Int(TU), @intCast((mantissa_digits - precision) * 4));
1095
1096 const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0;
1097 // Prefer a normalized result in case of overflow.
1098 if (overflow) {
1099 mantissa >>= 1;
1100 exponent += 1;
1101 }
1102 }
1103 }
1104
1105 // +1 for the decimal part.
1106 var buf: [1 + mantissa_digits]u8 = undefined;
1107 assert(std.fmt.printInt(&buf, mantissa, 16, .lower, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len);
1108
1109 try w.writeAll("0x");
1110 try w.writeByte(buf[0]);
1111 const trimmed = std.mem.trimRight(u8, buf[1..], "0");
1112 if (opt_precision) |precision| {
1113 if (precision > 0) try w.writeAll(".");
1114 } else if (trimmed.len > 0) {
1115 try w.writeAll(".");
1116 }
1117 try w.writeAll(trimmed);
1118 // Add trailing zeros if explicitly requested.
1119 if (opt_precision) |precision| if (precision > 0) {
1120 if (precision > trimmed.len)
1121 try w.splatByteAll('0', precision - trimmed.len);
1122 };
1123 try w.writeAll("p");
1124 try w.printIntOptions(exponent - exponent_bias, 10, .lower, .{});
1125}
1126
1127pub const ByteSizeUnits = enum {
1128 /// This formatter represents the number as multiple of 1000 and uses the SI
1129 /// measurement units (kB, MB, GB, ...).
1130 decimal,
1131 /// This formatter represents the number as multiple of 1024 and uses the IEC
1132 /// measurement units (KiB, MiB, GiB, ...).
1133 binary,
1134};
1135
1136/// Format option `precision` is ignored when `value` is less than 1kB
1137pub fn printByteSize(
1138 w: *std.io.Writer,
1139 value: u64,
1140 comptime units: ByteSizeUnits,
1141 options: std.fmt.Options,
1142) Error!void {
1143 if (value == 0) return w.alignBufferOptions("0B", options);
1144 // The worst case in terms of space needed is 32 bytes + 3 for the suffix.
1145 var buf: [std.fmt.float.min_buffer_size + 3]u8 = undefined;
1146
1147 const mags_si = " kMGTPEZY";
1148 const mags_iec = " KMGTPEZY";
1149
1150 const log2 = std.math.log2(value);
1151 const base = switch (units) {
1152 .decimal => 1000,
1153 .binary => 1024,
1154 };
1155 const magnitude = switch (units) {
1156 .decimal => @min(log2 / comptime std.math.log2(1000), mags_si.len - 1),
1157 .binary => @min(log2 / 10, mags_iec.len - 1),
1158 };
1159 const new_value = std.math.lossyCast(f64, value) / std.math.pow(f64, std.math.lossyCast(f64, base), std.math.lossyCast(f64, magnitude));
1160 const suffix = switch (units) {
1161 .decimal => mags_si[magnitude],
1162 .binary => mags_iec[magnitude],
1163 };
1164
1165 const s = switch (magnitude) {
1166 0 => buf[0..std.fmt.printInt(&buf, value, 10, .lower, .{})],
1167 else => std.fmt.float.render(&buf, new_value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1168 error.BufferTooSmall => unreachable,
1169 },
1170 };
1171
1172 var i: usize = s.len;
1173 if (suffix == ' ') {
1174 buf[i] = 'B';
1175 i += 1;
1176 } else switch (units) {
1177 .decimal => {
1178 buf[i..][0..2].* = [_]u8{ suffix, 'B' };
1179 i += 2;
1180 },
1181 .binary => {
1182 buf[i..][0..3].* = [_]u8{ suffix, 'i', 'B' };
1183 i += 3;
1184 },
1185 }
1186
1187 return w.alignBufferOptions(buf[0..i], options);
1188}
1189
1190// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
1191const ANY = "any";
1192
1193fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 {
1194 return if (std.mem.eql(u8, fmt[1..], ANY))
1195 ANY
1196 else
1197 fmt[1..];
1198}
1199
1200pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) noreturn {
1201 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
1202}
1203
1204pub fn printDurationSigned(w: *Writer, ns: i64) Error!void {
1205 if (ns < 0) try w.writeByte('-');
1206 return w.printDurationUnsigned(@abs(ns));
1207}
1208
1209pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {
1210 var ns_remaining = ns;
1211 inline for (.{
1212 .{ .ns = 365 * std.time.ns_per_day, .sep = 'y' },
1213 .{ .ns = std.time.ns_per_week, .sep = 'w' },
1214 .{ .ns = std.time.ns_per_day, .sep = 'd' },
1215 .{ .ns = std.time.ns_per_hour, .sep = 'h' },
1216 .{ .ns = std.time.ns_per_min, .sep = 'm' },
1217 }) |unit| {
1218 if (ns_remaining >= unit.ns) {
1219 const units = ns_remaining / unit.ns;
1220 try w.printIntOptions(units, 10, .lower, .{});
1221 try w.writeByte(unit.sep);
1222 ns_remaining -= units * unit.ns;
1223 if (ns_remaining == 0) return;
1224 }
1225 }
1226
1227 inline for (.{
1228 .{ .ns = std.time.ns_per_s, .sep = "s" },
1229 .{ .ns = std.time.ns_per_ms, .sep = "ms" },
1230 .{ .ns = std.time.ns_per_us, .sep = "us" },
1231 }) |unit| {
1232 const kunits = ns_remaining * 1000 / unit.ns;
1233 if (kunits >= 1000) {
1234 try w.printIntOptions(kunits / 1000, 10, .lower, .{});
1235 const frac = kunits % 1000;
1236 if (frac > 0) {
1237 // Write up to 3 decimal places
1238 var decimal_buf = [_]u8{ '.', 0, 0, 0 };
1239 var inner: Writer = .fixed(decimal_buf[1..]);
1240 inner.printIntOptions(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable;
1241 var end: usize = 4;
1242 while (end > 1) : (end -= 1) {
1243 if (decimal_buf[end - 1] != '0') break;
1244 }
1245 try w.writeAll(decimal_buf[0..end]);
1246 }
1247 return w.writeAll(unit.sep);
1248 }
1249 }
1250
1251 try w.printIntOptions(ns_remaining, 10, .lower, .{});
1252 try w.writeAll("ns");
1253}
1254
1255/// Writes number of nanoseconds according to its signed magnitude:
1256/// `[#y][#w][#d][#h][#m]#[.###][n|u|m]s`
1257/// `nanoseconds` must be an integer that coerces into `u64` or `i64`.
1258pub fn printDuration(w: *Writer, nanoseconds: anytype, options: std.fmt.Options) Error!void {
1259 // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24
1260 var buf: [24]u8 = undefined;
1261 var sub_bw: Writer = .fixed(&buf);
1262 switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) {
1263 .signed => sub_bw.printDurationSigned(nanoseconds) catch unreachable,
1264 .unsigned => sub_bw.printDurationUnsigned(nanoseconds) catch unreachable,
1265 }
1266 return w.alignBufferOptions(sub_bw.buffered(), options);
1267}
1268
1269pub fn printHex(w: *Writer, bytes: []const u8, case: std.fmt.Case) Error!void {
1270 const charset = switch (case) {
1271 .upper => "0123456789ABCDEF",
1272 .lower => "0123456789abcdef",
1273 };
1274 for (bytes) |c| {
1275 try w.writeByte(charset[c >> 4]);
1276 try w.writeByte(charset[c & 15]);
1277 }
1278}
1279
1280pub fn printBase64(w: *Writer, bytes: []const u8) Error!void {
1281 var chunker = std.mem.window(u8, bytes, 3, 3);
1282 var temp: [5]u8 = undefined;
1283 while (chunker.next()) |chunk| {
1284 try w.writeAll(std.base64.standard.Encoder.encode(&temp, chunk));
1285 }
1286}
1287
1288/// Write a single unsigned integer as LEB128 to the given writer.
1289pub fn writeUleb128(w: *Writer, value: anytype) Error!void {
1290 try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1291 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
1292 .int => |value_info| switch (value_info.signedness) {
1293 .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)),
1294 .unsigned => value,
1295 },
1296 else => comptime unreachable,
1297 });
1298}
1299
1300/// Write a single signed integer as LEB128 to the given writer.
1301pub fn writeSleb128(w: *Writer, value: anytype) Error!void {
1302 try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1303 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
1304 .int => |value_info| switch (value_info.signedness) {
1305 .signed => value,
1306 .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value),
1307 },
1308 else => comptime unreachable,
1309 });
1310}
1311
1312/// Write a single integer as LEB128 to the given writer.
1313pub fn writeLeb128(w: *Writer, value: anytype) Error!void {
1314 const value_info = @typeInfo(@TypeOf(value)).int;
1315 try w.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{
1316 .signedness = value_info.signedness,
1317 .bits = std.mem.alignForwardAnyAlign(u16, value_info.bits, 7),
1318 } }), value));
1319}
1320
1321fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {
1322 const value_info = @typeInfo(@TypeOf(value)).int;
1323 comptime assert(value_info.bits % 7 == 0);
1324 var remaining = value;
1325 while (true) {
1326 const buffer: []packed struct(u8) { bits: u7, more: bool } = @ptrCast(try w.writableSliceGreedy(1));
1327 for (buffer, 1..) |*byte, len| {
1328 const more = switch (value_info.signedness) {
1329 .signed => remaining >> 6 != remaining >> (value_info.bits - 1),
1330 .unsigned => remaining > std.math.maxInt(u7),
1331 };
1332 byte.* = if (@inComptime()) @typeInfo(@TypeOf(buffer)).pointer.child{
1333 .bits = @bitCast(@as(@Type(.{ .int = .{
1334 .signedness = value_info.signedness,
1335 .bits = 7,
1336 } }), @truncate(remaining))),
1337 .more = more,
1338 } else .{
1339 .bits = @bitCast(@as(@Type(.{ .int = .{
1340 .signedness = value_info.signedness,
1341 .bits = 7,
1342 } }), @truncate(remaining))),
1343 .more = more,
1344 };
1345 if (value_info.bits > 7) remaining >>= 7;
1346 if (!more) return w.advance(len);
1347 }
1348 w.advance(buffer.len);
1349 }
1350}
1351
1352test "formatValue max_depth" {
1353 const Vec2 = struct {
1354 const SelfType = @This();
1355 x: f32,
1356 y: f32,
1357
1358 pub fn format(
1359 self: SelfType,
1360 comptime fmt: []const u8,
1361 options: std.fmt.Options,
1362 w: *Writer,
1363 ) Error!void {
1364 _ = options;
1365 if (fmt.len == 0) {
1366 return w.print("({d:.3},{d:.3})", .{ self.x, self.y });
1367 } else {
1368 @compileError("unknown format string: '" ++ fmt ++ "'");
1369 }
1370 }
1371 };
1372 const E = enum {
1373 One,
1374 Two,
1375 Three,
1376 };
1377 const TU = union(enum) {
1378 const SelfType = @This();
1379 float: f32,
1380 int: u32,
1381 ptr: ?*SelfType,
1382 };
1383 const S = struct {
1384 const SelfType = @This();
1385 a: ?*SelfType,
1386 tu: TU,
1387 e: E,
1388 vec: Vec2,
1389 };
1390
1391 var inst = S{
1392 .a = null,
1393 .tu = TU{ .ptr = null },
1394 .e = E.Two,
1395 .vec = Vec2{ .x = 10.2, .y = 2.22 },
1396 };
1397 inst.a = &inst;
1398 inst.tu.ptr = &inst.tu;
1399
1400 var buf: [1000]u8 = undefined;
1401 var w: Writer = .fixed(&buf);
1402 try w.printValue("", .{}, inst, 0);
1403 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered());
1404
1405 w.reset();
1406 try w.printValue("", .{}, inst, 1);
1407 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
1408
1409 w.reset();
1410 try w.printValue("", .{}, inst, 2);
1411 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
1412
1413 w.reset();
1414 try w.printValue("", .{}, inst, 3);
1415 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
1416
1417 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
1418 w.reset();
1419 try w.printValue("", .{}, vec, 0);
1420 try testing.expectEqualStrings("{ ... }", w.buffered());
1421
1422 w.reset();
1423 try w.printValue("", .{}, vec, 1);
1424 try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());
1425}
1426
1427test printDuration {
1428 testDurationCase("0ns", 0);
1429 testDurationCase("1ns", 1);
1430 testDurationCase("999ns", std.time.ns_per_us - 1);
1431 testDurationCase("1us", std.time.ns_per_us);
1432 testDurationCase("1.45us", 1450);
1433 testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
1434 testDurationCase("14.5us", 14500);
1435 testDurationCase("145us", 145000);
1436 testDurationCase("999.999us", std.time.ns_per_ms - 1);
1437 testDurationCase("1ms", std.time.ns_per_ms + 1);
1438 testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
1439 testDurationCase("1.11ms", 1110000);
1440 testDurationCase("1.111ms", 1111000);
1441 testDurationCase("1.111ms", 1111100);
1442 testDurationCase("999.999ms", std.time.ns_per_s - 1);
1443 testDurationCase("1s", std.time.ns_per_s);
1444 testDurationCase("59.999s", std.time.ns_per_min - 1);
1445 testDurationCase("1m", std.time.ns_per_min);
1446 testDurationCase("1h", std.time.ns_per_hour);
1447 testDurationCase("1d", std.time.ns_per_day);
1448 testDurationCase("1w", std.time.ns_per_week);
1449 testDurationCase("1y", 365 * std.time.ns_per_day);
1450 testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
1451 testDurationCase("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1452 testDurationCase("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1453 testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1454 testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1455 testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1456 testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1457 testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
1458
1459 testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1460 testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1461 testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
1462}
1463
1464test printDurationSigned {
1465 testDurationCaseSigned("0ns", 0);
1466 testDurationCaseSigned("1ns", 1);
1467 testDurationCaseSigned("-1ns", -(1));
1468 testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
1469 testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
1470 testDurationCaseSigned("1us", std.time.ns_per_us);
1471 testDurationCaseSigned("-1us", -(std.time.ns_per_us));
1472 testDurationCaseSigned("1.45us", 1450);
1473 testDurationCaseSigned("-1.45us", -(1450));
1474 testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
1475 testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
1476 testDurationCaseSigned("14.5us", 14500);
1477 testDurationCaseSigned("-14.5us", -(14500));
1478 testDurationCaseSigned("145us", 145000);
1479 testDurationCaseSigned("-145us", -(145000));
1480 testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
1481 testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
1482 testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
1483 testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
1484 testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
1485 testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
1486 testDurationCaseSigned("1.11ms", 1110000);
1487 testDurationCaseSigned("-1.11ms", -(1110000));
1488 testDurationCaseSigned("1.111ms", 1111000);
1489 testDurationCaseSigned("-1.111ms", -(1111000));
1490 testDurationCaseSigned("1.111ms", 1111100);
1491 testDurationCaseSigned("-1.111ms", -(1111100));
1492 testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
1493 testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
1494 testDurationCaseSigned("1s", std.time.ns_per_s);
1495 testDurationCaseSigned("-1s", -(std.time.ns_per_s));
1496 testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
1497 testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
1498 testDurationCaseSigned("1m", std.time.ns_per_min);
1499 testDurationCaseSigned("-1m", -(std.time.ns_per_min));
1500 testDurationCaseSigned("1h", std.time.ns_per_hour);
1501 testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
1502 testDurationCaseSigned("1d", std.time.ns_per_day);
1503 testDurationCaseSigned("-1d", -(std.time.ns_per_day));
1504 testDurationCaseSigned("1w", std.time.ns_per_week);
1505 testDurationCaseSigned("-1w", -(std.time.ns_per_week));
1506 testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
1507 testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
1508 testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
1509 testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
1510 testDurationCaseSigned("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1511 testDurationCaseSigned("-1y1h1.001s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms));
1512 testDurationCaseSigned("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1513 testDurationCaseSigned("-1y1h1s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us));
1514 testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1515 testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
1516 testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1517 testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
1518 testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1519 testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
1520 testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1521 testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
1522 testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
1523 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
1524 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
1525
1526 testing.expectFmt("=======0ns", "{s:=>10}", .{0});
1527 testing.expectFmt("1ns=======", "{s:=<10}", .{1});
1528 testing.expectFmt("-1ns======", "{s:=<10}", .{-(1)});
1529 testing.expectFmt(" -999ns ", "{s:^10}", .{-(std.time.ns_per_us - 1)});
1530}
1531
1532fn testDurationCase(expected: []const u8, input: u64) !void {
1533 var buf: [24]u8 = undefined;
1534 var w: Writer = .fixed(&buf);
1535 try w.printDurationUnsigned(input);
1536 try testing.expectEqualStrings(expected, w.buffered());
1537}
1538
1539fn testDurationCaseSigned(expected: []const u8, input: i64) !void {
1540 var buf: [24]u8 = undefined;
1541 var w: Writer = .fixed(&buf);
1542 try w.printDurationSigned(input);
1543 try testing.expectEqualStrings(expected, w.buffered());
1544}
1545
1546test printIntOptions {
1547 try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{});
1548
1549 try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{});
1550 try testPrintIntCase("-12345678", @as(i32, -12345678), 10, .lower, .{});
1551 try testPrintIntCase("-bc614e", @as(i32, -12345678), 16, .lower, .{});
1552 try testPrintIntCase("-BC614E", @as(i32, -12345678), 16, .upper, .{});
1553
1554 try testPrintIntCase("12345678", @as(u32, 12345678), 10, .upper, .{});
1555
1556 try testPrintIntCase(" 666", @as(u32, 666), 10, .lower, .{ .width = 6 });
1557 try testPrintIntCase(" 1234", @as(u32, 0x1234), 16, .lower, .{ .width = 6 });
1558 try testPrintIntCase("1234", @as(u32, 0x1234), 16, .lower, .{ .width = 1 });
1559
1560 try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 });
1561 try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 });
1562}
1563
1564test "printInt with comptime_int" {
1565 var buf: [20]u8 = undefined;
1566 var w: Writer = .fixed(&buf);
1567 try w.printInt(@as(comptime_int, 123456789123456789), "", .{});
1568 try std.testing.expectEqualStrings("123456789123456789", w.buffered());
1569}
1570
1571test "printFloat with comptime_float" {
1572 var buf: [20]u8 = undefined;
1573 var w: Writer = .fixed(&buf);
1574 try w.printFloat("", .{}, @as(comptime_float, 1.0));
1575 try std.testing.expectEqualStrings(w.buffered(), "1e0");
1576 try std.testing.expectFmt("1e0", "{}", .{1.0});
1577}
1578
1579fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
1580 var buffer: [100]u8 = undefined;
1581 var w: Writer = .fixed(&buffer);
1582 w.printIntOptions(value, base, case, options);
1583 try testing.expectEqualStrings(expected, w.buffered());
1584}
1585
1586test printByteSize {
1587 try testing.expectFmt("file size: 42B\n", "file size: {B}\n", .{42});
1588 try testing.expectFmt("file size: 42B\n", "file size: {Bi}\n", .{42});
1589 try testing.expectFmt("file size: 63MB\n", "file size: {B}\n", .{63 * 1000 * 1000});
1590 try testing.expectFmt("file size: 63MiB\n", "file size: {Bi}\n", .{63 * 1024 * 1024});
1591 try testing.expectFmt("file size: 42B\n", "file size: {B:.2}\n", .{42});
1592 try testing.expectFmt("file size: 42B\n", "file size: {B:>9.2}\n", .{42});
1593 try testing.expectFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{63 * 1024 * 1024});
1594 try testing.expectFmt("file size: 60.08MiB\n", "file size: {Bi:.2}\n", .{63 * 1000 * 1000});
1595 try testing.expectFmt("file size: =66.06MB=\n", "file size: {B:=^9.2}\n", .{63 * 1024 * 1024});
1596 try testing.expectFmt("file size: 66.06MB\n", "file size: {B: >9.2}\n", .{63 * 1024 * 1024});
1597 try testing.expectFmt("file size: 66.06MB \n", "file size: {B: <9.2}\n", .{63 * 1024 * 1024});
1598 try testing.expectFmt("file size: 0.01844674407370955ZB\n", "file size: {B}\n", .{std.math.maxInt(u64)});
1599}
1600
1601test "bytes.hex" {
1602 const some_bytes = "\xCA\xFE\xBA\xBE";
1603 try std.testing.expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
1604 try std.testing.expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
1605 try std.testing.expectFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
1606 try std.testing.expectFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
1607 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
1608 try std.testing.expectFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
1609}
1610
1611test fixed {
1612 {
1613 var buf: [255]u8 = undefined;
1614 var w: Writer = .fixed(&buf);
1615 try w.print("{s}{s}!", .{ "Hello", "World" });
1616 try testing.expectEqualStrings("HelloWorld!", w.buffered());
1617 }
1618
1619 comptime {
1620 var buf: [255]u8 = undefined;
1621 var w: Writer = .fixed(&buf);
1622 try w.print("{s}{s}!", .{ "Hello", "World" });
1623 try testing.expectEqualStrings("HelloWorld!", w.buffered());
1624 }
1625}
1626
1627test "fixed output" {
1628 var buffer: [10]u8 = undefined;
1629 var w: Writer = .fixed(&buffer);
1630
1631 try w.writeAll("Hello");
1632 try testing.expect(std.mem.eql(u8, w.buffered(), "Hello"));
1633
1634 try w.writeAll("world");
1635 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
1636
1637 try testing.expectError(error.WriteStreamEnd, w.writeAll("!"));
1638 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
1639
1640 w.reset();
1641 try testing.expect(w.buffered().len == 0);
1642
1643 try testing.expectError(error.WriteStreamEnd, w.writeAll("Hello world!"));
1644 try testing.expect(std.mem.eql(u8, w.buffered(), "Hello worl"));
1645
1646 try w.seekTo((try w.getEndPos()) + 1);
1647 try testing.expectError(error.WriteStreamEnd, w.writeAll("H"));
1648}
1649
1650pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
1651 _ = w;
106 _ = data;1652 _ = data;
107 _ = splat;1653 _ = splat;
108 return error.WriteFailed;1654 return error.WriteFailed;
109}1655}
1101656
111pub fn failingWriteFile(1657pub fn failingSendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
112 context: ?*anyopaque,1658 _ = w;
113 file_reader: *File.Reader,
114 limit: Limit,
115 headers_and_trailers: []const []const u8,
116 headers_len: usize,
117) FileError!usize {
118 _ = context;
119 _ = file_reader;1659 _ = file_reader;
120 _ = limit;1660 _ = limit;
121 _ = headers_and_trailers;
122 _ = headers_len;
123 return error.WriteFailed;1661 return error.WriteFailed;
124}1662}
1251663
126pub const failing: Writer = .{1664pub fn discardingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
127 .context = undefined,1665 const slice = data[0 .. data.len - 1];
128 .vtable = &.{1666 const pattern = data[slice.len..];
129 .writeSplat = failingWriteSplat,
130 .writeFile = failingWriteFile,
131 },
132};
133
134pub fn discardingWriteSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Error!usize {
135 _ = context;
136 const headers = data[0 .. data.len - 1];
137 const pattern = data[headers.len..];
138 var written: usize = pattern.len * splat;1667 var written: usize = pattern.len * splat;
139 for (headers) |bytes| written += bytes.len;1668 for (slice) |bytes| written += bytes.len;
1669 w.end = 0;
140 return written;1670 return written;
141}1671}
1421672
143pub fn discardingWriteFile(1673pub fn discardingSendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
144 context: ?*anyopaque,1674 if (File.Handle == void) return error.Unimplemented;
145 file_reader: *std.fs.File.Reader,1675 if (w.end != 0) {
146 limit: Limit,1676 if (@intFromEnum(limit) >= w.end) {
147 headers_and_trailers: []const []const u8,1677 w.end = 0;
148 headers_len: usize,1678 } else {
149) Writer.FileError!usize {1679 const remaining = w.buffer[@intFromEnum(limit)..w.end];
150 _ = context;1680 @memmove(w.buffer[0..remaining.len], remaining);
151 if (file_reader.getSize()) |size| {1681 w.end = remaining.len;
152 const remaining = size - file_reader.pos;
153 const seek_amt = limit.minInt(remaining);
154 // Error is observable on `file_reader` instance, and is safe to ignore
155 // depending on the caller's needs. Caller can make that decision.
156 file_reader.seekBy(@intCast(seek_amt)) catch {};
157 var n: usize = seek_amt;
158 for (headers_and_trailers[0..headers_len]) |bytes| n += bytes.len;
159 if (seek_amt == remaining) {
160 // Since we made it all the way through the file, the trailers are
161 // also included.
162 for (headers_and_trailers[headers_len..]) |bytes| n += bytes.len;
163 }1682 }
1683 return 0;
1684 }
1685 if (file_reader.getSize()) |size| {
1686 const n = limit.minInt(size - file_reader.pos);
1687 file_reader.seekBy(@intCast(n)) catch return error.Unimplemented;
1688 w.end = 0;
164 return n;1689 return n;
165 } else |_| {1690 } else |_| {
166 // Error is observable on `file_reader` instance, and it is better to1691 // Error is observable on `file_reader` instance, and it is better to
...@@ -169,33 +1694,52 @@ pub fn discardingWriteFile(...@@ -169,33 +1694,52 @@ pub fn discardingWriteFile(
169 }1694 }
170}1695}
1711696
172pub const discarding: Writer = .{
173 .context = undefined,
174 .vtable = &.{
175 .writeSplat = discardingWriteSplat,
176 .writeFile = discardingWriteFile,
177 },
178};
179
180/// For use when the `Writer` implementation can cannot offer a more efficient1697/// For use when the `Writer` implementation can cannot offer a more efficient
181/// implementation than a basic read/write loop on the file.1698/// implementation than a basic read/write loop on the file.
182pub fn unimplementedWriteFile(1699pub fn unimplementedSendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
183 context: ?*anyopaque,1700 _ = w;
184 file_reader: *File.Reader,
185 limit: Limit,
186 headers_and_trailers: []const []const u8,
187 headers_len: usize,
188) FileError!usize {
189 _ = context;
190 _ = file_reader;1701 _ = file_reader;
191 _ = limit;1702 _ = limit;
192 _ = headers_and_trailers;
193 _ = headers_len;
194 return error.Unimplemented;1703 return error.Unimplemented;
195}1704}
1961705
1706/// When this function is called it usually means the buffer got full, so it's
1707/// time to return an error. However, we still need to make sure all of the
1708/// available buffer has been filled. Also, it may be called from `flush` in
1709/// which case it should return successfully.
1710fn fixedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
1711 for (data[0 .. data.len - 1]) |bytes| {
1712 const dest = w.buffer[w.end..];
1713 const len = @min(bytes.len, dest.len);
1714 @memcpy(dest[0..len], bytes[0..len]);
1715 w.end += len;
1716 if (bytes.len > dest.len) return error.WriteFailed;
1717 }
1718 const pattern = data[data.len - 1];
1719 const dest = w.buffer[w.end..];
1720 switch (pattern.len) {
1721 0 => return w.end,
1722 1 => {
1723 assert(splat >= dest.len);
1724 @memset(dest, pattern[0]);
1725 w.end += dest.len;
1726 return error.WriteFailed;
1727 },
1728 else => {
1729 for (0..splat) |i| {
1730 const remaining = dest[i * pattern.len ..];
1731 const len = @min(pattern.len, remaining.len);
1732 @memcpy(remaining[0..len], pattern[0..len]);
1733 w.end += len;
1734 if (pattern.len > remaining.len) return error.WriteFailed;
1735 }
1736 unreachable;
1737 },
1738 }
1739}
1740
197/// Provides a `Writer` implementation based on calling `Hasher.update`, sending1741/// Provides a `Writer` implementation based on calling `Hasher.update`, sending
198/// all data also to an underlying `std.io.BufferedWriter`.1742/// all data also to an underlying `Writer`.
199///1743///
200/// When using this, the underlying writer is best unbuffered because all1744/// When using this, the underlying writer is best unbuffered because all
201/// writes are passed on directly to it.1745/// writes are passed on directly to it.
...@@ -206,27 +1750,35 @@ pub fn unimplementedWriteFile(...@@ -206,27 +1750,35 @@ pub fn unimplementedWriteFile(
206/// details.1750/// details.
207pub fn Hashed(comptime Hasher: type) type {1751pub fn Hashed(comptime Hasher: type) type {
208 return struct {1752 return struct {
209 out: *std.io.BufferedWriter,1753 out: *Writer,
210 hasher: Hasher,1754 hasher: Hasher,
1755 interface: Writer,
2111756
212 pub fn writable(this: *@This(), buffer: []u8) std.io.BufferedWriter {1757 pub fn init(out: *Writer) @This() {
213 return .{1758 return .{
214 .unbuffered_writer = .{1759 .out = out,
215 .context = this,1760 .hasher = .{},
216 .vtable = &.{1761 .interface = .{
217 .writeSplat = @This().writeSplat,1762 .context = undefined,
218 .writeFile = Writer.unimplementedWriteFile,1763 .vtable = &.{@This().drain},
219 },
220 },1764 },
221 .buffer = buffer,
222 };1765 };
223 }1766 }
2241767
225 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {1768 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
226 const this: *@This() = @alignCast(@ptrCast(context));1769 const this: *@This() = @alignCast(@fieldParentPtr("interface", w));
227 const n = try this.out.writeSplat(data, splat);1770 const aux_n = try this.out.writeSplatAux(w.buffered(), data, splat);
228 const short_data = data[0 .. data.len - @intFromBool(splat == 0)];1771 if (aux_n <= w.end) {
1772 this.hasher.update(w.buffer[0..aux_n]);
1773 const remaining = w.buffer[aux_n..w.end];
1774 @memmove(w.buffer[0..remaining.len], remaining);
1775 w.end = remaining.len;
1776 return 0;
1777 }
1778 const n = aux_n - w.end;
1779 w.end = 0;
229 var remaining: usize = n;1780 var remaining: usize = n;
1781 const short_data = data[0 .. data.len - @intFromBool(splat == 0)];
230 for (short_data) |slice| {1782 for (short_data) |slice| {
231 if (remaining < slice.len) {1783 if (remaining < slice.len) {
232 this.hasher.update(slice[0..remaining]);1784 this.hasher.update(slice[0..remaining]);
...@@ -243,31 +1795,185 @@ pub fn Hashed(comptime Hasher: type) type {...@@ -243,31 +1795,185 @@ pub fn Hashed(comptime Hasher: type) type {
243 },1795 },
244 else => splat - 1,1796 else => splat - 1,
245 };1797 };
246 const last = data[data.len - 1];1798 const pattern = data[data.len - 1];
247 assert(remaining == remaining_splat * last.len);1799 assert(remaining == remaining_splat * pattern.len);
248 switch (last.len) {1800 switch (pattern.len) {
249 0 => {1801 0 => {
250 assert(remaining == 0);1802 assert(remaining == 0);
251 return n;
252 },1803 },
253 1 => {1804 1 => {
254 var buffer: [64]u8 = undefined;1805 var buffer: [64]u8 = undefined;
255 @memset(&buffer, last[0]);1806 @memset(&buffer, pattern[0]);
256 while (remaining > 0) {1807 while (remaining > 0) {
257 const update_len = @min(remaining, buffer.len);1808 const update_len = @min(remaining, buffer.len);
258 this.hasher.update(buffer[0..update_len]);1809 this.hasher.update(buffer[0..update_len]);
259 remaining -= update_len;1810 remaining -= update_len;
260 }1811 }
261 return n;
262 },1812 },
263 else => {},1813 else => {
264 }1814 while (remaining > 0) {
265 while (remaining > 0) {1815 const update_len = @min(remaining, pattern.len);
266 const update_len = @min(remaining, last.len);1816 this.hasher.update(pattern[0..update_len]);
267 this.hasher.update(last[0..update_len]);1817 remaining -= update_len;
268 remaining -= update_len;1818 }
1819 },
269 }1820 }
270 return n;1821 return n;
271 }1822 }
272 };1823 };
273}1824}
1825
1826/// Maintains `Writer` state such that it writes to the unused capacity of an
1827/// array list, filling it up completely before making a call through the
1828/// vtable, causing a resize. Consequently, the same, optimized, non-generic
1829/// machine code that uses `std.io.Reader`, such as formatted printing, takes
1830/// the hot paths when using this API.
1831///
1832/// When using this API, it is not necessary to call `flush`.
1833pub const Allocating = struct {
1834 allocator: Allocator,
1835 interface: Writer,
1836
1837 pub fn init(allocator: Allocator) Allocating {
1838 return .{
1839 .allocator = allocator,
1840 .interface = init_interface,
1841 .buffer = &.{},
1842 };
1843 }
1844
1845 pub fn initCapacity(allocator: Allocator, capacity: usize) error{OutOfMemory}!Allocating {
1846 return .{
1847 .allocator = allocator,
1848 .interface = init_interface,
1849 .buffer = try allocator.alloc(u8, capacity),
1850 };
1851 }
1852
1853 pub fn initOwnedSlice(allocator: Allocator, slice: []u8) Allocating {
1854 return .{
1855 .allocator = allocator,
1856 .interface = init_interface,
1857 .buffer = slice,
1858 };
1859 }
1860
1861 /// Replaces `array_list` with empty, taking ownership of the memory.
1862 pub fn fromArrayList(allocator: Allocator, array_list: *std.ArrayListUnmanaged(u8)) Allocating {
1863 defer array_list.* = .empty;
1864 return .{
1865 .allocator = allocator,
1866 .interface = init_interface,
1867 .buffer = array_list.allocatedSlice(),
1868 .end = array_list.items.len,
1869 };
1870 }
1871
1872 const init_interface: Writer = .{
1873 .interface = .{
1874 .context = undefined,
1875 .vtable = &.{
1876 .drain = Allocating.drain,
1877 .sendFile = Allocating.sendFile,
1878 },
1879 },
1880 };
1881
1882 pub fn deinit(a: *Allocating) void {
1883 a.allocator.free(a.buffer);
1884 a.* = undefined;
1885 }
1886
1887 /// Returns an array list that takes ownership of the allocated memory.
1888 /// Resets the `Allocating` to an empty state.
1889 pub fn toArrayList(a: *Allocating) std.ArrayListUnmanaged(u8) {
1890 const w = &a.interface;
1891 const result: std.ArrayListUnmanaged(u8) = .{
1892 .items = w.buffer[0..w.end],
1893 .capacity = w.buffer.len,
1894 };
1895 w.buffer = &.{};
1896 w.end = 0;
1897 return result;
1898 }
1899
1900 pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 {
1901 var list = a.toArrayList();
1902 return list.toOwnedSlice(a.allocator);
1903 }
1904
1905 pub fn toOwnedSliceSentinel(a: *Allocating, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 {
1906 const gpa = a.allocator;
1907 var list = toArrayList(a);
1908 return list.toOwnedSliceSentinel(gpa, sentinel);
1909 }
1910
1911 pub fn getWritten(a: *Allocating) []u8 {
1912 return a.interface.buffered();
1913 }
1914
1915 pub fn shrinkRetainingCapacity(a: *Allocating, new_len: usize) void {
1916 const shrink_by = a.interface.end - new_len;
1917 a.interface.end = new_len;
1918 a.interface.count -= shrink_by;
1919 }
1920
1921 pub fn clearRetainingCapacity(a: *Allocating) void {
1922 a.shrinkRetainingCapacity(0);
1923 }
1924
1925 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
1926 const a: *Allocating = @fieldParentPtr("interface", w);
1927 const gpa = a.allocator;
1928 const pattern = data[data.len - 1];
1929 const splat_len = pattern.len * splat;
1930 var list = a.toArrayList();
1931 defer setArrayList(a, list);
1932 const start_len = list.items.len;
1933 for (data[0 .. data.len - 1]) |bytes| {
1934 list.ensureUnusedCapacity(gpa, bytes.len + splat_len) catch return error.WriteFailed;
1935 list.appendSliceAssumeCapacity(bytes);
1936 }
1937 switch (pattern.len) {
1938 0 => {},
1939 1 => list.appendNTimesAssumeCapacity(pattern[0], splat),
1940 else => for (0..splat) |_| list.appendSliceAssumeCapacity(pattern),
1941 }
1942 return list.items.len - start_len;
1943 }
1944
1945 fn sendFile(w: *Writer, file_reader: *File.Reader, limit: std.io.Limit) FileError!usize {
1946 if (File.Handle == void) return error.Unimplemented;
1947 const a: *Allocating = @fieldParentPtr("interface", w);
1948 const gpa = a.allocator;
1949 var list = a.toArrayList();
1950 defer setArrayList(a, list);
1951 const pos = file_reader.pos;
1952 const additional = if (file_reader.getSize()) |size| size - pos else |_| std.atomic.cache_line;
1953 list.ensureUnusedCapacity(gpa, limit.minInt(additional)) catch return error.WriteFailed;
1954 const dest = limit.slice(list.unusedCapacitySlice());
1955 const n = file_reader.read(dest) catch |err| switch (err) {
1956 error.ReadFailed => return error.ReadFailed,
1957 error.EndOfStream => 0,
1958 };
1959 list.items.len += n;
1960 return n;
1961 }
1962
1963 fn setArrayList(a: *Allocating, list: std.ArrayListUnmanaged(u8)) void {
1964 a.buffer = list.allocatedSlice();
1965 a.end = list.items.len;
1966 }
1967
1968 test Allocating {
1969 var a: Allocating = .init(std.testing.allocator);
1970 defer a.deinit();
1971 const w = &a.interface;
1972
1973 const x: i32 = 42;
1974 const y: i32 = 1234;
1975 try w.print("x: {}\ny: {}\n", .{ x, y });
1976
1977 try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", a.getWritten());
1978 }
1979};
lib/std/io/tty.zig+2-2
...@@ -73,7 +73,7 @@ pub const Config = union(enum) {...@@ -73,7 +73,7 @@ pub const Config = union(enum) {
7373
74 pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || std.io.Writer.Error;74 pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || std.io.Writer.Error;
7575
76 pub fn setColor(conf: Config, bw: *std.io.BufferedWriter, color: Color) SetColorError!void {76 pub fn setColor(conf: Config, w: *std.io.Writer, color: Color) SetColorError!void {
77 nosuspend switch (conf) {77 nosuspend switch (conf) {
78 .no_color => return,78 .no_color => return,
79 .escape_codes => {79 .escape_codes => {
...@@ -98,7 +98,7 @@ pub const Config = union(enum) {...@@ -98,7 +98,7 @@ pub const Config = union(enum) {
98 .dim => "\x1b[2m",98 .dim => "\x1b[2m",
99 .reset => "\x1b[0m",99 .reset => "\x1b[0m",
100 };100 };
101 try bw.writeAll(color_string);101 try w.writeAll(color_string);
102 },102 },
103 .windows_api => |ctx| if (native_os == .windows) {103 .windows_api => |ctx| if (native_os == .windows) {
104 const attributes = switch (color) {104 const attributes = switch (color) {
lib/std/json.zig+2-2
...@@ -127,9 +127,9 @@ pub fn Formatter(comptime T: type) type {...@@ -127,9 +127,9 @@ pub fn Formatter(comptime T: type) type {
127 self: @This(),127 self: @This(),
128 comptime fmt_spec: []const u8,128 comptime fmt_spec: []const u8,
129 options: std.fmt.FormatOptions,129 options: std.fmt.FormatOptions,
130 writer: *std.io.BufferedWriter,130 writer: *std.io.Writer,
131 ) !void {131 ) !void {
132 _ = fmt_spec;132 comptime std.debug.assert(fmt_spec.len == 0);
133 _ = options;133 _ = options;
134 try Stringify.value(self.value, self.options, writer);134 try Stringify.value(self.value, self.options, writer);
135 }135 }
lib/std/json/Stringify.zig+13-16
...@@ -23,13 +23,14 @@ const Allocator = std.mem.Allocator;...@@ -23,13 +23,14 @@ const Allocator = std.mem.Allocator;
23const ArrayList = std.ArrayList;23const ArrayList = std.ArrayList;
24const BitStack = std.BitStack;24const BitStack = std.BitStack;
25const Stringify = @This();25const Stringify = @This();
26const Writer = std.io.Writer;
2627
27const IndentationMode = enum(u1) {28const IndentationMode = enum(u1) {
28 object = 0,29 object = 0,
29 array = 1,30 array = 1,
30};31};
3132
32writer: *std.io.BufferedWriter,33writer: *Writer,
33options: Options = .{},34options: Options = .{},
34indent_level: usize = 0,35indent_level: usize = 0,
35next_punctuation: enum {36next_punctuation: enum {
...@@ -77,7 +78,7 @@ const safety_checks: @TypeOf(safety_checks_hint) = if (build_mode_has_safety)...@@ -77,7 +78,7 @@ const safety_checks: @TypeOf(safety_checks_hint) = if (build_mode_has_safety)
77else78else
78 .assumed_correct;79 .assumed_correct;
7980
80pub const Error = std.io.Writer.Error;81pub const Error = Writer.Error;
8182
82pub fn beginArray(self: *Stringify) Error!void {83pub fn beginArray(self: *Stringify) Error!void {
83 if (build_mode_has_safety) assert(self.raw_streaming_mode == .none);84 if (build_mode_has_safety) assert(self.raw_streaming_mode == .none);
...@@ -224,8 +225,7 @@ pub fn print(self: *Stringify, comptime fmt: []const u8, args: anytype) Error!vo...@@ -224,8 +225,7 @@ pub fn print(self: *Stringify, comptime fmt: []const u8, args: anytype) Error!vo
224225
225test print {226test print {
226 var out_buf: [1024]u8 = undefined;227 var out_buf: [1024]u8 = undefined;
227 var out: std.io.BufferedWriter = undefined;228 var out: Writer = .fixed(&out_buf);
228 out.initFixed(&out_buf);
229229
230 var w: Stringify = .{ .writer = &out, .options = .{ .whitespace = .indent_2 } };230 var w: Stringify = .{ .writer = &out, .options = .{ .whitespace = .indent_2 } };
231231
...@@ -567,10 +567,10 @@ pub const Options = struct {...@@ -567,10 +567,10 @@ pub const Options = struct {
567 emit_nonportable_numbers_as_strings: bool = false,567 emit_nonportable_numbers_as_strings: bool = false,
568};568};
569569
570/// Writes the given value to the `std.io.Writer` writer.570/// Writes the given value to the `Writer` writer.
571/// See `Stringify` for how the given value is serialized into JSON.571/// See `Stringify` for how the given value is serialized into JSON.
572/// The maximum nesting depth of the output JSON document is 256.572/// The maximum nesting depth of the output JSON document is 256.
573pub fn value(v: anytype, options: Options, writer: *std.io.BufferedWriter) Error!void {573pub fn value(v: anytype, options: Options, writer: *Writer) Error!void {
574 var s: Stringify = .{ .writer = writer, .options = options };574 var s: Stringify = .{ .writer = writer, .options = options };
575 try s.write(v);575 try s.write(v);
576}576}
...@@ -634,7 +634,7 @@ test valueAlloc {...@@ -634,7 +634,7 @@ test valueAlloc {
634 try std.testing.expectEqualStrings(expected, actual);634 try std.testing.expectEqualStrings(expected, actual);
635}635}
636636
637fn outputUnicodeEscape(codepoint: u21, bw: *std.io.BufferedWriter) Error!void {637fn outputUnicodeEscape(codepoint: u21, bw: *Writer) Error!void {
638 if (codepoint <= 0xFFFF) {638 if (codepoint <= 0xFFFF) {
639 // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),639 // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
640 // then it may be represented as a six-character sequence: a reverse solidus, followed640 // then it may be represented as a six-character sequence: a reverse solidus, followed
...@@ -654,7 +654,7 @@ fn outputUnicodeEscape(codepoint: u21, bw: *std.io.BufferedWriter) Error!void {...@@ -654,7 +654,7 @@ fn outputUnicodeEscape(codepoint: u21, bw: *std.io.BufferedWriter) Error!void {
654 }654 }
655}655}
656656
657fn outputSpecialEscape(c: u8, writer: *std.io.BufferedWriter) Error!void {657fn outputSpecialEscape(c: u8, writer: *Writer) Error!void {
658 switch (c) {658 switch (c) {
659 '\\' => try writer.writeAll("\\\\"),659 '\\' => try writer.writeAll("\\\\"),
660 '\"' => try writer.writeAll("\\\""),660 '\"' => try writer.writeAll("\\\""),
...@@ -668,14 +668,14 @@ fn outputSpecialEscape(c: u8, writer: *std.io.BufferedWriter) Error!void {...@@ -668,14 +668,14 @@ fn outputSpecialEscape(c: u8, writer: *std.io.BufferedWriter) Error!void {
668}668}
669669
670/// Write `string` to `writer` as a JSON encoded string.670/// Write `string` to `writer` as a JSON encoded string.
671pub fn encodeJsonString(string: []const u8, options: Options, writer: *std.io.BufferedWriter) Error!void {671pub fn encodeJsonString(string: []const u8, options: Options, writer: *Writer) Error!void {
672 try writer.writeByte('\"');672 try writer.writeByte('\"');
673 try encodeJsonStringChars(string, options, writer);673 try encodeJsonStringChars(string, options, writer);
674 try writer.writeByte('\"');674 try writer.writeByte('\"');
675}675}
676676
677/// Write `chars` to `writer` as JSON encoded string characters.677/// Write `chars` to `writer` as JSON encoded string characters.
678pub fn encodeJsonStringChars(chars: []const u8, options: Options, writer: *std.io.BufferedWriter) Error!void {678pub fn encodeJsonStringChars(chars: []const u8, options: Options, writer: *Writer) Error!void {
679 var write_cursor: usize = 0;679 var write_cursor: usize = 0;
680 var i: usize = 0;680 var i: usize = 0;
681 if (options.escape_unicode) {681 if (options.escape_unicode) {
...@@ -718,8 +718,7 @@ pub fn encodeJsonStringChars(chars: []const u8, options: Options, writer: *std.i...@@ -718,8 +718,7 @@ pub fn encodeJsonStringChars(chars: []const u8, options: Options, writer: *std.i
718718
719test "json write stream" {719test "json write stream" {
720 var out_buf: [1024]u8 = undefined;720 var out_buf: [1024]u8 = undefined;
721 var out: std.io.BufferedWriter = undefined;721 var out: Writer = .fixed(&out_buf);
722 out.initFixed(&out_buf);
723 var w: Stringify = .{ .writer = &out, .options = .{ .whitespace = .indent_2 } };722 var w: Stringify = .{ .writer = &out, .options = .{ .whitespace = .indent_2 } };
724 try testBasicWriteStream(&w);723 try testBasicWriteStream(&w);
725}724}
...@@ -971,16 +970,14 @@ test "stringify struct with custom stringifier" {...@@ -971,16 +970,14 @@ test "stringify struct with custom stringifier" {
971970
972fn testStringify(expected: []const u8, v: anytype, options: Options) !void {971fn testStringify(expected: []const u8, v: anytype, options: Options) !void {
973 var buffer: [4096]u8 = undefined;972 var buffer: [4096]u8 = undefined;
974 var bw: std.io.BufferedWriter = undefined;973 var bw: Writer = .fixed(&buffer);
975 bw.initFixed(&buffer);
976 try value(v, options, &bw);974 try value(v, options, &bw);
977 try std.testing.expectEqualStrings(expected, bw.getWritten());975 try std.testing.expectEqualStrings(expected, bw.getWritten());
978}976}
979977
980test "raw streaming" {978test "raw streaming" {
981 var out_buf: [1024]u8 = undefined;979 var out_buf: [1024]u8 = undefined;
982 var out: std.io.BufferedWriter = undefined;980 var out: Writer = .fixed(&out_buf);
983 out.initFixed(&out_buf);
984981
985 var w: Stringify = .{ .writer = &out, .options = .{ .whitespace = .indent_2 } };982 var w: Stringify = .{ .writer = &out, .options = .{ .whitespace = .indent_2 } };
986 try w.beginObject();983 try w.beginObject();
lib/std/json/dynamic_test.zig+3-4
...@@ -4,6 +4,7 @@ const mem = std.mem;...@@ -4,6 +4,7 @@ const mem = std.mem;
4const testing = std.testing;4const testing = std.testing;
5const ArenaAllocator = std.heap.ArenaAllocator;5const ArenaAllocator = std.heap.ArenaAllocator;
6const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
7const Writer = std.io.Writer;
78
8const ObjectMap = @import("dynamic.zig").ObjectMap;9const ObjectMap = @import("dynamic.zig").ObjectMap;
9const Array = @import("dynamic.zig").Array;10const Array = @import("dynamic.zig").Array;
...@@ -73,8 +74,7 @@ test "json.parser.dynamic" {...@@ -73,8 +74,7 @@ test "json.parser.dynamic" {
7374
74test "write json then parse it" {75test "write json then parse it" {
75 var out_buffer: [1000]u8 = undefined;76 var out_buffer: [1000]u8 = undefined;
76 var fixed_writer: std.io.BufferedWriter = undefined;77 var fixed_writer: Writer = .fixed(&out_buffer);
77 fixed_writer.initFixed(&out_buffer);
78 var jw: json.Stringify = .{ .writer = &fixed_writer, .options = .{} };78 var jw: json.Stringify = .{ .writer = &fixed_writer, .options = .{} };
7979
80 try jw.beginObject();80 try jw.beginObject();
...@@ -240,8 +240,7 @@ test "Value.jsonStringify" {...@@ -240,8 +240,7 @@ test "Value.jsonStringify" {
240 .{ .object = obj },240 .{ .object = obj },
241 };241 };
242 var buffer: [0x1000]u8 = undefined;242 var buffer: [0x1000]u8 = undefined;
243 var fixed_writer: std.io.BufferedWriter = undefined;243 var fixed_writer: Writer = .fixed(&buffer);
244 fixed_writer.initFixed(&buffer);
245244
246 var jw: json.Stringify = .{ .writer = &fixed_writer, .options = .{ .whitespace = .indent_1 } };245 var jw: json.Stringify = .{ .writer = &fixed_writer, .options = .{ .whitespace = .indent_1 } };
247 try jw.write(array);246 try jw.write(array);
lib/std/leb128.zig+3-3
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const testing = std.testing;3const testing = std.testing;
4const Writer = std.io.Writer;
45
5/// This is an "advanced" function. It allows one to use a fixed amount of memory to store a6/// This is an "advanced" function. It allows one to use a fixed amount of memory to store a
6/// ULEB128. This defeats the entire purpose of using this data encoding; it will no longer use7/// ULEB128. This defeats the entire purpose of using this data encoding; it will no longer use
...@@ -241,7 +242,7 @@ fn test_write_leb128(value: anytype) !void {...@@ -241,7 +242,7 @@ fn test_write_leb128(value: anytype) !void {
241 const signedness = @typeInfo(T).int.signedness;242 const signedness = @typeInfo(T).int.signedness;
242 const t_signed = signedness == .signed;243 const t_signed = signedness == .signed;
243244
244 const writeStream = if (t_signed) std.io.BufferedWriter.writeIleb128 else std.io.BufferedWriter.writeUleb128;245 const writeStream = if (t_signed) Writer.writeIleb128 else Writer.writeUleb128;
245 const readStream = if (t_signed) std.io.Reader.readIleb128 else std.io.Reader.readUleb128;246 const readStream = if (t_signed) std.io.Reader.readIleb128 else std.io.Reader.readUleb128;
246247
247 // decode to a larger bit size too, to ensure sign extension248 // decode to a larger bit size too, to ensure sign extension
...@@ -261,8 +262,7 @@ fn test_write_leb128(value: anytype) !void {...@@ -261,8 +262,7 @@ fn test_write_leb128(value: anytype) !void {
261 const max_groups = if (@typeInfo(T).int.bits == 0) 1 else (@typeInfo(T).int.bits + 6) / 7;262 const max_groups = if (@typeInfo(T).int.bits == 0) 1 else (@typeInfo(T).int.bits + 6) / 7;
262263
263 var buf: [max_groups]u8 = undefined;264 var buf: [max_groups]u8 = undefined;
264 var bw: std.io.BufferedWriter = undefined;265 var bw: Writer = .fixed(&buf);
265 bw.initFixed(&buf);
266266
267 // stream write267 // stream write
268 try testing.expect((try writeStream(&bw, value)) == bytes_needed);268 try testing.expect((try writeStream(&bw, value)) == bytes_needed);
lib/std/math/big/int.zig+1-1
...@@ -2322,7 +2322,7 @@ pub const Const = struct {...@@ -2322,7 +2322,7 @@ pub const Const = struct {
2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2325 pub fn format(self: Const, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {2325 pub fn format(self: Const, bw: *std.io.Writer, comptime fmt: []const u8) !void {
2326 comptime var base = 10;2326 comptime var base = 10;
2327 comptime var case: std.fmt.Case = .lower;2327 comptime var case: std.fmt.Case = .lower;
23282328
lib/std/net.zig+1-1
...@@ -1915,7 +1915,7 @@ pub const Stream = struct {...@@ -1915,7 +1915,7 @@ pub const Stream = struct {
19151915
1916 fn read(1916 fn read(
1917 context: ?*anyopaque,1917 context: ?*anyopaque,
1918 bw: *std.io.BufferedWriter,1918 bw: *std.io.Writer,
1919 limit: std.io.Limit,1919 limit: std.io.Limit,
1920 ) std.io.Reader.Error!usize {1920 ) std.io.Reader.Error!usize {
1921 const buf = limit.slice(try bw.writableSliceGreedy(1));1921 const buf = limit.slice(try bw.writableSliceGreedy(1));
lib/std/tar.zig+11-19
...@@ -358,7 +358,7 @@ pub const Iterator = struct {...@@ -358,7 +358,7 @@ pub const Iterator = struct {
358 };358 };
359 }359 }
360360
361 fn read(context: ?*anyopaque, bw: *std.io.BufferedWriter, limit: std.io.Limit) std.io.Reader.StreamError!usize {361 fn read(context: ?*anyopaque, bw: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
362 const file: *File = @ptrCast(@alignCast(context));362 const file: *File = @ptrCast(@alignCast(context));
363 if (file.unread_bytes.* == 0) return error.EndOfStream;363 if (file.unread_bytes.* == 0) return error.EndOfStream;
364 const n = try file.parent_reader.read(bw, limit.min(.limited(file.unread_bytes.*)));364 const n = try file.parent_reader.read(bw, limit.min(.limited(file.unread_bytes.*)));
...@@ -381,7 +381,7 @@ pub const Iterator = struct {...@@ -381,7 +381,7 @@ pub const Iterator = struct {
381 return n;381 return n;
382 }382 }
383383
384 pub fn readRemaining(file: *File, out: *std.io.BufferedWriter) std.io.Reader.StreamRemainingError!void {384 pub fn readRemaining(file: *File, out: *std.io.Writer) std.io.Reader.StreamRemainingError!void {
385 return file.reader().readRemaining(out);385 return file.reader().readRemaining(out);
386 }386 }
387 };387 };
...@@ -818,8 +818,7 @@ test PaxIterator {...@@ -818,8 +818,7 @@ test PaxIterator {
818 var buffer: [1024]u8 = undefined;818 var buffer: [1024]u8 = undefined;
819819
820 outer: for (cases) |case| {820 outer: for (cases) |case| {
821 var br: std.io.Reader = undefined;821 var br: std.io.Reader = .fixed(case.data);
822 br.initFixed(case.data);
823 var iter: PaxIterator = .init(&br, case.data.len);822 var iter: PaxIterator = .init(&br, case.data.len);
824823
825 var i: usize = 0;824 var i: usize = 0;
...@@ -955,8 +954,7 @@ test Iterator {...@@ -955,8 +954,7 @@ test Iterator {
955 // example/empty/954 // example/empty/
956955
957 const data = @embedFile("tar/testdata/example.tar");956 const data = @embedFile("tar/testdata/example.tar");
958 var br: std.io.Reader = undefined;957 var br: std.io.Reader = .fixed(data);
959 br.initFixed(data);
960958
961 // User provided buffers to the iterator959 // User provided buffers to the iterator
962 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;960 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
...@@ -1015,8 +1013,7 @@ test pipeToFileSystem {...@@ -1015,8 +1013,7 @@ test pipeToFileSystem {
1015 // example/empty/1013 // example/empty/
10161014
1017 const data = @embedFile("tar/testdata/example.tar");1015 const data = @embedFile("tar/testdata/example.tar");
1018 var br: std.io.Reader = undefined;1016 var br: std.io.Reader = .fixed(data);
1019 br.initFixed(data);
10201017
1021 var tmp = testing.tmpDir(.{ .no_follow = true });1018 var tmp = testing.tmpDir(.{ .no_follow = true });
1022 defer tmp.cleanup();1019 defer tmp.cleanup();
...@@ -1047,8 +1044,7 @@ test pipeToFileSystem {...@@ -1047,8 +1044,7 @@ test pipeToFileSystem {
10471044
1048test "pipeToFileSystem root_dir" {1045test "pipeToFileSystem root_dir" {
1049 const data = @embedFile("tar/testdata/example.tar");1046 const data = @embedFile("tar/testdata/example.tar");
1050 var br: std.io.Reader = undefined;1047 var br: std.io.Reader = .fixed(data);
1051 br.initFixed(data);
10521048
1053 // with strip_components = 11049 // with strip_components = 1
1054 {1050 {
...@@ -1073,7 +1069,7 @@ test "pipeToFileSystem root_dir" {...@@ -1073,7 +1069,7 @@ test "pipeToFileSystem root_dir" {
10731069
1074 // with strip_components = 01070 // with strip_components = 0
1075 {1071 {
1076 br.initFixed(data);1072 br = .fixed(data);
1077 var tmp = testing.tmpDir(.{ .no_follow = true });1073 var tmp = testing.tmpDir(.{ .no_follow = true });
1078 defer tmp.cleanup();1074 defer tmp.cleanup();
1079 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1075 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
...@@ -1096,8 +1092,7 @@ test "pipeToFileSystem root_dir" {...@@ -1096,8 +1092,7 @@ test "pipeToFileSystem root_dir" {
10961092
1097test "findRoot with single file archive" {1093test "findRoot with single file archive" {
1098 const data = @embedFile("tar/testdata/22752.tar");1094 const data = @embedFile("tar/testdata/22752.tar");
1099 var br: std.io.Reader = undefined;1095 var br: std.io.Reader = .fixed(data);
1100 br.initFixed(data);
11011096
1102 var tmp = testing.tmpDir(.{});1097 var tmp = testing.tmpDir(.{});
1103 defer tmp.cleanup();1098 defer tmp.cleanup();
...@@ -1111,8 +1106,7 @@ test "findRoot with single file archive" {...@@ -1111,8 +1106,7 @@ test "findRoot with single file archive" {
11111106
1112test "findRoot without explicit root dir" {1107test "findRoot without explicit root dir" {
1113 const data = @embedFile("tar/testdata/19820.tar");1108 const data = @embedFile("tar/testdata/19820.tar");
1114 var br: std.io.Reader = undefined;1109 var br: std.io.Reader = .fixed(data);
1115 br.initFixed(data);
11161110
1117 var tmp = testing.tmpDir(.{});1111 var tmp = testing.tmpDir(.{});
1118 defer tmp.cleanup();1112 defer tmp.cleanup();
...@@ -1126,8 +1120,7 @@ test "findRoot without explicit root dir" {...@@ -1126,8 +1120,7 @@ test "findRoot without explicit root dir" {
11261120
1127test "pipeToFileSystem strip_components" {1121test "pipeToFileSystem strip_components" {
1128 const data = @embedFile("tar/testdata/example.tar");1122 const data = @embedFile("tar/testdata/example.tar");
1129 var br: std.io.Reader = undefined;1123 var br: std.io.Reader = .fixed(data);
1130 br.initFixed(data);
11311124
1132 var tmp = testing.tmpDir(.{ .no_follow = true });1125 var tmp = testing.tmpDir(.{ .no_follow = true });
1133 defer tmp.cleanup();1126 defer tmp.cleanup();
...@@ -1188,8 +1181,7 @@ test "executable bit" {...@@ -1188,8 +1181,7 @@ test "executable bit" {
1188 const data = @embedFile("tar/testdata/example.tar");1181 const data = @embedFile("tar/testdata/example.tar");
11891182
1190 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {1183 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {
1191 var br: std.io.Reader = undefined;1184 var br: std.io.Reader = .fixed(data);
1192 br.initFixed(data);
11931185
1194 var tmp = testing.tmpDir(.{ .no_follow = true });1186 var tmp = testing.tmpDir(.{ .no_follow = true });
1195 //defer tmp.cleanup();1187 //defer tmp.cleanup();
lib/std/tar/Writer.zig+6-10
...@@ -14,7 +14,7 @@ pub const Options = struct {...@@ -14,7 +14,7 @@ pub const Options = struct {
14 mtime: u64 = 0,14 mtime: u64 = 0,
15};15};
1616
17underlying_writer: *std.io.BufferedWriter,17underlying_writer: *std.io.Writer,
18prefix: []const u8 = "",18prefix: []const u8 = "",
19mtime_now: u64 = 0,19mtime_now: u64 = 0,
2020
...@@ -277,7 +277,7 @@ pub const Header = extern struct {...@@ -277,7 +277,7 @@ pub const Header = extern struct {
277 try octal(&w.checksum, checksum);277 try octal(&w.checksum, checksum);
278 }278 }
279279
280 pub fn write(h: *Header, bw: *std.io.BufferedWriter) error{ OctalOverflow, WriteFailed }!void {280 pub fn write(h: *Header, bw: *std.io.Writer) error{ OctalOverflow, WriteFailed }!void {
281 try h.updateChecksum();281 try h.updateChecksum();
282 try bw.writeAll(std.mem.asBytes(h));282 try bw.writeAll(std.mem.asBytes(h));
283 }283 }
...@@ -433,16 +433,14 @@ test "write files" {...@@ -433,16 +433,14 @@ test "write files" {
433 {433 {
434 const root = "root";434 const root = "root";
435435
436 var output: std.io.AllocatingWriter = undefined;436 var output: std.io.AllocatingWriter = .init(testing.allocator);
437 output.init(testing.allocator);
438 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };437 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };
439 defer output.deinit();438 defer output.deinit();
440 try wrt.setRoot(root);439 try wrt.setRoot(root);
441 for (files) |file|440 for (files) |file|
442 try wrt.writeFileBytes(file.path, file.content, .{});441 try wrt.writeFileBytes(file.path, file.content, .{});
443442
444 var input: std.io.Reader = undefined;443 var input: std.io.Reader = .fixed(output.getWritten());
445 input.initFixed(output.getWritten());
446 var iter = std.tar.iterator(&input, .{444 var iter = std.tar.iterator(&input, .{
447 .file_name_buffer = &file_name_buffer,445 .file_name_buffer = &file_name_buffer,
448 .link_name_buffer = &link_name_buffer,446 .link_name_buffer = &link_name_buffer,
...@@ -476,13 +474,11 @@ test "write files" {...@@ -476,13 +474,11 @@ test "write files" {
476 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };474 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };
477 defer output.deinit();475 defer output.deinit();
478 for (files) |file| {476 for (files) |file| {
479 var content: std.io.Reader = undefined;477 var content: std.io.Reader = .fixed(file.content);
480 content.initFixed(file.content);
481 try wrt.writeFileStream(file.path, file.content.len, &content, .{});478 try wrt.writeFileStream(file.path, file.content.len, &content, .{});
482 }479 }
483480
484 var input: std.io.Reader = undefined;481 var input: std.io.Reader = .fixed(output.getWritten());
485 input.initFixed(output.getWritten());
486 var iter = std.tar.iterator(&input, .{482 var iter = std.tar.iterator(&input, .{
487 .file_name_buffer = &file_name_buffer,483 .file_name_buffer = &file_name_buffer,
488 .link_name_buffer = &link_name_buffer,484 .link_name_buffer = &link_name_buffer,
lib/std/testing.zig+4-3
...@@ -2,6 +2,7 @@ const std = @import("std.zig");...@@ -2,6 +2,7 @@ const std = @import("std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const math = std.math;4const math = std.math;
5const Writer = std.io.Writer;
56
6/// Provides deterministic randomness in unit tests.7/// Provides deterministic randomness in unit tests.
7/// Initialized on startup. Read-only after that.8/// Initialized on startup. Read-only after that.
...@@ -459,7 +460,7 @@ fn SliceDiffer(comptime T: type) type {...@@ -459,7 +460,7 @@ fn SliceDiffer(comptime T: type) type {
459460
460 const Self = @This();461 const Self = @This();
461462
462 pub fn write(self: Self, bw: *std.io.BufferedWriter) !void {463 pub fn write(self: Self, bw: *Writer) !void {
463 for (self.expected, 0..) |value, i| {464 for (self.expected, 0..) |value, i| {
464 const full_index = self.start_index + i;465 const full_index = self.start_index + i;
465 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;466 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;
...@@ -480,7 +481,7 @@ const BytesDiffer = struct {...@@ -480,7 +481,7 @@ const BytesDiffer = struct {
480 actual: []const u8,481 actual: []const u8,
481 ttyconf: std.io.tty.Config,482 ttyconf: std.io.tty.Config,
482483
483 pub fn write(self: BytesDiffer, bw: *std.io.BufferedWriter) !void {484 pub fn write(self: BytesDiffer, bw: *Writer) !void {
484 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);485 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);
485 var row: usize = 0;486 var row: usize = 0;
486 while (expected_iterator.next()) |chunk| {487 while (expected_iterator.next()) |chunk| {
...@@ -526,7 +527,7 @@ const BytesDiffer = struct {...@@ -526,7 +527,7 @@ const BytesDiffer = struct {
526 }527 }
527 }528 }
528529
529 fn writeDiff(self: BytesDiffer, bw: *std.io.BufferedWriter, comptime fmt: []const u8, args: anytype, diff: bool) !void {530 fn writeDiff(self: BytesDiffer, bw: *Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void {
530 if (diff) try self.ttyconf.setColor(bw, .red);531 if (diff) try self.ttyconf.setColor(bw, .red);
531 try bw.print(fmt, args);532 try bw.print(fmt, args);
532 if (diff) try self.ttyconf.setColor(bw, .reset);533 if (diff) try self.ttyconf.setColor(bw, .reset);
lib/std/tz.zig+3-6
...@@ -215,8 +215,7 @@ pub const Tz = struct {...@@ -215,8 +215,7 @@ pub const Tz = struct {
215215
216test "slim" {216test "slim" {
217 const data = @embedFile("tz/asia_tokyo.tzif");217 const data = @embedFile("tz/asia_tokyo.tzif");
218 var in_stream: std.io.Reader = undefined;218 var in_stream: std.io.Reader = .fixed(data);
219 in_stream.initFixed(data);
220219
221 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);220 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
222 defer tz.deinit();221 defer tz.deinit();
...@@ -229,8 +228,7 @@ test "slim" {...@@ -229,8 +228,7 @@ test "slim" {
229228
230test "fat" {229test "fat" {
231 const data = @embedFile("tz/antarctica_davis.tzif");230 const data = @embedFile("tz/antarctica_davis.tzif");
232 var in_stream: std.io.Reader = undefined;231 var in_stream: std.io.Reader = .fixed(data);
233 in_stream.initFixed(data);
234232
235 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);233 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
236 defer tz.deinit();234 defer tz.deinit();
...@@ -243,8 +241,7 @@ test "fat" {...@@ -243,8 +241,7 @@ test "fat" {
243test "legacy" {241test "legacy" {
244 // Taken from Slackware 8.0, from 2001242 // Taken from Slackware 8.0, from 2001
245 const data = @embedFile("tz/europe_vatican.tzif");243 const data = @embedFile("tz/europe_vatican.tzif");
246 var in_stream: std.io.Reader = undefined;244 var in_stream: std.io.Reader = .fixed(data);
247 in_stream.initFixed(data);
248245
249 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);246 var tz = try std.Tz.parse(std.testing.allocator, &in_stream);
250 defer tz.deinit();247 defer tz.deinit();
lib/std/zig.zig+8-15
...@@ -2,6 +2,12 @@...@@ -2,6 +2,12 @@
2//! source lives here. These APIs are provided as-is and have absolutely no API2//! source lives here. These APIs are provided as-is and have absolutely no API
3//! guarantees whatsoever.3//! guarantees whatsoever.
44
5const std = @import("std.zig");
6const tokenizer = @import("zig/tokenizer.zig");
7const assert = std.debug.assert;
8const Allocator = std.mem.Allocator;
9const Writer = std.io.Writer;
10
5pub const ErrorBundle = @import("zig/ErrorBundle.zig");11pub const ErrorBundle = @import("zig/ErrorBundle.zig");
6pub const Server = @import("zig/Server.zig");12pub const Server = @import("zig/Server.zig");
7pub const Client = @import("zig/Client.zig");13pub const Client = @import("zig/Client.zig");
...@@ -356,11 +362,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![...@@ -356,11 +362,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![
356 return buffer.toOwnedSlice();362 return buffer.toOwnedSlice();
357}363}
358364
359const std = @import("std.zig");
360const tokenizer = @import("zig/tokenizer.zig");
361const assert = std.debug.assert;
362const Allocator = std.mem.Allocator;
363
364/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.365/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.
365///366///
366/// - An empty `{}` format specifier escapes invalid identifiers, identifiers that shadow primitives367/// - An empty `{}` format specifier escapes invalid identifiers, identifiers that shadow primitives
...@@ -412,11 +413,7 @@ test fmtId {...@@ -412,11 +413,7 @@ test fmtId {
412}413}
413414
414/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.415/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
415fn formatId(416fn formatId(bytes: []const u8, bw: *Writer, comptime fmt: []const u8) !void {
416 bytes: []const u8,
417 bw: *std.io.BufferedWriter,
418 comptime fmt: []const u8,
419) !void {
420 const allow_primitive, const allow_underscore = comptime parse_fmt: {417 const allow_primitive, const allow_underscore = comptime parse_fmt: {
421 var allow_primitive = false;418 var allow_primitive = false;
422 var allow_underscore = false;419 var allow_underscore = false;
...@@ -470,11 +467,7 @@ test fmtEscapes {...@@ -470,11 +467,7 @@ test fmtEscapes {
470/// Print the string as escaped contents of a double quoted or single-quoted string.467/// Print the string as escaped contents of a double quoted or single-quoted string.
471/// Format `{}` treats contents as a double-quoted string.468/// Format `{}` treats contents as a double-quoted string.
472/// Format `{'}` treats contents as a single-quoted string.469/// Format `{'}` treats contents as a single-quoted string.
473pub fn stringEscape(470pub fn stringEscape(bytes: []const u8, bw: *Writer, comptime f: []const u8) !void {
474 bytes: []const u8,
475 bw: *std.io.BufferedWriter,
476 comptime f: []const u8,
477) !void {
478 for (bytes) |byte| switch (byte) {471 for (bytes) |byte| switch (byte) {
479 '\n' => try bw.writeAll("\\n"),472 '\n' => try bw.writeAll("\\n"),
480 '\r' => try bw.writeAll("\\r"),473 '\r' => try bw.writeAll("\\r"),
lib/std/zig/Ast.zig+12-11
...@@ -4,6 +4,16 @@...@@ -4,6 +4,16 @@
4//! For Zon syntax, the root node is at nodes[0] and contains lhs as the node4//! For Zon syntax, the root node is at nodes[0] and contains lhs as the node
5//! index of the main expression.5//! index of the main expression.
66
7const std = @import("../std.zig");
8const assert = std.debug.assert;
9const testing = std.testing;
10const mem = std.mem;
11const Token = std.zig.Token;
12const Ast = @This();
13const Allocator = std.mem.Allocator;
14const Parse = @import("Parse.zig");
15const Writer = std.io.Writer;
16
7/// Reference to externally-owned data.17/// Reference to externally-owned data.
8source: [:0]const u8,18source: [:0]const u8,
919
...@@ -205,7 +215,7 @@ pub fn renderAlloc(tree: Ast, gpa: Allocator) error{OutOfMemory}![]u8 {...@@ -205,7 +215,7 @@ pub fn renderAlloc(tree: Ast, gpa: Allocator) error{OutOfMemory}![]u8 {
205215
206pub const Render = @import("Ast/Render.zig");216pub const Render = @import("Ast/Render.zig");
207217
208pub fn render(tree: Ast, gpa: Allocator, bw: *std.io.BufferedWriter, fixups: Render.Fixups) Render.Error!void {218pub fn render(tree: Ast, gpa: Allocator, bw: *Writer, fixups: Render.Fixups) Render.Error!void {
209 return Render.tree(gpa, bw, tree, fixups);219 return Render.tree(gpa, bw, tree, fixups);
210}220}
211221
...@@ -311,7 +321,7 @@ pub fn rootDecls(tree: Ast) []const Node.Index {...@@ -311,7 +321,7 @@ pub fn rootDecls(tree: Ast) []const Node.Index {
311 }321 }
312}322}
313323
314pub fn renderError(tree: Ast, parse_error: Error, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {324pub fn renderError(tree: Ast, parse_error: Error, bw: *Writer) Writer.Error!void {
315 switch (parse_error.tag) {325 switch (parse_error.tag) {
316 .asterisk_after_ptr_deref => {326 .asterisk_after_ptr_deref => {
317 // Note that the token will point at the `.*` but ideally the source327 // Note that the token will point at the `.*` but ideally the source
...@@ -4118,15 +4128,6 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex...@@ -4118,15 +4128,6 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex
4118 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };4128 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };
4119}4129}
41204130
4121const std = @import("../std.zig");
4122const assert = std.debug.assert;
4123const testing = std.testing;
4124const mem = std.mem;
4125const Token = std.zig.Token;
4126const Ast = @This();
4127const Allocator = std.mem.Allocator;
4128const Parse = @import("Parse.zig");
4129
4130test {4131test {
4131 _ = Parse;4132 _ = Parse;
4132 _ = Render;4133 _ = Render;
lib/std/zig/Ast/Render.zig+6-5
...@@ -6,6 +6,7 @@ const meta = std.meta;...@@ -6,6 +6,7 @@ const meta = std.meta;
6const Ast = std.zig.Ast;6const Ast = std.zig.Ast;
7const Token = std.zig.Token;7const Token = std.zig.Token;
8const primitives = std.zig.primitives;8const primitives = std.zig.primitives;
9const Writer = std.io.Writer;
910
10const Render = @This();11const Render = @This();
1112
...@@ -82,7 +83,7 @@ pub const Fixups = struct {...@@ -82,7 +83,7 @@ pub const Fixups = struct {
82 }83 }
83};84};
8485
85pub fn renderTree(gpa: Allocator, bw: *std.io.BufferedWriter, tree: Ast, fixups: Fixups) Error!void {86pub fn renderTree(gpa: Allocator, bw: *Writer, tree: Ast, fixups: Fixups) Error!void {
86 assert(tree.errors.len == 0); // Cannot render an invalid tree.87 assert(tree.errors.len == 0); // Cannot render an invalid tree.
87 var auto_indenting_stream: AutoIndentingStream = .init(gpa, bw, indent_delta);88 var auto_indenting_stream: AutoIndentingStream = .init(gpa, bw, indent_delta);
88 defer auto_indenting_stream.deinit();89 defer auto_indenting_stream.deinit();
...@@ -3136,7 +3137,7 @@ fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenI...@@ -3136,7 +3137,7 @@ fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenI
3136 return false;3137 return false;
3137}3138}
31383139
3139fn writeFixingWhitespace(bw: *std.io.BufferedWriter, slice: []const u8) Error!void {3140fn writeFixingWhitespace(bw: *Writer, slice: []const u8) Error!void {
3140 for (slice) |byte| switch (byte) {3141 for (slice) |byte| switch (byte) {
3141 '\t' => try bw.splatByteAll(' ', indent_delta),3142 '\t' => try bw.splatByteAll(' ', indent_delta),
3142 '\r' => {},3143 '\r' => {},
...@@ -3266,7 +3267,7 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi...@@ -3266,7 +3267,7 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi
3266/// This should be done whenever a scope that ends in a .semicolon or a3267/// This should be done whenever a scope that ends in a .semicolon or a
3267/// .comma is introduced.3268/// .comma is introduced.
3268const AutoIndentingStream = struct {3269const AutoIndentingStream = struct {
3269 underlying_writer: *std.io.BufferedWriter,3270 underlying_writer: *Writer,
32703271
3271 /// Offset into the source at which formatting has been disabled with3272 /// Offset into the source at which formatting has been disabled with
3272 /// a `zig fmt: off` comment.3273 /// a `zig fmt: off` comment.
...@@ -3301,10 +3302,10 @@ const AutoIndentingStream = struct {...@@ -3301,10 +3302,10 @@ const AutoIndentingStream = struct {
3301 indent_count: usize,3302 indent_count: usize,
3302 };3303 };
33033304
3304 pub fn init(gpa: Allocator, bw: *std.io.BufferedWriter, indent_delta_: usize) AutoIndentingStream {3305 pub fn init(gpa: Allocator, bw: *Writer, starting_indent_delta: usize) AutoIndentingStream {
3305 return .{3306 return .{
3306 .underlying_writer = bw,3307 .underlying_writer = bw,
3307 .indent_delta = indent_delta_,3308 .indent_delta = starting_indent_delta,
3308 .indent_stack = .init(gpa),3309 .indent_stack = .init(gpa),
3309 .space_stack = .init(gpa),3310 .space_stack = .init(gpa),
3310 };3311 };
lib/std/zig/ErrorBundle.zig+10-9
...@@ -7,6 +7,12 @@...@@ -7,6 +7,12 @@
7//! empty, it means there are no errors. This special encoding exists so that7//! empty, it means there are no errors. This special encoding exists so that
8//! heap allocation is not needed in the common case of no errors.8//! heap allocation is not needed in the common case of no errors.
99
10const std = @import("std");
11const ErrorBundle = @This();
12const Allocator = std.mem.Allocator;
13const assert = std.debug.assert;
14const Writer = std.io.Writer;
15
10string_bytes: []const u8,16string_bytes: []const u8,
11/// The first thing in this array is an `ErrorMessageList`.17/// The first thing in this array is an `ErrorMessageList`.
12extra: []const u32,18extra: []const u32,
...@@ -163,7 +169,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {...@@ -163,7 +169,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {
163 renderToWriter(eb, options, bw) catch return;169 renderToWriter(eb, options, bw) catch return;
164}170}
165171
166pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, bw: *std.io.BufferedWriter) (std.io.Writer.Error || std.posix.UnexpectedError)!void {172pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, bw: *Writer) (Writer.Error || std.posix.UnexpectedError)!void {
167 if (eb.extra.len == 0) return;173 if (eb.extra.len == 0) return;
168 for (eb.getMessages()) |err_msg| {174 for (eb.getMessages()) |err_msg| {
169 try renderErrorMessageToWriter(eb, options, err_msg, bw, "error", .red, 0);175 try renderErrorMessageToWriter(eb, options, err_msg, bw, "error", .red, 0);
...@@ -182,11 +188,11 @@ fn renderErrorMessageToWriter(...@@ -182,11 +188,11 @@ fn renderErrorMessageToWriter(
182 eb: ErrorBundle,188 eb: ErrorBundle,
183 options: RenderOptions,189 options: RenderOptions,
184 err_msg_index: MessageIndex,190 err_msg_index: MessageIndex,
185 bw: *std.io.BufferedWriter,191 bw: *Writer,
186 kind: []const u8,192 kind: []const u8,
187 color: std.io.tty.Color,193 color: std.io.tty.Color,
188 indent: usize,194 indent: usize,
189) (std.io.Writer.Error || std.posix.UnexpectedError)!void {195) (Writer.Error || std.posix.UnexpectedError)!void {
190 const ttyconf = options.ttyconf;196 const ttyconf = options.ttyconf;
191 const err_msg = eb.getErrorMessage(err_msg_index);197 const err_msg = eb.getErrorMessage(err_msg_index);
192 const prefix_start = bw.count;198 const prefix_start = bw.count;
...@@ -294,7 +300,7 @@ fn renderErrorMessageToWriter(...@@ -294,7 +300,7 @@ fn renderErrorMessageToWriter(
294/// to allow for long, good-looking error messages.300/// to allow for long, good-looking error messages.
295///301///
296/// This is used to split the message in `@compileError("hello\nworld")` for example.302/// This is used to split the message in `@compileError("hello\nworld")` for example.
297fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *std.io.BufferedWriter, indent: usize) !void {303fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *Writer, indent: usize) !void {
298 var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n');304 var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n');
299 while (lines.next()) |line| {305 while (lines.next()) |line| {
300 try bw.writeAll(line);306 try bw.writeAll(line);
...@@ -304,11 +310,6 @@ fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *std.io.BufferedWriter,...@@ -304,11 +310,6 @@ fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *std.io.BufferedWriter,
304 }310 }
305}311}
306312
307const std = @import("std");
308const ErrorBundle = @This();
309const Allocator = std.mem.Allocator;
310const assert = std.debug.assert;
311
312pub const Wip = struct {313pub const Wip = struct {
313 gpa: Allocator,314 gpa: Allocator,
314 string_bytes: std.ArrayListUnmanaged(u8),315 string_bytes: std.ArrayListUnmanaged(u8),
lib/std/zig/Server.zig+3-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1in: *std.io.Reader,1in: *std.io.Reader,
2out: *std.io.BufferedWriter,2out: *Writer,
33
4pub const Message = struct {4pub const Message = struct {
5 pub const Header = extern struct {5 pub const Header = extern struct {
...@@ -94,7 +94,7 @@ pub const Message = struct {...@@ -94,7 +94,7 @@ pub const Message = struct {
9494
95pub const Options = struct {95pub const Options = struct {
96 in: *std.io.Reader,96 in: *std.io.Reader,
97 out: *std.io.BufferedWriter,97 out: *Writer,
98 zig_version: []const u8,98 zig_version: []const u8,
99};99};
100100
...@@ -215,3 +215,4 @@ const assert = std.debug.assert;...@@ -215,3 +215,4 @@ const assert = std.debug.assert;
215const native_endian = builtin.target.cpu.arch.endian();215const native_endian = builtin.target.cpu.arch.endian();
216const need_bswap = native_endian != .little;216const need_bswap = native_endian != .little;
217const Cache = std.Build.Cache;217const Cache = std.Build.Cache;
218const Writer = std.io.Writer;
lib/std/zig/WindowsSdk.zig+6-6
...@@ -1,11 +1,12 @@...@@ -1,11 +1,12 @@
1const WindowsSdk = @This();
2const builtin = @import("builtin");
3const std = @import("std");
4const Writer = std.io.Writer;
5
1windows10sdk: ?Installation,6windows10sdk: ?Installation,
2windows81sdk: ?Installation,7windows81sdk: ?Installation,
3msvc_lib_dir: ?[]const u8,8msvc_lib_dir: ?[]const u8,
49
5const WindowsSdk = @This();
6const std = @import("std");
7const builtin = @import("builtin");
8
9const windows = std.os.windows;10const windows = std.os.windows;
10const RRF = windows.advapi32.RRF;11const RRF = windows.advapi32.RRF;
1112
...@@ -759,8 +760,7 @@ const MsvcLibDir = struct {...@@ -759,8 +760,7 @@ const MsvcLibDir = struct {
759 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {760 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {
760 if (entry.kind != .directory) continue;761 if (entry.kind != .directory) continue;
761762
762 var bw: std.io.BufferedWriter = undefined;763 var bw: Writer = .fixed(&state_subpath_buf);
763 bw.initFixed(&state_subpath_buf);
764764
765 bw.writeAll(entry.name) catch unreachable;765 bw.writeAll(entry.name) catch unreachable;
766 bw.writeByte(std.fs.path.sep) catch unreachable;766 bw.writeByte(std.fs.path.sep) catch unreachable;
lib/std/zig/ZonGen.zig+3-2
...@@ -521,8 +521,8 @@ pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {...@@ -521,8 +521,8 @@ pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
521pub fn parseStrLit(521pub fn parseStrLit(
522 tree: Ast,522 tree: Ast,
523 node: Ast.Node.Index,523 node: Ast.Node.Index,
524 writer: *std.io.BufferedWriter,524 writer: *Writer,
525) std.io.Writer.Error!std.zig.string_literal.Result {525) Writer.Error!std.zig.string_literal.Result {
526 switch (tree.nodeTag(node)) {526 switch (tree.nodeTag(node)) {
527 .string_literal => {527 .string_literal => {
528 const token = tree.nodeMainToken(node);528 const token = tree.nodeMainToken(node);
...@@ -933,3 +933,4 @@ const StringIndexContext = std.hash_map.StringIndexContext;...@@ -933,3 +933,4 @@ const StringIndexContext = std.hash_map.StringIndexContext;
933const ZonGen = @This();933const ZonGen = @This();
934const Zoir = @import("Zoir.zig");934const Zoir = @import("Zoir.zig");
935const Ast = @import("Ast.zig");935const Ast = @import("Ast.zig");
936const Writer = std.io.Writer;
lib/std/zig/llvm/Builder.zig+35-38
...@@ -91,7 +91,7 @@ pub const String = enum(u32) {...@@ -91,7 +91,7 @@ pub const String = enum(u32) {
91 string: String,91 string: String,
92 builder: *const Builder,92 builder: *const Builder,
93 };93 };
94 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {94 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
95 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|95 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
96 @compileError("invalid format string: '" ++ fmt_str ++ "'");96 @compileError("invalid format string: '" ++ fmt_str ++ "'");
97 assert(data.string != .none);97 assert(data.string != .none);
...@@ -649,7 +649,7 @@ pub const Type = enum(u32) {...@@ -649,7 +649,7 @@ pub const Type = enum(u32) {
649 type: Type,649 type: Type,
650 builder: *const Builder,650 builder: *const Builder,
651 };651 };
652 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {652 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
653 assert(data.type != .none);653 assert(data.type != .none);
654 if (comptime std.mem.eql(u8, fmt_str, "m")) {654 if (comptime std.mem.eql(u8, fmt_str, "m")) {
655 const item = data.builder.type_items.items[@intFromEnum(data.type)];655 const item = data.builder.type_items.items[@intFromEnum(data.type)];
...@@ -1129,7 +1129,7 @@ pub const Attribute = union(Kind) {...@@ -1129,7 +1129,7 @@ pub const Attribute = union(Kind) {
1129 attribute_index: Index,1129 attribute_index: Index,
1130 builder: *const Builder,1130 builder: *const Builder,
1131 };1131 };
1132 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {1132 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
1133 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_|1133 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_|
1134 @compileError("invalid format string: '" ++ fmt_str ++ "'");1134 @compileError("invalid format string: '" ++ fmt_str ++ "'");
1135 const attribute = data.attribute_index.toAttribute(data.builder);1135 const attribute = data.attribute_index.toAttribute(data.builder);
...@@ -1568,7 +1568,7 @@ pub const Attributes = enum(u32) {...@@ -1568,7 +1568,7 @@ pub const Attributes = enum(u32) {
1568 attributes: Attributes,1568 attributes: Attributes,
1569 builder: *const Builder,1569 builder: *const Builder,
1570 };1570 };
1571 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {1571 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
1572 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{1572 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{
1573 .attribute_index = attribute_index,1573 .attribute_index = attribute_index,
1574 .builder = data.builder,1574 .builder = data.builder,
...@@ -1761,11 +1761,11 @@ pub const Linkage = enum(u4) {...@@ -1761,11 +1761,11 @@ pub const Linkage = enum(u4) {
1761 extern_weak = 7,1761 extern_weak = 7,
1762 external = 0,1762 external = 0,
17631763
1764 pub fn format(self: Linkage, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1764 pub fn format(self: Linkage, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1765 if (self != .external) try bw.print(" {s}", .{@tagName(self)});1765 if (self != .external) try bw.print(" {s}", .{@tagName(self)});
1766 }1766 }
17671767
1768 fn formatOptional(data: ?Linkage, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1768 fn formatOptional(data: ?Linkage, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1769 if (data) |linkage| try bw.print(" {s}", .{@tagName(linkage)});1769 if (data) |linkage| try bw.print(" {s}", .{@tagName(linkage)});
1770 }1770 }
1771 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {1771 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {
...@@ -1778,7 +1778,7 @@ pub const Preemption = enum {...@@ -1778,7 +1778,7 @@ pub const Preemption = enum {
1778 dso_local,1778 dso_local,
1779 implicit_dso_local,1779 implicit_dso_local,
17801780
1781 pub fn format(self: Preemption, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1781 pub fn format(self: Preemption, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1782 if (self == .dso_local) try bw.print(" {s}", .{@tagName(self)});1782 if (self == .dso_local) try bw.print(" {s}", .{@tagName(self)});
1783 }1783 }
1784};1784};
...@@ -1796,11 +1796,7 @@ pub const Visibility = enum(u2) {...@@ -1796,11 +1796,7 @@ pub const Visibility = enum(u2) {
1796 };1796 };
1797 }1797 }
17981798
1799 pub fn format(1799 pub fn format(self: Visibility, comptime format_string: []const u8, writer: *Writer) Writer.Error!void {
1800 self: Visibility,
1801 comptime format_string: []const u8,
1802 writer: *std.io.BufferedWriter,
1803 ) std.io.Writer.Error!void {
1804 comptime assert(format_string.len == 0);1800 comptime assert(format_string.len == 0);
1805 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1801 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1806 }1802 }
...@@ -1811,7 +1807,7 @@ pub const DllStorageClass = enum(u2) {...@@ -1811,7 +1807,7 @@ pub const DllStorageClass = enum(u2) {
1811 dllimport = 1,1807 dllimport = 1,
1812 dllexport = 2,1808 dllexport = 2,
18131809
1814 pub fn format(self: DllStorageClass, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1810 pub fn format(self: DllStorageClass, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1815 if (self != .default) try bw.print(" {s}", .{@tagName(self)});1811 if (self != .default) try bw.print(" {s}", .{@tagName(self)});
1816 }1812 }
1817};1813};
...@@ -1823,7 +1819,7 @@ pub const ThreadLocal = enum(u3) {...@@ -1823,7 +1819,7 @@ pub const ThreadLocal = enum(u3) {
1823 initialexec = 3,1819 initialexec = 3,
1824 localexec = 4,1820 localexec = 4,
18251821
1826 pub fn format(self: ThreadLocal, bw: *std.io.BufferedWriter, comptime prefix: []const u8) std.io.Writer.Error!void {1822 pub fn format(self: ThreadLocal, bw: *Writer, comptime prefix: []const u8) Writer.Error!void {
1827 if (self == .default) return;1823 if (self == .default) return;
1828 try bw.print("{s}thread_local", .{prefix});1824 try bw.print("{s}thread_local", .{prefix});
1829 if (self != .generaldynamic) try bw.print("({s})", .{@tagName(self)});1825 if (self != .generaldynamic) try bw.print("({s})", .{@tagName(self)});
...@@ -1837,7 +1833,7 @@ pub const UnnamedAddr = enum(u2) {...@@ -1837,7 +1833,7 @@ pub const UnnamedAddr = enum(u2) {
1837 unnamed_addr = 1,1833 unnamed_addr = 1,
1838 local_unnamed_addr = 2,1834 local_unnamed_addr = 2,
18391835
1840 pub fn format(self: UnnamedAddr, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1836 pub fn format(self: UnnamedAddr, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1841 if (self != .default) try bw.print(" {s}", .{@tagName(self)});1837 if (self != .default) try bw.print(" {s}", .{@tagName(self)});
1842 }1838 }
1843};1839};
...@@ -1931,7 +1927,7 @@ pub const AddrSpace = enum(u24) {...@@ -1931,7 +1927,7 @@ pub const AddrSpace = enum(u24) {
1931 pub const funcref: AddrSpace = @enumFromInt(20);1927 pub const funcref: AddrSpace = @enumFromInt(20);
1932 };1928 };
19331929
1934 pub fn format(self: AddrSpace, bw: *std.io.BufferedWriter, comptime prefix: []const u8) std.io.Writer.Error!void {1930 pub fn format(self: AddrSpace, bw: *Writer, comptime prefix: []const u8) Writer.Error!void {
1935 if (self != .default) try bw.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });1931 if (self != .default) try bw.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
1936 }1932 }
1937};1933};
...@@ -1940,7 +1936,7 @@ pub const ExternallyInitialized = enum {...@@ -1940,7 +1936,7 @@ pub const ExternallyInitialized = enum {
1940 default,1936 default,
1941 externally_initialized,1937 externally_initialized,
19421938
1943 pub fn format(self: ExternallyInitialized, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1939 pub fn format(self: ExternallyInitialized, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1944 if (self != .default) try bw.print(" {s}", .{@tagName(self)});1940 if (self != .default) try bw.print(" {s}", .{@tagName(self)});
1945 }1941 }
1946};1942};
...@@ -1964,7 +1960,7 @@ pub const Alignment = enum(u6) {...@@ -1964,7 +1960,7 @@ pub const Alignment = enum(u6) {
1964 return if (self == .default) 0 else (@intFromEnum(self) + 1);1960 return if (self == .default) 0 else (@intFromEnum(self) + 1);
1965 }1961 }
19661962
1967 pub fn format(self: Alignment, bw: *std.io.BufferedWriter, comptime prefix: []const u8) std.io.Writer.Error!void {1963 pub fn format(self: Alignment, bw: *Writer, comptime prefix: []const u8) Writer.Error!void {
1968 try bw.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });1964 try bw.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
1969 }1965 }
1970};1966};
...@@ -2038,7 +2034,7 @@ pub const CallConv = enum(u10) {...@@ -2038,7 +2034,7 @@ pub const CallConv = enum(u10) {
20382034
2039 pub const default = CallConv.ccc;2035 pub const default = CallConv.ccc;
20402036
2041 pub fn format(self: CallConv, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {2037 pub fn format(self: CallConv, bw: *Writer, comptime _: []const u8) Writer.Error!void {
2042 switch (self) {2038 switch (self) {
2043 default => {},2039 default => {},
2044 .fastcc,2040 .fastcc,
...@@ -2119,7 +2115,7 @@ pub const StrtabString = enum(u32) {...@@ -2119,7 +2115,7 @@ pub const StrtabString = enum(u32) {
2119 string: StrtabString,2115 string: StrtabString,
2120 builder: *const Builder,2116 builder: *const Builder,
2121 };2117 };
2122 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {2118 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
2123 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|2119 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
2124 @compileError("invalid format string: '" ++ fmt_str ++ "'");2120 @compileError("invalid format string: '" ++ fmt_str ++ "'");
2125 assert(data.string != .none);2121 assert(data.string != .none);
...@@ -2306,7 +2302,7 @@ pub const Global = struct {...@@ -2306,7 +2302,7 @@ pub const Global = struct {
2306 global: Index,2302 global: Index,
2307 builder: *const Builder,2303 builder: *const Builder,
2308 };2304 };
2309 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {2305 fn format(data: FormatData, bw: *Writer, comptime _: []const u8) Writer.Error!void {
2310 try bw.print("@{f}", .{2306 try bw.print("@{f}", .{
2311 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),2307 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),
2312 });2308 });
...@@ -4752,7 +4748,7 @@ pub const Function = struct {...@@ -4752,7 +4748,7 @@ pub const Function = struct {
4752 function: Function.Index,4748 function: Function.Index,
4753 builder: *Builder,4749 builder: *Builder,
4754 };4750 };
4755 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {4751 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
4756 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|4752 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
4757 @compileError("invalid format string: '" ++ fmt_str ++ "'");4753 @compileError("invalid format string: '" ++ fmt_str ++ "'");
4758 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {4754 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
...@@ -6944,7 +6940,7 @@ pub const MemoryAccessKind = enum(u1) {...@@ -6944,7 +6940,7 @@ pub const MemoryAccessKind = enum(u1) {
6944 normal,6940 normal,
6945 @"volatile",6941 @"volatile",
69466942
6947 pub fn format(self: MemoryAccessKind, bw: *std.io.BufferedWriter, comptime prefix: []const u8) std.io.Writer.Error!void {6943 pub fn format(self: MemoryAccessKind, bw: *Writer, comptime prefix: []const u8) Writer.Error!void {
6948 if (self != .normal) try bw.print("{s}{s}", .{ prefix, @tagName(self) });6944 if (self != .normal) try bw.print("{s}{s}", .{ prefix, @tagName(self) });
6949 }6945 }
6950};6946};
...@@ -6953,7 +6949,7 @@ pub const SyncScope = enum(u1) {...@@ -6953,7 +6949,7 @@ pub const SyncScope = enum(u1) {
6953 singlethread,6949 singlethread,
6954 system,6950 system,
69556951
6956 pub fn format(self: SyncScope, bw: *std.io.BufferedWriter, comptime prefix: []const u8) std.io.Writer.Error!void {6952 pub fn format(self: SyncScope, bw: *Writer, comptime prefix: []const u8) Writer.Error!void {
6957 if (self != .system) try bw.print(6953 if (self != .system) try bw.print(
6958 \\{s}syncscope("{s}")6954 \\{s}syncscope("{s}")
6959 , .{ prefix, @tagName(self) });6955 , .{ prefix, @tagName(self) });
...@@ -6969,7 +6965,7 @@ pub const AtomicOrdering = enum(u3) {...@@ -6969,7 +6965,7 @@ pub const AtomicOrdering = enum(u3) {
6969 acq_rel = 5,6965 acq_rel = 5,
6970 seq_cst = 6,6966 seq_cst = 6,
69716967
6972 pub fn format(self: AtomicOrdering, bw: *std.io.BufferedWriter, comptime prefix: []const u8) std.io.Writer.Error!void {6968 pub fn format(self: AtomicOrdering, bw: *Writer, comptime prefix: []const u8) Writer.Error!void {
6973 if (self != .none) try bw.print("{s}{s}", .{ prefix, @tagName(self) });6969 if (self != .none) try bw.print("{s}{s}", .{ prefix, @tagName(self) });
6974 }6970 }
6975};6971};
...@@ -7385,7 +7381,7 @@ pub const Constant = enum(u32) {...@@ -7385,7 +7381,7 @@ pub const Constant = enum(u32) {
7385 constant: Constant,7381 constant: Constant,
7386 builder: *Builder,7382 builder: *Builder,
7387 };7383 };
7388 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {7384 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
7389 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|7385 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
7390 @compileError("invalid format string: '" ++ fmt_str ++ "'");7386 @compileError("invalid format string: '" ++ fmt_str ++ "'");
7391 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {7387 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
...@@ -7712,7 +7708,7 @@ pub const Value = enum(u32) {...@@ -7712,7 +7708,7 @@ pub const Value = enum(u32) {
7712 function: Function.Index,7708 function: Function.Index,
7713 builder: *Builder,7709 builder: *Builder,
7714 };7710 };
7715 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {7711 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
7716 switch (data.value.unwrap()) {7712 switch (data.value.unwrap()) {
7717 .instruction => |instruction| try Function.Instruction.Index.format(.{7713 .instruction => |instruction| try Function.Instruction.Index.format(.{
7718 .instruction = instruction,7714 .instruction = instruction,
...@@ -7757,7 +7753,7 @@ pub const MetadataString = enum(u32) {...@@ -7757,7 +7753,7 @@ pub const MetadataString = enum(u32) {
7757 metadata_string: MetadataString,7753 metadata_string: MetadataString,
7758 builder: *const Builder,7754 builder: *const Builder,
7759 };7755 };
7760 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {7756 fn format(data: FormatData, bw: *Writer, comptime _: []const u8) Writer.Error!void {
7761 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, bw);7757 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, bw);
7762 }7758 }
7763 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {7759 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {
...@@ -7922,7 +7918,7 @@ pub const Metadata = enum(u32) {...@@ -7922,7 +7918,7 @@ pub const Metadata = enum(u32) {
7922 AllCallsDescribed: bool = false,7918 AllCallsDescribed: bool = false,
7923 Unused: u2 = 0,7919 Unused: u2 = 0,
79247920
7925 pub fn format(self: DIFlags, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {7921 pub fn format(self: DIFlags, bw: *Writer, comptime _: []const u8) Writer.Error!void {
7926 var need_pipe = false;7922 var need_pipe = false;
7927 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {7923 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {
7928 switch (@typeInfo(field.type)) {7924 switch (@typeInfo(field.type)) {
...@@ -7979,7 +7975,7 @@ pub const Metadata = enum(u32) {...@@ -7979,7 +7975,7 @@ pub const Metadata = enum(u32) {
7979 ObjCDirect: bool = false,7975 ObjCDirect: bool = false,
7980 Unused: u20 = 0,7976 Unused: u20 = 0,
79817977
7982 pub fn format(self: DISPFlags, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {7978 pub fn format(self: DISPFlags, bw: *Writer, comptime _: []const u8) Writer.Error!void {
7983 var need_pipe = false;7979 var need_pipe = false;
7984 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {7980 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {
7985 switch (@typeInfo(field.type)) {7981 switch (@typeInfo(field.type)) {
...@@ -8196,7 +8192,7 @@ pub const Metadata = enum(u32) {...@@ -8196,7 +8192,7 @@ pub const Metadata = enum(u32) {
8196 };8192 };
8197 };8193 };
8198 };8194 };
8199 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) std.io.Writer.Error!void {8195 fn format(data: FormatData, bw: *Writer, comptime fmt_str: []const u8) Writer.Error!void {
8200 if (data.node == .none) return;8196 if (data.node == .none) return;
82018197
8202 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';8198 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';
...@@ -8370,7 +8366,7 @@ pub const Metadata = enum(u32) {...@@ -8370,7 +8366,7 @@ pub const Metadata = enum(u32) {
8370 DIGlobalVariableExpression,8366 DIGlobalVariableExpression,
8371 },8367 },
8372 nodes: anytype,8368 nodes: anytype,
8373 bw: *std.io.BufferedWriter,8369 bw: *Writer,
8374 ) !void {8370 ) !void {
8375 comptime var fmt_str: []const u8 = "";8371 comptime var fmt_str: []const u8 = "";
8376 const names = comptime std.meta.fieldNames(@TypeOf(nodes));8372 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
...@@ -8623,12 +8619,12 @@ pub fn deinit(self: *Builder) void {...@@ -8623,12 +8619,12 @@ pub fn deinit(self: *Builder) void {
8623 self.* = undefined;8619 self.* = undefined;
8624}8620}
86258621
8626pub fn setModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) *std.io.BufferedWriter {8622pub fn setModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) *Writer {
8627 self.module_asm.clearRetainingCapacity();8623 self.module_asm.clearRetainingCapacity();
8628 return self.appendModuleAsm(aw);8624 return self.appendModuleAsm(aw);
8629}8625}
86308626
8631pub fn appendModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) *std.io.BufferedWriter {8627pub fn appendModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) *Writer {
8632 return aw.fromArrayList(self.gpa, &self.module_asm);8628 return aw.fromArrayList(self.gpa, &self.module_asm);
8633}8629}
86348630
...@@ -9379,14 +9375,14 @@ pub fn printToFile(self: *Builder, path: []const u8) bool {...@@ -9379,14 +9375,14 @@ pub fn printToFile(self: *Builder, path: []const u8) bool {
9379 return true;9375 return true;
9380}9376}
93819377
9382pub fn printBuffered(self: *Builder, writer: std.io.Writer) std.io.Writer.Error!void {9378pub fn printBuffered(self: *Builder, writer: Writer) Writer.Error!void {
9383 var buffer: [4096]u8 = undefined;9379 var buffer: [4096]u8 = undefined;
9384 var bw = writer.buffered(&buffer);9380 var bw = writer.buffered(&buffer);
9385 try self.print(&bw);9381 try self.print(&bw);
9386 try bw.flush();9382 try bw.flush();
9387}9383}
93889384
9389pub fn print(self: *Builder, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {9385pub fn print(self: *Builder, bw: *Writer) Writer.Error!void {
9390 var need_newline = false;9386 var need_newline = false;
9391 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };9387 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
9392 defer metadata_formatter.map.deinit(self.gpa);9388 defer metadata_formatter.map.deinit(self.gpa);
...@@ -10458,7 +10454,7 @@ fn isValidIdentifier(id: []const u8) bool {...@@ -10458,7 +10454,7 @@ fn isValidIdentifier(id: []const u8) bool {
10458}10454}
1045910455
10460const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };10456const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };
10461fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {10457fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, bw: *Writer) Writer.Error!void {
10462 const need_quotes = switch (quotes) {10458 const need_quotes = switch (quotes) {
10463 .always_quote => true,10459 .always_quote => true,
10464 .quote_unless_valid_identifier => !isValidIdentifier(slice),10460 .quote_unless_valid_identifier => !isValidIdentifier(slice),
...@@ -15097,6 +15093,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -15097,6 +15093,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
15097 return bitcode.toOwnedSlice();15093 return bitcode.toOwnedSlice();
15098}15094}
1509915095
15096const std = @import("../../std.zig");
15100const Allocator = std.mem.Allocator;15097const Allocator = std.mem.Allocator;
15101const assert = std.debug.assert;15098const assert = std.debug.assert;
15102const bitcode_writer = @import("bitcode_writer.zig");15099const bitcode_writer = @import("bitcode_writer.zig");
...@@ -15105,4 +15102,4 @@ const builtin = @import("builtin");...@@ -15105,4 +15102,4 @@ const builtin = @import("builtin");
15105const DW = std.dwarf;15102const DW = std.dwarf;
15106const ir = @import("ir.zig");15103const ir = @import("ir.zig");
15107const log = std.log.scoped(.llvm);15104const log = std.log.scoped(.llvm);
15108const std = @import("../../std.zig");15105const Writer = std.io.Writer;
lib/std/zig/string_literal.zig+4-3
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const utf8Encode = std.unicode.utf8Encode;3const utf8Encode = std.unicode.utf8Encode;
4const Writer = std.io.Writer;
45
5pub const ParseError = error{6pub const ParseError = error{
6 OutOfMemory,7 OutOfMemory,
...@@ -44,7 +45,7 @@ pub const Error = union(enum) {...@@ -44,7 +45,7 @@ pub const Error = union(enum) {
44 raw_string: []const u8,45 raw_string: []const u8,
45 };46 };
4647
47 fn formatMessage(self: FormatMessage, bw: *std.io.BufferedWriter, comptime f: []const u8) !void {48 fn formatMessage(self: FormatMessage, bw: *Writer, comptime f: []const u8) !void {
48 _ = f;49 _ = f;
49 switch (self.err) {50 switch (self.err) {
50 .invalid_escape_character => |bad_index| try bw.print(51 .invalid_escape_character => |bad_index| try bw.print(
...@@ -316,9 +317,9 @@ test parseCharLiteral {...@@ -316,9 +317,9 @@ test parseCharLiteral {
316 );317 );
317}318}
318319
319/// Parses `bytes` as a Zig string literal and writes the result to the `std.io.Writer` type.320/// Parses `bytes` as a Zig string literal and writes the result to the `Writer` type.
320/// Asserts `bytes` has '"' at beginning and end.321/// Asserts `bytes` has '"' at beginning and end.
321pub fn parseWrite(writer: *std.io.BufferedWriter, bytes: []const u8) std.io.Writer.Error!Result {322pub fn parseWrite(writer: *Writer, bytes: []const u8) Writer.Error!Result {
322 assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"');323 assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"');
323324
324 var index: usize = 1;325 var index: usize = 1;
lib/std/zip.zig+3-2
...@@ -7,6 +7,7 @@ const builtin = @import("builtin");...@@ -7,6 +7,7 @@ const builtin = @import("builtin");
7const std = @import("std");7const std = @import("std");
8const File = std.fs.File;8const File = std.fs.File;
9const is_le = builtin.target.cpu.arch.endian() == .little;9const is_le = builtin.target.cpu.arch.endian() == .little;
10const Writer = std.io.Writer;
1011
11pub const CompressionMethod = enum(u16) {12pub const CompressionMethod = enum(u16) {
12 store = 0,13 store = 0,
...@@ -200,7 +201,7 @@ pub const Decompress = union {...@@ -200,7 +201,7 @@ pub const Decompress = union {
200201
201 fn readStore(202 fn readStore(
202 context: ?*anyopaque,203 context: ?*anyopaque,
203 writer: *std.io.BufferedWriter,204 writer: *Writer,
204 limit: std.io.Limit,205 limit: std.io.Limit,
205 ) std.io.Reader.StreamError!usize {206 ) std.io.Reader.StreamError!usize {
206 const d: *Decompress = @ptrCast(@alignCast(context));207 const d: *Decompress = @ptrCast(@alignCast(context));
...@@ -209,7 +210,7 @@ pub const Decompress = union {...@@ -209,7 +210,7 @@ pub const Decompress = union {
209210
210 fn readDeflate(211 fn readDeflate(
211 context: ?*anyopaque,212 context: ?*anyopaque,
212 writer: *std.io.BufferedWriter,213 writer: *Writer,
213 limit: std.io.Limit,214 limit: std.io.Limit,
214 ) std.io.Reader.StreamError!usize {215 ) std.io.Reader.StreamError!usize {
215 const d: *Decompress = @ptrCast(@alignCast(context));216 const d: *Decompress = @ptrCast(@alignCast(context));
lib/std/zip/test.zig+5-5
...@@ -3,6 +3,7 @@ const testing = std.testing;...@@ -3,6 +3,7 @@ const testing = std.testing;
3const zip = @import("../zip.zig");3const zip = @import("../zip.zig");
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const Writer = std.io.Writer;
67
7const File = struct {8const File = struct {
8 name: []const u8,9 name: []const u8,
...@@ -103,7 +104,7 @@ const Zip64Options = struct {...@@ -103,7 +104,7 @@ const Zip64Options = struct {
103};104};
104105
105fn writeZip(106fn writeZip(
106 writer: *std.io.BufferedWriter,107 writer: *Writer,
107 files: []const File,108 files: []const File,
108 store: []FileStore,109 store: []FileStore,
109 options: WriteZipOptions,110 options: WriteZipOptions,
...@@ -129,13 +130,13 @@ fn writeZip(...@@ -129,13 +130,13 @@ fn writeZip(
129/// Provides methods to format and write the contents of a zip archive130/// Provides methods to format and write the contents of a zip archive
130/// to the underlying Writer.131/// to the underlying Writer.
131const Zipper = struct {132const Zipper = struct {
132 writer: *std.io.BufferedWriter,133 writer: *Writer,
133 init_count: u64,134 init_count: u64,
134 central_count: u64 = 0,135 central_count: u64 = 0,
135 first_central_offset: ?u64 = null,136 first_central_offset: ?u64 = null,
136 last_central_limit: ?u64 = null,137 last_central_limit: ?u64 = null,
137138
138 fn init(writer: *std.io.BufferedWriter) Zipper {139 fn init(writer: *Writer) Zipper {
139 return .{ .writer = writer, .init_count = writer.count };140 return .{ .writer = writer, .init_count = writer.count };
140 }141 }
141142
...@@ -198,8 +199,7 @@ const Zipper = struct {...@@ -198,8 +199,7 @@ const Zipper = struct {
198 },199 },
199 .deflate => {200 .deflate => {
200 const offset = writer.count;201 const offset = writer.count;
201 var br: std.io.Reader = undefined;202 var br: std.io.Reader = .fixed(opt.content);
202 br.initFixed(@constCast(opt.content));
203 var compress: std.compress.flate.Compress = .init(&br, .{});203 var compress: std.compress.flate.Compress = .init(&br, .{});
204 var compress_br = compress.readable(&.{});204 var compress_br = compress.readable(&.{});
205 const n = try compress_br.readRemaining(writer);205 const n = try compress_br.readRemaining(writer);
lib/std/zon/stringify.zig+7-7
...@@ -22,7 +22,7 @@...@@ -22,7 +22,7 @@
2222
23const std = @import("std");23const std = @import("std");
24const assert = std.debug.assert;24const assert = std.debug.assert;
25const BufferedWriter = std.io.BufferedWriter;25const Writer = std.io.Writer;
2626
27/// Options for `serialize`.27/// Options for `serialize`.
28pub const SerializeOptions = struct {28pub const SerializeOptions = struct {
...@@ -41,7 +41,7 @@ pub const SerializeOptions = struct {...@@ -41,7 +41,7 @@ pub const SerializeOptions = struct {
41/// Serialize the given value as ZON.41/// Serialize the given value as ZON.
42///42///
43/// It is asserted at comptime that `@TypeOf(val)` is not a recursive type.43/// It is asserted at comptime that `@TypeOf(val)` is not a recursive type.
44pub fn serialize(val: anytype, options: SerializeOptions, writer: *BufferedWriter) std.io.Writer.Error!void {44pub fn serialize(val: anytype, options: SerializeOptions, writer: *Writer) Writer.Error!void {
45 var s: Serializer = .{45 var s: Serializer = .{
46 .writer = writer,46 .writer = writer,
47 .options = .{ .whitespace = options.whitespace },47 .options = .{ .whitespace = options.whitespace },
...@@ -60,7 +60,7 @@ pub fn serialize(val: anytype, options: SerializeOptions, writer: *BufferedWrite...@@ -60,7 +60,7 @@ pub fn serialize(val: anytype, options: SerializeOptions, writer: *BufferedWrite
60pub fn serializeMaxDepth(60pub fn serializeMaxDepth(
61 val: anytype,61 val: anytype,
62 options: SerializeOptions,62 options: SerializeOptions,
63 writer: *BufferedWriter,63 writer: *Writer,
64 depth: usize,64 depth: usize,
65) Serializer.DepthError!void {65) Serializer.DepthError!void {
66 var s: Serializer = .{66 var s: Serializer = .{
...@@ -80,7 +80,7 @@ pub fn serializeMaxDepth(...@@ -80,7 +80,7 @@ pub fn serializeMaxDepth(
80pub fn serializeArbitraryDepth(80pub fn serializeArbitraryDepth(
81 val: anytype,81 val: anytype,
82 options: SerializeOptions,82 options: SerializeOptions,
83 writer: *BufferedWriter,83 writer: *Writer,
84) Serializer.Error!void {84) Serializer.Error!void {
85 var s: Serializer = .{85 var s: Serializer = .{
86 .writer = writer,86 .writer = writer,
...@@ -437,9 +437,9 @@ pub const SerializeContainerOptions = struct {...@@ -437,9 +437,9 @@ pub const SerializeContainerOptions = struct {
437pub const Serializer = struct {437pub const Serializer = struct {
438 options: Options = .{},438 options: Options = .{},
439 indent_level: u8 = 0,439 indent_level: u8 = 0,
440 writer: *BufferedWriter,440 writer: *Writer,
441441
442 pub const Error = std.io.Writer.Error;442 pub const Error = Writer.Error;
443 pub const DepthError = Error || error{ExceededMaxDepth};443 pub const DepthError = Error || error{ExceededMaxDepth};
444444
445 pub const Options = struct {445 pub const Options = struct {
...@@ -1040,7 +1040,7 @@ pub const Serializer = struct {...@@ -1040,7 +1040,7 @@ pub const Serializer = struct {
1040};1040};
10411041
1042test Serializer {1042test Serializer {
1043 var bw: std.io.BufferedWriter = .{1043 var bw: Writer = .{
1044 .unbuffered_writer = .discarding,1044 .unbuffered_writer = .discarding,
1045 .buffer = &.{},1045 .buffer = &.{},
1046 };1046 };
lib/ubsan_rt.zig+1-1
...@@ -119,7 +119,7 @@ const Value = extern struct {...@@ -119,7 +119,7 @@ const Value = extern struct {
119 }119 }
120 }120 }
121121
122 pub fn format(value: Value, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {122 pub fn format(value: Value, bw: *std.io.Writer, comptime fmt: []const u8) !void {
123 comptime assert(fmt.len == 0);123 comptime assert(fmt.len == 0);
124124
125 // Work around x86_64 backend limitation.125 // Work around x86_64 backend limitation.
src/Air.zig+3-1
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7const std = @import("std");7const std = @import("std");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const Writer = std.io.Writer;
1011
11const Air = @This();12const Air = @This();
12const InternPool = @import("InternPool.zig");13const InternPool = @import("InternPool.zig");
...@@ -957,7 +958,8 @@ pub const Inst = struct {...@@ -957,7 +958,8 @@ pub const Inst = struct {
957 return index.unwrap().target;958 return index.unwrap().target;
958 }959 }
959960
960 pub fn format(index: Index, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {961 pub fn format(index: Index, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
962 comptime assert(fmt.len == 0);
961 try bw.writeByte('%');963 try bw.writeByte('%');
962 switch (index.unwrap()) {964 switch (index.unwrap()) {
963 .ref => {},965 .ref => {},
src/Air/Liveness.zig+4-2
...@@ -10,6 +10,7 @@ const log = std.log.scoped(.liveness);...@@ -10,6 +10,7 @@ const log = std.log.scoped(.liveness);
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
12const Log2Int = std.math.Log2Int;12const Log2Int = std.math.Log2Int;
13const Writer = std.io.Writer;
1314
14const Liveness = @This();15const Liveness = @This();
15const trace = @import("../tracy.zig").trace;16const trace = @import("../tracy.zig").trace;
...@@ -2036,7 +2037,7 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns...@@ -2036,7 +2037,7 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns
2036const FmtInstSet = struct {2037const FmtInstSet = struct {
2037 set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void),2038 set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void),
20382039
2039 pub fn format(val: FmtInstSet, bw: *std.io.BufferedWriter, comptime _: []const u8) !void {2040 pub fn format(val: FmtInstSet, bw: *Writer, comptime _: []const u8) !void {
2040 if (val.set.count() == 0) {2041 if (val.set.count() == 0) {
2041 try bw.writeAll("[no instructions]");2042 try bw.writeAll("[no instructions]");
2042 return;2043 return;
...@@ -2056,7 +2057,8 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList {...@@ -2056,7 +2057,8 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList {
2056const FmtInstList = struct {2057const FmtInstList = struct {
2057 list: []const Air.Inst.Index,2058 list: []const Air.Inst.Index,
20582059
2059 pub fn format(val: FmtInstList, bw: *std.io.BufferedWriter, comptime _: []const u8) !void {2060 pub fn format(val: FmtInstList, bw: *Writer, comptime fmt: []const u8) !void {
2061 comptime assert(fmt.len == 0);
2060 if (val.list.len == 0) {2062 if (val.list.len == 0) {
2061 try bw.writeAll("[no instructions]");2063 try bw.writeAll("[no instructions]");
2062 return;2064 return;
src/Air/print.zig+45-45
...@@ -8,7 +8,7 @@ const Type = @import("../Type.zig");...@@ -8,7 +8,7 @@ const Type = @import("../Type.zig");
8const Air = @import("../Air.zig");8const Air = @import("../Air.zig");
9const InternPool = @import("../InternPool.zig");9const InternPool = @import("../InternPool.zig");
1010
11pub fn write(air: Air, stream: *std.io.BufferedWriter, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {11pub fn write(air: Air, stream: *std.io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
12 comptime std.debug.assert(build_options.enable_debug_extensions);12 comptime std.debug.assert(build_options.enable_debug_extensions);
13 const instruction_bytes = air.instructions.len *13 const instruction_bytes = air.instructions.len *
14 // Here we don't use @sizeOf(Air.Inst.Data) because it would include14 // Here we don't use @sizeOf(Air.Inst.Data) because it would include
...@@ -54,7 +54,7 @@ pub fn write(air: Air, stream: *std.io.BufferedWriter, pt: Zcu.PerThread, livene...@@ -54,7 +54,7 @@ pub fn write(air: Air, stream: *std.io.BufferedWriter, pt: Zcu.PerThread, livene
5454
55pub fn writeInst(55pub fn writeInst(
56 air: Air,56 air: Air,
57 stream: *std.io.BufferedWriter,57 stream: *std.io.Writer,
58 inst: Air.Inst.Index,58 inst: Air.Inst.Index,
59 pt: Zcu.PerThread,59 pt: Zcu.PerThread,
60 liveness: ?Air.Liveness,60 liveness: ?Air.Liveness,
...@@ -93,14 +93,14 @@ const Writer = struct {...@@ -93,14 +93,14 @@ const Writer = struct {
9393
94 const Error = std.io.Writer.Error;94 const Error = std.io.Writer.Error;
9595
96 fn writeBody(w: *Writer, s: *std.io.BufferedWriter, body: []const Air.Inst.Index) Error!void {96 fn writeBody(w: *Writer, s: *std.io.Writer, body: []const Air.Inst.Index) Error!void {
97 for (body) |inst| {97 for (body) |inst| {
98 try w.writeInst(s, inst);98 try w.writeInst(s, inst);
99 try s.writeByte('\n');99 try s.writeByte('\n');
100 }100 }
101 }101 }
102102
103 fn writeInst(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {103 fn writeInst(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
104 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];104 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];
105 try s.splatByteAll(' ', w.indent);105 try s.splatByteAll(' ', w.indent);
106 try s.print("{f}{c}= {s}(", .{106 try s.print("{f}{c}= {s}(", .{
...@@ -340,48 +340,48 @@ const Writer = struct {...@@ -340,48 +340,48 @@ const Writer = struct {
340 try s.writeByte(')');340 try s.writeByte(')');
341 }341 }
342342
343 fn writeBinOp(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {343 fn writeBinOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
344 const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;344 const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
345 try w.writeOperand(s, inst, 0, bin_op.lhs);345 try w.writeOperand(s, inst, 0, bin_op.lhs);
346 try s.writeAll(", ");346 try s.writeAll(", ");
347 try w.writeOperand(s, inst, 1, bin_op.rhs);347 try w.writeOperand(s, inst, 1, bin_op.rhs);
348 }348 }
349349
350 fn writeUnOp(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {350 fn writeUnOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
351 const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op;351 const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
352 try w.writeOperand(s, inst, 0, un_op);352 try w.writeOperand(s, inst, 0, un_op);
353 }353 }
354354
355 fn writeNoOp(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {355 fn writeNoOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
356 _ = w;356 _ = w;
357 _ = s;357 _ = s;
358 _ = inst;358 _ = inst;
359 // no-op, no argument to write359 // no-op, no argument to write
360 }360 }
361361
362 fn writeType(w: *Writer, s: *std.io.BufferedWriter, ty: Type) !void {362 fn writeType(w: *Writer, s: *std.io.Writer, ty: Type) !void {
363 return ty.print(s, w.pt);363 return ty.print(s, w.pt);
364 }364 }
365365
366 fn writeTy(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {366 fn writeTy(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
367 const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty;367 const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty;
368 try w.writeType(s, ty);368 try w.writeType(s, ty);
369 }369 }
370370
371 fn writeArg(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {371 fn writeArg(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
372 const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;372 const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;
373 try w.writeType(s, arg.ty.toType());373 try w.writeType(s, arg.ty.toType());
374 try s.print(", {d}", .{arg.zir_param_index});374 try s.print(", {d}", .{arg.zir_param_index});
375 }375 }
376376
377 fn writeTyOp(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {377 fn writeTyOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
378 const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;378 const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
379 try w.writeType(s, ty_op.ty.toType());379 try w.writeType(s, ty_op.ty.toType());
380 try s.writeAll(", ");380 try s.writeAll(", ");
381 try w.writeOperand(s, inst, 0, ty_op.operand);381 try w.writeOperand(s, inst, 0, ty_op.operand);
382 }382 }
383383
384 fn writeBlock(w: *Writer, s: *std.io.BufferedWriter, tag: Air.Inst.Tag, inst: Air.Inst.Index) Error!void {384 fn writeBlock(w: *Writer, s: *std.io.Writer, tag: Air.Inst.Tag, inst: Air.Inst.Index) Error!void {
385 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;385 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
386 try w.writeType(s, ty_pl.ty.toType());386 try w.writeType(s, ty_pl.ty.toType());
387 const body: []const Air.Inst.Index = @ptrCast(switch (tag) {387 const body: []const Air.Inst.Index = @ptrCast(switch (tag) {
...@@ -422,7 +422,7 @@ const Writer = struct {...@@ -422,7 +422,7 @@ const Writer = struct {
422 }422 }
423 }423 }
424424
425 fn writeLoop(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {425 fn writeLoop(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
426 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;426 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
427 const extra = w.air.extraData(Air.Block, ty_pl.payload);427 const extra = w.air.extraData(Air.Block, ty_pl.payload);
428 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);428 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);
...@@ -438,7 +438,7 @@ const Writer = struct {...@@ -438,7 +438,7 @@ const Writer = struct {
438 try s.writeAll("}");438 try s.writeAll("}");
439 }439 }
440440
441 fn writeAggregateInit(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {441 fn writeAggregateInit(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
442 const zcu = w.pt.zcu;442 const zcu = w.pt.zcu;
443 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;443 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
444 const vector_ty = ty_pl.ty.toType();444 const vector_ty = ty_pl.ty.toType();
...@@ -454,7 +454,7 @@ const Writer = struct {...@@ -454,7 +454,7 @@ const Writer = struct {
454 try s.writeAll("]");454 try s.writeAll("]");
455 }455 }
456456
457 fn writeUnionInit(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {457 fn writeUnionInit(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
458 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;458 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
459 const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data;459 const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data;
460460
...@@ -462,7 +462,7 @@ const Writer = struct {...@@ -462,7 +462,7 @@ const Writer = struct {
462 try w.writeOperand(s, inst, 0, extra.init);462 try w.writeOperand(s, inst, 0, extra.init);
463 }463 }
464464
465 fn writeStructField(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {465 fn writeStructField(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
466 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;466 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
467 const extra = w.air.extraData(Air.StructField, ty_pl.payload).data;467 const extra = w.air.extraData(Air.StructField, ty_pl.payload).data;
468468
...@@ -470,7 +470,7 @@ const Writer = struct {...@@ -470,7 +470,7 @@ const Writer = struct {
470 try s.print(", {d}", .{extra.field_index});470 try s.print(", {d}", .{extra.field_index});
471 }471 }
472472
473 fn writeTyPlBin(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {473 fn writeTyPlBin(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
474 const data = w.air.instructions.items(.data);474 const data = w.air.instructions.items(.data);
475 const ty_pl = data[@intFromEnum(inst)].ty_pl;475 const ty_pl = data[@intFromEnum(inst)].ty_pl;
476 const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;476 const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -483,7 +483,7 @@ const Writer = struct {...@@ -483,7 +483,7 @@ const Writer = struct {
483 try w.writeOperand(s, inst, 1, extra.rhs);483 try w.writeOperand(s, inst, 1, extra.rhs);
484 }484 }
485485
486 fn writeCmpxchg(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {486 fn writeCmpxchg(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
487 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;487 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
488 const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data;488 const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
489489
...@@ -497,7 +497,7 @@ const Writer = struct {...@@ -497,7 +497,7 @@ const Writer = struct {
497 });497 });
498 }498 }
499499
500 fn writeMulAdd(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {500 fn writeMulAdd(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
501 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;501 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
502 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;502 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
503503
...@@ -508,7 +508,7 @@ const Writer = struct {...@@ -508,7 +508,7 @@ const Writer = struct {
508 try w.writeOperand(s, inst, 2, pl_op.operand);508 try w.writeOperand(s, inst, 2, pl_op.operand);
509 }509 }
510510
511 fn writeShuffleOne(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {511 fn writeShuffleOne(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
512 const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst);512 const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst);
513 try w.writeType(s, unwrapped.result_ty);513 try w.writeType(s, unwrapped.result_ty);
514 try s.writeAll(", ");514 try s.writeAll(", ");
...@@ -543,7 +543,7 @@ const Writer = struct {...@@ -543,7 +543,7 @@ const Writer = struct {
543 try s.writeByte(']');543 try s.writeByte(']');
544 }544 }
545545
546 fn writeSelect(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {546 fn writeSelect(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
547 const zcu = w.pt.zcu;547 const zcu = w.pt.zcu;
548 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;548 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
549 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;549 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
...@@ -558,14 +558,14 @@ const Writer = struct {...@@ -558,14 +558,14 @@ const Writer = struct {
558 try w.writeOperand(s, inst, 2, extra.rhs);558 try w.writeOperand(s, inst, 2, extra.rhs);
559 }559 }
560560
561 fn writeReduce(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {561 fn writeReduce(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
562 const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce;562 const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
563563
564 try w.writeOperand(s, inst, 0, reduce.operand);564 try w.writeOperand(s, inst, 0, reduce.operand);
565 try s.print(", {s}", .{@tagName(reduce.operation)});565 try s.print(", {s}", .{@tagName(reduce.operation)});
566 }566 }
567567
568 fn writeCmpVector(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {568 fn writeCmpVector(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
569 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;569 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
570 const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;570 const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;
571571
...@@ -575,7 +575,7 @@ const Writer = struct {...@@ -575,7 +575,7 @@ const Writer = struct {
575 try w.writeOperand(s, inst, 1, extra.rhs);575 try w.writeOperand(s, inst, 1, extra.rhs);
576 }576 }
577577
578 fn writeVectorStoreElem(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {578 fn writeVectorStoreElem(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
579 const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem;579 const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem;
580 const extra = w.air.extraData(Air.VectorCmp, data.payload).data;580 const extra = w.air.extraData(Air.VectorCmp, data.payload).data;
581581
...@@ -586,21 +586,21 @@ const Writer = struct {...@@ -586,21 +586,21 @@ const Writer = struct {
586 try w.writeOperand(s, inst, 2, extra.rhs);586 try w.writeOperand(s, inst, 2, extra.rhs);
587 }587 }
588588
589 fn writeRuntimeNavPtr(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {589 fn writeRuntimeNavPtr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
590 const ip = &w.pt.zcu.intern_pool;590 const ip = &w.pt.zcu.intern_pool;
591 const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;591 const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;
592 try w.writeType(s, .fromInterned(ty_nav.ty));592 try w.writeType(s, .fromInterned(ty_nav.ty));
593 try s.print(", '{}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)});593 try s.print(", '{}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)});
594 }594 }
595595
596 fn writeAtomicLoad(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {596 fn writeAtomicLoad(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
597 const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;597 const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;
598598
599 try w.writeOperand(s, inst, 0, atomic_load.ptr);599 try w.writeOperand(s, inst, 0, atomic_load.ptr);
600 try s.print(", {s}", .{@tagName(atomic_load.order)});600 try s.print(", {s}", .{@tagName(atomic_load.order)});
601 }601 }
602602
603 fn writePrefetch(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {603 fn writePrefetch(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
604 const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;604 const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
605605
606 try w.writeOperand(s, inst, 0, prefetch.ptr);606 try w.writeOperand(s, inst, 0, prefetch.ptr);
...@@ -611,7 +611,7 @@ const Writer = struct {...@@ -611,7 +611,7 @@ const Writer = struct {
611611
612 fn writeAtomicStore(612 fn writeAtomicStore(
613 w: *Writer,613 w: *Writer,
614 s: *std.io.BufferedWriter,614 s: *std.io.Writer,
615 inst: Air.Inst.Index,615 inst: Air.Inst.Index,
616 order: std.builtin.AtomicOrder,616 order: std.builtin.AtomicOrder,
617 ) Error!void {617 ) Error!void {
...@@ -622,7 +622,7 @@ const Writer = struct {...@@ -622,7 +622,7 @@ const Writer = struct {
622 try s.print(", {s}", .{@tagName(order)});622 try s.print(", {s}", .{@tagName(order)});
623 }623 }
624624
625 fn writeAtomicRmw(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {625 fn writeAtomicRmw(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
626 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;626 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
627 const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data;627 const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data;
628628
...@@ -632,7 +632,7 @@ const Writer = struct {...@@ -632,7 +632,7 @@ const Writer = struct {
632 try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) });632 try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) });
633 }633 }
634634
635 fn writeFieldParentPtr(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {635 fn writeFieldParentPtr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
636 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;636 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
637 const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;637 const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
638638
...@@ -640,7 +640,7 @@ const Writer = struct {...@@ -640,7 +640,7 @@ const Writer = struct {
640 try s.print(", {d}", .{extra.field_index});640 try s.print(", {d}", .{extra.field_index});
641 }641 }
642642
643 fn writeAssembly(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {643 fn writeAssembly(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
644 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;644 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
645 const extra = w.air.extraData(Air.Asm, ty_pl.payload);645 const extra = w.air.extraData(Air.Asm, ty_pl.payload);
646 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;646 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
...@@ -713,19 +713,19 @@ const Writer = struct {...@@ -713,19 +713,19 @@ const Writer = struct {
713 try s.print(", \"{f}\"", .{std.zig.fmtEscapes(asm_source)});713 try s.print(", \"{f}\"", .{std.zig.fmtEscapes(asm_source)});
714 }714 }
715715
716 fn writeDbgStmt(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {716 fn writeDbgStmt(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
717 const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;717 const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
718 try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });718 try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
719 }719 }
720720
721 fn writeDbgVar(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {721 fn writeDbgVar(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
722 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;722 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
723 try w.writeOperand(s, inst, 0, pl_op.operand);723 try w.writeOperand(s, inst, 0, pl_op.operand);
724 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);724 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
725 try s.print(", \"{f}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});725 try s.print(", \"{f}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});
726 }726 }
727727
728 fn writeCall(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {728 fn writeCall(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
729 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;729 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
730 const extra = w.air.extraData(Air.Call, pl_op.payload);730 const extra = w.air.extraData(Air.Call, pl_op.payload);
731 const args = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra.end..][0..extra.data.args_len]));731 const args = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra.end..][0..extra.data.args_len]));
...@@ -738,19 +738,19 @@ const Writer = struct {...@@ -738,19 +738,19 @@ const Writer = struct {
738 try s.writeAll("]");738 try s.writeAll("]");
739 }739 }
740740
741 fn writeBr(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {741 fn writeBr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
742 const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br;742 const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br;
743 try w.writeInstIndex(s, br.block_inst, false);743 try w.writeInstIndex(s, br.block_inst, false);
744 try s.writeAll(", ");744 try s.writeAll(", ");
745 try w.writeOperand(s, inst, 0, br.operand);745 try w.writeOperand(s, inst, 0, br.operand);
746 }746 }
747747
748 fn writeRepeat(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {748 fn writeRepeat(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
749 const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat;749 const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
750 try w.writeInstIndex(s, repeat.loop_inst, false);750 try w.writeInstIndex(s, repeat.loop_inst, false);
751 }751 }
752752
753 fn writeTry(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {753 fn writeTry(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
754 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;754 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
755 const extra = w.air.extraData(Air.Try, pl_op.payload);755 const extra = w.air.extraData(Air.Try, pl_op.payload);
756 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);756 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);
...@@ -784,7 +784,7 @@ const Writer = struct {...@@ -784,7 +784,7 @@ const Writer = struct {
784 }784 }
785 }785 }
786786
787 fn writeTryPtr(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {787 fn writeTryPtr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
788 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;788 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
789 const extra = w.air.extraData(Air.TryPtr, ty_pl.payload);789 const extra = w.air.extraData(Air.TryPtr, ty_pl.payload);
790 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);790 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);
...@@ -821,7 +821,7 @@ const Writer = struct {...@@ -821,7 +821,7 @@ const Writer = struct {
821 }821 }
822 }822 }
823823
824 fn writeCondBr(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {824 fn writeCondBr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
825 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;825 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
826 const extra = w.air.extraData(Air.CondBr, pl_op.payload);826 const extra = w.air.extraData(Air.CondBr, pl_op.payload);
827 const then_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.then_body_len]);827 const then_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.then_body_len]);
...@@ -880,7 +880,7 @@ const Writer = struct {...@@ -880,7 +880,7 @@ const Writer = struct {
880 try s.writeAll("}");880 try s.writeAll("}");
881 }881 }
882882
883 fn writeSwitchBr(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {883 fn writeSwitchBr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
884 const switch_br = w.air.unwrapSwitch(inst);884 const switch_br = w.air.unwrapSwitch(inst);
885885
886 const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness|886 const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness|
...@@ -966,25 +966,25 @@ const Writer = struct {...@@ -966,25 +966,25 @@ const Writer = struct {
966 try s.splatByteAll(' ', old_indent);966 try s.splatByteAll(' ', old_indent);
967 }967 }
968968
969 fn writeWasmMemorySize(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {969 fn writeWasmMemorySize(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
970 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;970 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
971 try s.print("{d}", .{pl_op.payload});971 try s.print("{d}", .{pl_op.payload});
972 }972 }
973973
974 fn writeWasmMemoryGrow(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {974 fn writeWasmMemoryGrow(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
975 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;975 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
976 try s.print("{d}, ", .{pl_op.payload});976 try s.print("{d}, ", .{pl_op.payload});
977 try w.writeOperand(s, inst, 0, pl_op.operand);977 try w.writeOperand(s, inst, 0, pl_op.operand);
978 }978 }
979979
980 fn writeWorkDimension(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) Error!void {980 fn writeWorkDimension(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
981 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;981 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
982 try s.print("{d}", .{pl_op.payload});982 try s.print("{d}", .{pl_op.payload});
983 }983 }
984984
985 fn writeOperand(985 fn writeOperand(
986 w: *Writer,986 w: *Writer,
987 s: *std.io.BufferedWriter,987 s: *std.io.Writer,
988 inst: Air.Inst.Index,988 inst: Air.Inst.Index,
989 op_index: usize,989 op_index: usize,
990 operand: Air.Inst.Ref,990 operand: Air.Inst.Ref,
...@@ -1030,7 +1030,7 @@ const Writer = struct {...@@ -1030,7 +1030,7 @@ const Writer = struct {
10301030
1031 fn writeInstIndex(1031 fn writeInstIndex(
1032 w: *Writer,1032 w: *Writer,
1033 s: *std.io.BufferedWriter,1033 s: *std.io.Writer,
1034 inst: Air.Inst.Index,1034 inst: Air.Inst.Index,
1035 dies: bool,1035 dies: bool,
1036 ) Error!void {1036 ) Error!void {
src/Compilation.zig+7-9
...@@ -12,6 +12,7 @@ const ThreadPool = std.Thread.Pool;...@@ -12,6 +12,7 @@ const ThreadPool = std.Thread.Pool;
12const WaitGroup = std.Thread.WaitGroup;12const WaitGroup = std.Thread.WaitGroup;
13const ErrorBundle = std.zig.ErrorBundle;13const ErrorBundle = std.zig.ErrorBundle;
14const fatal = std.process.fatal;14const fatal = std.process.fatal;
15const Writer = std.io.Writer;
1516
16const Value = @import("Value.zig");17const Value = @import("Value.zig");
17const Type = @import("Type.zig");18const Type = @import("Type.zig");
...@@ -1000,15 +1001,12 @@ pub const CObject = struct {...@@ -1000,15 +1001,12 @@ pub const CObject = struct {
10001001
1001 const file = std.fs.cwd().openFile(file_name, .{}) catch break :source_line 0;1002 const file = std.fs.cwd().openFile(file_name, .{}) catch break :source_line 0;
1002 defer file.close();1003 defer file.close();
1003 file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
1004
1005 var buffer: [1 << 10]u8 = undefined;1004 var buffer: [1 << 10]u8 = undefined;
1006 var fr = file.reader();1005 var fr = file.reader(&buffer);
1007 var br = fr.interface().buffered(&buffer);1006 fr.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
1008 var bw: std.io.BufferedWriter = undefined;1007 var bw: Writer = .fixed(&buffer);
1009 bw.initFixed(&buffer);
1010 break :source_line try eb.addString(1008 break :source_line try eb.addString(
1011 buffer[0 .. br.readDelimiterEnding(&bw, '\n') catch break :source_line 0],1009 buffer[0 .. fr.interface.readDelimiterEnding(&bw, '\n') catch break :source_line 0],
1012 );1010 );
1013 };1011 };
10141012
...@@ -6026,8 +6024,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6026,8 +6024,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
60266024
6027 // In .rc files, a " within a quoted string is escaped as ""6025 // In .rc files, a " within a quoted string is escaped as ""
6028 const fmtRcEscape = struct {6026 const fmtRcEscape = struct {
6029 fn formatRcEscape(bytes: []const u8, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {6027 fn formatRcEscape(bytes: []const u8, bw: *Writer, comptime fmt: []const u8) !void {
6030 _ = fmt;6028 comptime assert(fmt.len == 0);
6031 for (bytes) |byte| switch (byte) {6029 for (bytes) |byte| switch (byte) {
6032 '"' => try bw.writeAll("\"\""),6030 '"' => try bw.writeAll("\"\""),
6033 '\\' => try bw.writeAll("\\\\"),6031 '\\' => try bw.writeAll("\\\\"),
src/InternPool.zig+1-1
...@@ -1888,7 +1888,7 @@ pub const NullTerminatedString = enum(u32) {...@@ -1888,7 +1888,7 @@ pub const NullTerminatedString = enum(u32) {
1888 string: NullTerminatedString,1888 string: NullTerminatedString,
1889 ip: *const InternPool,1889 ip: *const InternPool,
1890 };1890 };
1891 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime specifier: []const u8) std.io.Writer.Error!void {1891 fn format(data: FormatData, bw: *std.io.Writer, comptime specifier: []const u8) std.io.Writer.Error!void {
1892 const slice = data.string.toSlice(data.ip);1892 const slice = data.string.toSlice(data.ip);
1893 if (comptime std.mem.eql(u8, specifier, "")) {1893 if (comptime std.mem.eql(u8, specifier, "")) {
1894 try bw.writeAll(slice);1894 try bw.writeAll(slice);
src/Package/Fetch.zig+7-7
...@@ -1366,9 +1366,9 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U...@@ -1366,9 +1366,9 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
1366 const index_prog_node = f.prog_node.start("Index pack", 0);1366 const index_prog_node = f.prog_node.start("Index pack", 0);
1367 defer index_prog_node.end();1367 defer index_prog_node.end();
1368 var buffer: [4096]u8 = undefined;1368 var buffer: [4096]u8 = undefined;
1369 var index_buffered_writer: std.io.BufferedWriter = index_file.writer().buffered(&buffer);1369 var index_file_writer = index_file.writer(&buffer);
1370 try git.indexPack(gpa, object_format, pack_file, &index_buffered_writer);1370 try git.indexPack(gpa, object_format, pack_file, &index_file_writer.interface);
1371 try index_buffered_writer.flush();1371 try index_file_writer.flush();
1372 try index_file.sync();1372 try index_file.sync();
1373 }1373 }
13741374
...@@ -1639,14 +1639,14 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute...@@ -1639,14 +1639,14 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
16391639
1640fn dumpHashInfo(all_files: []const *const HashedFile) !void {1640fn dumpHashInfo(all_files: []const *const HashedFile) !void {
1641 var buffer: [4096]u8 = undefined;1641 var buffer: [4096]u8 = undefined;
1642 var bw: std.io.BufferedWriter = std.fs.File.stdout().writer().buffered(&buffer);1642 var file_writer = std.fs.File.stdout().writer(&buffer);
1643 const w = &file_writer.interface;
1643 for (all_files) |hashed_file| {1644 for (all_files) |hashed_file| {
1644 try bw.print("{s}: {x}: {s}\n", .{1645 try w.print("{s}: {x}: {s}\n", .{
1645 @tagName(hashed_file.kind), &hashed_file.hash, hashed_file.normalized_path,1646 @tagName(hashed_file.kind), &hashed_file.hash, hashed_file.normalized_path,
1646 });1647 });
1647 }1648 }
16481649 try file_writer.flush();
1649 try bw.flush();
1650}1650}
16511651
1652fn workerHashFile(dir: fs.Dir, hashed_file: *HashedFile) void {1652fn workerHashFile(dir: fs.Dir, hashed_file: *HashedFile) void {
src/Package/Fetch/git.zig+8-8
...@@ -12,6 +12,7 @@ const Sha1 = std.crypto.hash.Sha1;...@@ -12,6 +12,7 @@ const Sha1 = std.crypto.hash.Sha1;
12const Sha256 = std.crypto.hash.sha2.Sha256;12const Sha256 = std.crypto.hash.sha2.Sha256;
13const assert = std.debug.assert;13const assert = std.debug.assert;
14const zlib = std.compress.zlib;14const zlib = std.compress.zlib;
15const Writer = std.io.Writer;
1516
16/// The ID of a Git object.17/// The ID of a Git object.
17pub const Oid = union(Format) {18pub const Oid = union(Format) {
...@@ -65,7 +66,7 @@ pub const Oid = union(Format) {...@@ -65,7 +66,7 @@ pub const Oid = union(Format) {
65 };66 };
66 }67 }
6768
68 pub fn writable(hasher: *Hasher, buffer: []u8) std.io.BufferedWriter {69 pub fn writer(hasher: *Hasher, buffer: []u8) Writer {
69 return switch (hasher.*) {70 return switch (hasher.*) {
70 inline else => |*inner| inner.writable(buffer),71 inline else => |*inner| inner.writable(buffer),
71 };72 };
...@@ -134,9 +135,9 @@ pub const Oid = union(Format) {...@@ -134,9 +135,9 @@ pub const Oid = union(Format) {
134 } else error.InvalidOid;135 } else error.InvalidOid;
135 }136 }
136137
137 pub fn format(oid: Oid, bw: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {138 pub fn format(oid: Oid, w: *Writer, comptime fmt: []const u8) Writer.Error!void {
138 _ = fmt;139 comptime assert(fmt.len == 0);
139 try bw.print("{x}", .{oid.slice()});140 try w.print("{x}", .{oid.slice()});
140 }141 }
141142
142 pub fn slice(oid: *const Oid) []const u8 {143 pub fn slice(oid: *const Oid) []const u8 {
...@@ -608,7 +609,7 @@ const Packet = union(enum) {...@@ -608,7 +609,7 @@ const Packet = union(enum) {
608 }609 }
609610
610 /// Writes a packet in pkt-line format.611 /// Writes a packet in pkt-line format.
611 fn write(packet: Packet, writer: *std.io.BufferedWriter) !void {612 fn write(packet: Packet, writer: *Writer) !void {
612 switch (packet) {613 switch (packet) {
613 .flush => try writer.writeAll("0000"),614 .flush => try writer.writeAll("0000"),
614 .delimiter => try writer.writeAll("0001"),615 .delimiter => try writer.writeAll("0001"),
...@@ -1481,8 +1482,7 @@ fn resolveDeltaChain(...@@ -1481,8 +1482,7 @@ fn resolveDeltaChain(
1481 const expanded_alloc_size = std.math.cast(usize, expanded_size) orelse return error.ObjectTooLarge;1482 const expanded_alloc_size = std.math.cast(usize, expanded_size) orelse return error.ObjectTooLarge;
1482 const expanded_data = try allocator.alloc(u8, expanded_alloc_size);1483 const expanded_data = try allocator.alloc(u8, expanded_alloc_size);
1483 errdefer allocator.free(expanded_data);1484 errdefer allocator.free(expanded_data);
1484 var expanded_delta_stream: std.io.BufferedWriter = undefined;1485 var expanded_delta_stream: Writer = .fixed(expanded_data);
1485 expanded_delta_stream.initFixed(expanded_data);
1486 try expandDelta(base_data, &delta_reader, &expanded_delta_stream);1486 try expandDelta(base_data, &delta_reader, &expanded_delta_stream);
1487 if (expanded_delta_stream.end != expanded_size) return error.InvalidObject;1487 if (expanded_delta_stream.end != expanded_size) return error.InvalidObject;
14881488
...@@ -1505,7 +1505,7 @@ fn readObjectRaw(gpa: Allocator, reader: *std.io.Reader, size: u64) ![]u8 {...@@ -1505,7 +1505,7 @@ fn readObjectRaw(gpa: Allocator, reader: *std.io.Reader, size: u64) ![]u8 {
15051505
1506/// The format of the delta data is documented in1506/// The format of the delta data is documented in
1507/// [pack-format](https://git-scm.com/docs/pack-format).1507/// [pack-format](https://git-scm.com/docs/pack-format).
1508fn expandDelta(base_object: []const u8, delta_reader: *std.io.Reader, writer: *std.io.BufferedWriter) !void {1508fn expandDelta(base_object: []const u8, delta_reader: *std.io.Reader, writer: *Writer) !void {
1509 var base_offset: u32 = 0;1509 var base_offset: u32 = 0;
1510 while (true) {1510 while (true) {
1511 const inst: packed struct { value: u7, copy: bool } = @bitCast(delta_reader.takeByte() catch |e| switch (e) {1511 const inst: packed struct { value: u7, copy: bool } = @bitCast(delta_reader.takeByte() catch |e| switch (e) {
src/Sema.zig+4-4
...@@ -9544,8 +9544,8 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {...@@ -9544,8 +9544,8 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
9544fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {9544fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {
9545 const CallingConventionsSupportingVarArgsList = struct {9545 const CallingConventionsSupportingVarArgsList = struct {
9546 arch: std.Target.Cpu.Arch,9546 arch: std.Target.Cpu.Arch,
9547 pub fn format(ctx: @This(), bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {9547 pub fn format(ctx: @This(), bw: *std.io.Writer, comptime fmt: []const u8) !void {
9548 _ = fmt;9548 comptime assert(fmt.len == 0);
9549 var first = true;9549 var first = true;
9550 for (calling_conventions_supporting_var_args) |cc_inner| {9550 for (calling_conventions_supporting_var_args) |cc_inner| {
9551 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {9551 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {
...@@ -9990,8 +9990,8 @@ fn finishFunc(...@@ -9990,8 +9990,8 @@ fn finishFunc(
9990 .bad_arch => |allowed_archs| {9990 .bad_arch => |allowed_archs| {
9991 const ArchListFormatter = struct {9991 const ArchListFormatter = struct {
9992 archs: []const std.Target.Cpu.Arch,9992 archs: []const std.Target.Cpu.Arch,
9993 pub fn format(formatter: @This(), bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {9993 pub fn format(formatter: @This(), bw: *std.io.Writer, comptime fmt: []const u8) !void {
9994 _ = fmt;9994 comptime assert(fmt.len == 0);
9995 for (formatter.archs, 0..) |arch, i| {9995 for (formatter.archs, 0..) |arch, i| {
9996 if (i != 0)9996 if (i != 0)
9997 try bw.writeAll(", ");9997 try bw.writeAll(", ");
src/Type.zig+5-4
...@@ -18,6 +18,7 @@ const Alignment = InternPool.Alignment;...@@ -18,6 +18,7 @@ const Alignment = InternPool.Alignment;
18const Zir = std.zig.Zir;18const Zir = std.zig.Zir;
19const Type = @This();19const Type = @This();
20const SemaError = Zcu.SemaError;20const SemaError = Zcu.SemaError;
21const Writer = std.io.Writer;
2122
22ip_index: InternPool.Index,23ip_index: InternPool.Index,
2324
...@@ -121,7 +122,7 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool {...@@ -121,7 +122,7 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool {
121 return a.toIntern() == b.toIntern();122 return a.toIntern() == b.toIntern();
122}123}
123124
124pub fn format(ty: Type, bw: *std.io.BufferedWriter, comptime f: []const u8) !usize {125pub fn format(ty: Type, bw: *Writer, comptime f: []const u8) !usize {
125 _ = ty;126 _ = ty;
126 _ = f;127 _ = f;
127 _ = bw;128 _ = bw;
...@@ -142,7 +143,7 @@ const FormatContext = struct {...@@ -142,7 +143,7 @@ const FormatContext = struct {
142 pt: Zcu.PerThread,143 pt: Zcu.PerThread,
143};144};
144145
145fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime f: []const u8) !void {146fn format2(ctx: FormatContext, bw: *Writer, comptime f: []const u8) !void {
146 comptime assert(f.len == 0);147 comptime assert(f.len == 0);
147 try print(ctx.ty, bw, ctx.pt);148 try print(ctx.ty, bw, ctx.pt);
148}149}
...@@ -153,14 +154,14 @@ pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {...@@ -153,14 +154,14 @@ pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {
153154
154/// This is a debug function. In order to print types in a meaningful way155/// This is a debug function. In order to print types in a meaningful way
155/// we also need access to the module.156/// we also need access to the module.
156pub fn dump(start_type: Type, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) !void {157pub fn dump(start_type: Type, bw: *Writer, comptime unused_format_string: []const u8) !void {
157 comptime assert(unused_format_string.len == 0);158 comptime assert(unused_format_string.len == 0);
158 return bw.print("{any}", .{start_type.ip_index});159 return bw.print("{any}", .{start_type.ip_index});
159}160}
160161
161/// Prints a name suitable for `@typeName`.162/// Prints a name suitable for `@typeName`.
162/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.163/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.
163pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) std.io.Writer.Error!void {164pub fn print(ty: Type, bw: *Writer, pt: Zcu.PerThread) Writer.Error!void {
164 const zcu = pt.zcu;165 const zcu = pt.zcu;
165 const ip = &zcu.intern_pool;166 const ip = &zcu.intern_pool;
166 switch (ip.indexToKey(ty.toIntern())) {167 switch (ip.indexToKey(ty.toIntern())) {
src/Zcu.zig+4-4
...@@ -15,6 +15,7 @@ const BigIntConst = std.math.big.int.Const;...@@ -15,6 +15,7 @@ const BigIntConst = std.math.big.int.Const;
15const BigIntMutable = std.math.big.int.Mutable;15const BigIntMutable = std.math.big.int.Mutable;
16const Target = std.Target;16const Target = std.Target;
17const Ast = std.zig.Ast;17const Ast = std.zig.Ast;
18const Writer = std.io.Writer;
1819
19const Zcu = @This();20const Zcu = @This();
20const Compilation = @import("Compilation.zig");21const Compilation = @import("Compilation.zig");
...@@ -1101,8 +1102,7 @@ pub const File = struct {...@@ -1101,8 +1102,7 @@ pub const File = struct {
1101 const gpa = pt.zcu.gpa;1102 const gpa = pt.zcu.gpa;
1102 const ip = &pt.zcu.intern_pool;1103 const ip = &pt.zcu.intern_pool;
1103 const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);1104 const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);
1104 var bw: std.io.BufferedWriter = undefined;1105 var bw: Writer = .fixed((try strings.addManyAsSlice(file.fullyQualifiedNameLen()))[0]);
1105 bw.initFixed((try strings.addManyAsSlice(file.fullyQualifiedNameLen()))[0]);
1106 file.renderFullyQualifiedName(&bw) catch unreachable;1106 file.renderFullyQualifiedName(&bw) catch unreachable;
1107 assert(bw.end == bw.buffer.len);1107 assert(bw.end == bw.buffer.len);
1108 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(bw.end), .no_embedded_nulls);1108 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(bw.end), .no_embedded_nulls);
...@@ -4260,7 +4260,7 @@ pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(formatDe...@@ -4260,7 +4260,7 @@ pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(formatDe
4260 return .{ .data = .{ .dependee = d, .zcu = zcu } };4260 return .{ .data = .{ .dependee = d, .zcu = zcu } };
4261}4261}
42624262
4263fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {4263fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, bw: *Writer, comptime fmt: []const u8) !void {
4264 _ = fmt;4264 _ = fmt;
4265 const zcu = data.zcu;4265 const zcu = data.zcu;
4266 const ip = &zcu.intern_pool;4266 const ip = &zcu.intern_pool;
...@@ -4284,7 +4284,7 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, bw: *std.io.Buffer...@@ -4284,7 +4284,7 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, bw: *std.io.Buffer
4284 .memoized_state => return bw.writeAll("memoized_state"),4284 .memoized_state => return bw.writeAll("memoized_state"),
4285 }4285 }
4286}4286}
4287fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {4287fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, bw: *Writer, comptime fmt: []const u8) !void {
4288 _ = fmt;4288 _ = fmt;
4289 const zcu = data.zcu;4289 const zcu = data.zcu;
4290 const ip = &zcu.intern_pool;4290 const ip = &zcu.intern_pool;
src/arch/riscv64/CodeGen.zig+14-6
...@@ -6,6 +6,7 @@ const mem = std.mem;...@@ -6,6 +6,7 @@ const mem = std.mem;
6const math = std.math;6const math = std.math;
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const Allocator = mem.Allocator;8const Allocator = mem.Allocator;
9const Writer = std.io.Writer;
910
10const Air = @import("../../Air.zig");11const Air = @import("../../Air.zig");
11const Mir = @import("Mir.zig");12const Mir = @import("Mir.zig");
...@@ -566,7 +567,8 @@ const InstTracking = struct {...@@ -566,7 +567,8 @@ const InstTracking = struct {
566 }567 }
567 }568 }
568569
569 pub fn format(inst_tracking: InstTracking, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {570 pub fn format(inst_tracking: InstTracking, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
571 comptime assert(fmt.len == 0);
570 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try bw.print("|{}| ", .{inst_tracking.long});572 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try bw.print("|{}| ", .{inst_tracking.long});
571 try bw.print("{}", .{inst_tracking.short});573 try bw.print("{}", .{inst_tracking.short});
572 }574 }
...@@ -932,7 +934,7 @@ const FormatWipMirData = struct {...@@ -932,7 +934,7 @@ const FormatWipMirData = struct {
932 func: *Func,934 func: *Func,
933 inst: Mir.Inst.Index,935 inst: Mir.Inst.Index,
934};936};
935fn formatWipMir(data: FormatWipMirData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {937fn formatWipMir(data: FormatWipMirData, bw: *Writer, comptime _: []const u8) Writer.Error!void {
936 const pt = data.func.pt;938 const pt = data.func.pt;
937 const comp = pt.zcu.comp;939 const comp = pt.zcu.comp;
938 var lower: Lower = .{940 var lower: Lower = .{
...@@ -980,7 +982,7 @@ const FormatNavData = struct {...@@ -980,7 +982,7 @@ const FormatNavData = struct {
980 ip: *const InternPool,982 ip: *const InternPool,
981 nav_index: InternPool.Nav.Index,983 nav_index: InternPool.Nav.Index,
982};984};
983fn formatNav(data: FormatNavData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {985fn formatNav(data: FormatNavData, bw: *Writer, comptime _: []const u8) Writer.Error!void {
984 try bw.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});986 try bw.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
985}987}
986fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {988fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {
...@@ -994,8 +996,13 @@ const FormatAirData = struct {...@@ -994,8 +996,13 @@ const FormatAirData = struct {
994 func: *Func,996 func: *Func,
995 inst: Air.Inst.Index,997 inst: Air.Inst.Index,
996};998};
997fn formatAir(data: FormatAirData, _: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {999fn formatAir(data: FormatAirData, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
998 data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness);1000 comptime assert(fmt.len == 0);
1001 // not acceptable implementation:
1002 // data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness);
1003 _ = data;
1004 _ = w;
1005 @panic("TODO: unimplemented");
999}1006}
1000fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {1007fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
1001 return .{ .data = .{ .func = func, .inst = inst } };1008 return .{ .data = .{ .func = func, .inst = inst } };
...@@ -1004,7 +1011,8 @@ fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {...@@ -1004,7 +1011,8 @@ fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
1004const FormatTrackingData = struct {1011const FormatTrackingData = struct {
1005 func: *Func,1012 func: *Func,
1006};1013};
1007fn formatTracking(data: FormatTrackingData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1014fn formatTracking(data: FormatTrackingData, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
1015 comptime assert(fmt.len == 0);
1008 var it = data.func.inst_tracking.iterator();1016 var it = data.func.inst_tracking.iterator();
1009 while (it.next()) |entry| try bw.print("\n%{d} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });1017 while (it.next()) |entry| try bw.print("\n%{d} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });
1010}1018}
src/arch/riscv64/Mir.zig+1-1
...@@ -92,7 +92,7 @@ pub const Inst = struct {...@@ -92,7 +92,7 @@ pub const Inst = struct {
92 },92 },
93 };93 };
9494
95 pub fn format(inst: Inst, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {95 pub fn format(inst: Inst, bw: *std.io.Writer, comptime fmt: []const u8) !void {
96 assert(fmt.len == 0);96 assert(fmt.len == 0);
97 try bw.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });97 try bw.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });
98 }98 }
src/arch/riscv64/bits.zig+3-1
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;3const testing = std.testing;
4const Target = std.Target;4const Target = std.Target;
5const Writer = std.io.Writer;
56
6const Zcu = @import("../../Zcu.zig");7const Zcu = @import("../../Zcu.zig");
7const Mir = @import("Mir.zig");8const Mir = @import("Mir.zig");
...@@ -256,7 +257,8 @@ pub const FrameIndex = enum(u32) {...@@ -256,7 +257,8 @@ pub const FrameIndex = enum(u32) {
256 return @intFromEnum(fi) < named_count;257 return @intFromEnum(fi) < named_count;
257 }258 }
258259
259 pub fn format(fi: FrameIndex, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {260 pub fn format(fi: FrameIndex, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
261 comptime assert(fmt.len == 0);
260 try bw.writeAll("FrameIndex");262 try bw.writeAll("FrameIndex");
261 if (fi.isNamed())263 if (fi.isNamed())
262 try bw.print(".{s}", .{@tagName(fi)})264 try bw.print(".{s}", .{@tagName(fi)})
src/arch/wasm/CodeGen.zig+1
...@@ -5,6 +5,7 @@ const assert = std.debug.assert;...@@ -5,6 +5,7 @@ const assert = std.debug.assert;
5const testing = std.testing;5const testing = std.testing;
6const mem = std.mem;6const mem = std.mem;
7const log = std.log.scoped(.codegen);7const log = std.log.scoped(.codegen);
8const Writer = std.io.Writer;
89
9const CodeGen = @This();10const CodeGen = @This();
10const codegen = @import("../../codegen.zig");11const codegen = @import("../../codegen.zig");
src/arch/wasm/Emit.zig+7-6
...@@ -4,6 +4,7 @@ const std = @import("std");...@@ -4,6 +4,7 @@ const std = @import("std");
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const Allocator = std.mem.Allocator;5const Allocator = std.mem.Allocator;
6const leb = std.leb;6const leb = std.leb;
7const Writer = std.io.Writer;
78
8const Wasm = link.File.Wasm;9const Wasm = link.File.Wasm;
9const Mir = @import("Mir.zig");10const Mir = @import("Mir.zig");
...@@ -15,7 +16,7 @@ const codegen = @import("../../codegen.zig");...@@ -15,7 +16,7 @@ const codegen = @import("../../codegen.zig");
15mir: Mir,16mir: Mir,
16wasm: *Wasm,17wasm: *Wasm,
17/// The binary representation of this module is written here.18/// The binary representation of this module is written here.
18bw: *std.io.BufferedWriter,19bw: *Writer,
1920
20pub const Error = error{21pub const Error = error{
21 OutOfMemory,22 OutOfMemory,
...@@ -893,12 +894,12 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -893,12 +894,12 @@ pub fn lowerToCode(emit: *Emit) Error!void {
893}894}
894895
895/// Asserts 20 unused capacity.896/// Asserts 20 unused capacity.
896fn encodeMemArg(bw: *std.io.BufferedWriter, mem_arg: Mir.MemArg) std.io.Writer.Error!void {897fn encodeMemArg(bw: *Writer, mem_arg: Mir.MemArg) Writer.Error!void {
897 try bw.writeLeb128(Wasm.Alignment.fromNonzeroByteUnits(mem_arg.alignment).toLog2Units());898 try bw.writeLeb128(Wasm.Alignment.fromNonzeroByteUnits(mem_arg.alignment).toLog2Units());
898 try bw.writeLeb128(mem_arg.offset);899 try bw.writeLeb128(mem_arg.offset);
899}900}
900901
901fn uavRefObj(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, offset: i32, is_wasm32: bool) std.io.Writer.Error!void {902fn uavRefObj(wasm: *Wasm, bw: *Writer, value: InternPool.Index, offset: i32, is_wasm32: bool) Writer.Error!void {
902 const comp = wasm.base.comp;903 const comp = wasm.base.comp;
903 const gpa = comp.gpa;904 const gpa = comp.gpa;
904 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;905 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
...@@ -914,7 +915,7 @@ fn uavRefObj(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, o...@@ -914,7 +915,7 @@ fn uavRefObj(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, o
914 try bw.splatByteAll(0, if (is_wasm32) 5 else 10);915 try bw.splatByteAll(0, if (is_wasm32) 5 else 10);
915}916}
916917
917fn uavRefExe(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, offset: i32, is_wasm32: bool) !void {918fn uavRefExe(wasm: *Wasm, bw: *Writer, value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
918 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;919 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
919 try bw.writeByte(@intFromEnum(opcode));920 try bw.writeByte(@intFromEnum(opcode));
920921
...@@ -922,7 +923,7 @@ fn uavRefExe(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, o...@@ -922,7 +923,7 @@ fn uavRefExe(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, o
922 try bw.writeLeb128(@as(u32, @intCast(@as(i64, addr) + offset)));923 try bw.writeLeb128(@as(u32, @intCast(@as(i64, addr) + offset)));
923}924}
924925
925fn navRefOff(wasm: *Wasm, bw: *std.io.BufferedWriter, data: Mir.NavRefOff, is_wasm32: bool) !void {926fn navRefOff(wasm: *Wasm, bw: *Writer, data: Mir.NavRefOff, is_wasm32: bool) !void {
926 const comp = wasm.base.comp;927 const comp = wasm.base.comp;
927 const zcu = comp.zcu.?;928 const zcu = comp.zcu.?;
928 const ip = &zcu.intern_pool;929 const ip = &zcu.intern_pool;
...@@ -947,6 +948,6 @@ fn navRefOff(wasm: *Wasm, bw: *std.io.BufferedWriter, data: Mir.NavRefOff, is_wa...@@ -947,6 +948,6 @@ fn navRefOff(wasm: *Wasm, bw: *std.io.BufferedWriter, data: Mir.NavRefOff, is_wa
947 }948 }
948}949}
949950
950fn appendOutputFunctionIndex(bw: *std.io.BufferedWriter, i: Wasm.OutputFunctionIndex) std.io.Writer.Error!void {951fn appendOutputFunctionIndex(bw: *Writer, i: Wasm.OutputFunctionIndex) Writer.Error!void {
951 return bw.writeLeb128(@intFromEnum(i));952 return bw.writeLeb128(@intFromEnum(i));
952}953}
src/arch/x86_64/CodeGen.zig+14-7
...@@ -6,6 +6,7 @@ const log = std.log.scoped(.codegen);...@@ -6,6 +6,7 @@ const log = std.log.scoped(.codegen);
6const tracking_log = std.log.scoped(.tracking);6const tracking_log = std.log.scoped(.tracking);
7const verbose_tracking_log = std.log.scoped(.verbose_tracking);7const verbose_tracking_log = std.log.scoped(.verbose_tracking);
8const wip_mir_log = std.log.scoped(.wip_mir);8const wip_mir_log = std.log.scoped(.wip_mir);
9const Writer = std.io.Writer;
910
10const Air = @import("../../Air.zig");11const Air = @import("../../Air.zig");
11const Allocator = std.mem.Allocator;12const Allocator = std.mem.Allocator;
...@@ -524,7 +525,7 @@ pub const MCValue = union(enum) {...@@ -524,7 +525,7 @@ pub const MCValue = union(enum) {
524 };525 };
525 }526 }
526527
527 pub fn format(mcv: MCValue, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {528 pub fn format(mcv: MCValue, bw: *Writer, comptime _: []const u8) Writer.Error!void {
528 switch (mcv) {529 switch (mcv) {
529 .none, .unreach, .dead, .undef => try bw.print("({s})", .{@tagName(mcv)}),530 .none, .unreach, .dead, .undef => try bw.print("({s})", .{@tagName(mcv)}),
530 .immediate => |pl| try bw.print("0x{x}", .{pl}),531 .immediate => |pl| try bw.print("0x{x}", .{pl}),
...@@ -811,7 +812,7 @@ const InstTracking = struct {...@@ -811,7 +812,7 @@ const InstTracking = struct {
811 }812 }
812 }813 }
813814
814 pub fn format(tracking: InstTracking, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {815 pub fn format(tracking: InstTracking, bw: *Writer, comptime _: []const u8) Writer.Error!void {
815 if (!std.meta.eql(tracking.long, tracking.short)) try bw.print("|{f}| ", .{tracking.long});816 if (!std.meta.eql(tracking.long, tracking.short)) try bw.print("|{f}| ", .{tracking.long});
816 try bw.print("{f}", .{tracking.short});817 try bw.print("{f}", .{tracking.short});
817 }818 }
...@@ -1087,7 +1088,7 @@ const FormatNavData = struct {...@@ -1087,7 +1088,7 @@ const FormatNavData = struct {
1087 ip: *const InternPool,1088 ip: *const InternPool,
1088 nav_index: InternPool.Nav.Index,1089 nav_index: InternPool.Nav.Index,
1089};1090};
1090fn formatNav(data: FormatNavData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1091fn formatNav(data: FormatNavData, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1091 try bw.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});1092 try bw.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1092}1093}
1093fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {1094fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {
...@@ -1101,8 +1102,13 @@ const FormatAirData = struct {...@@ -1101,8 +1102,13 @@ const FormatAirData = struct {
1101 self: *CodeGen,1102 self: *CodeGen,
1102 inst: Air.Inst.Index,1103 inst: Air.Inst.Index,
1103};1104};
1104fn formatAir(data: FormatAirData, _: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1105fn formatAir(data: FormatAirData, w: *std.io.Writer, comptime fmt: []const u8) Writer.Error!void {
1105 data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness);1106 comptime assert(fmt.len == 0);
1107 // not acceptable implementation:
1108 //data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness);
1109 _ = data;
1110 _ = w;
1111 @panic("TODO: unimplemented");
1106}1112}
1107fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {1113fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
1108 return .{ .data = .{ .self = self, .inst = inst } };1114 return .{ .data = .{ .self = self, .inst = inst } };
...@@ -1112,7 +1118,7 @@ const FormatWipMirData = struct {...@@ -1112,7 +1118,7 @@ const FormatWipMirData = struct {
1112 self: *CodeGen,1118 self: *CodeGen,
1113 inst: Mir.Inst.Index,1119 inst: Mir.Inst.Index,
1114};1120};
1115fn formatWipMir(data: FormatWipMirData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1121fn formatWipMir(data: FormatWipMirData, bw: *Writer, comptime _: []const u8) Writer.Error!void {
1116 var lower: Lower = .{1122 var lower: Lower = .{
1117 .target = data.self.target,1123 .target = data.self.target,
1118 .allocator = data.self.gpa,1124 .allocator = data.self.gpa,
...@@ -1208,7 +1214,8 @@ fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMi...@@ -1208,7 +1214,8 @@ fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMi
1208const FormatTrackingData = struct {1214const FormatTrackingData = struct {
1209 self: *CodeGen,1215 self: *CodeGen,
1210};1216};
1211fn formatTracking(data: FormatTrackingData, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {1217fn formatTracking(data: FormatTrackingData, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
1218 comptime assert(fmt.len == 0);
1212 var it = data.self.inst_tracking.iterator();1219 var it = data.self.inst_tracking.iterator();
1213 while (it.next()) |entry| try bw.print("\n{f} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });1220 while (it.next()) |entry| try bw.print("\n{f} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });
1214}1221}
src/arch/x86_64/Disassembler.zig+2-4
...@@ -372,8 +372,7 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi...@@ -372,8 +372,7 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi
372}372}
373373
374fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {374fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {
375 var br: std.io.Reader = undefined;375 var br: std.io.Reader = .fixed(dis.code[dis.pos..]);
376 br.initFixed(dis.code[dis.pos..]);
377 defer dis.pos += br.seek;376 defer dis.pos += br.seek;
378 return switch (kind) {377 return switch (kind) {
379 .imm8s, .rel8 => .s(try br.takeInt(i8, .little)),378 .imm8s, .rel8 => .s(try br.takeInt(i8, .little)),
...@@ -388,8 +387,7 @@ fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {...@@ -388,8 +387,7 @@ fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {
388}387}
389388
390fn parseOffset(dis: *Disassembler) !u64 {389fn parseOffset(dis: *Disassembler) !u64 {
391 var br: std.io.Reader = undefined;390 var br: std.io.Reader = .fixed(dis.code[dis.pos..]);
392 br.initFixed(dis.code[dis.pos..]);
393 defer dis.pos += br.seek;391 defer dis.pos += br.seek;
394 return br.takeInt(u64, .little);392 return br.takeInt(u64, .little);
395}393}
src/arch/x86_64/Encoding.zig+4-4
...@@ -3,6 +3,7 @@ const Encoding = @This();...@@ -3,6 +3,7 @@ const Encoding = @This();
3const std = @import("std");3const std = @import("std");
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const math = std.math;5const math = std.math;
6const Writer = std.io.Writer;
67
7const bits = @import("bits.zig");8const bits = @import("bits.zig");
8const encoder = @import("encoder.zig");9const encoder = @import("encoder.zig");
...@@ -158,8 +159,8 @@ pub fn modRmExt(encoding: Encoding) u3 {...@@ -158,8 +159,8 @@ pub fn modRmExt(encoding: Encoding) u3 {
158 };159 };
159}160}
160161
161pub fn format(encoding: Encoding, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {162pub fn format(encoding: Encoding, bw: *Writer, comptime fmt: []const u8) !void {
162 _ = fmt;163 comptime assert(fmt.len == 0);
163164
164 var opc = encoding.opcode();165 var opc = encoding.opcode();
165 if (encoding.data.mode.isVex()) {166 if (encoding.data.mode.isVex()) {
...@@ -1016,8 +1017,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op...@@ -1016,8 +1017,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op
1016 @memcpy(inst.ops[0..ops.len], ops);1017 @memcpy(inst.ops[0..ops.len], ops);
10171018
1018 var buf: [15]u8 = undefined;1019 var buf: [15]u8 = undefined;
1019 var bw: std.io.BufferedWriter = undefined;1020 var bw: Writer = .fixed(&buf);
1020 bw.initFixed(&buf);
1021 inst.encode(&bw, .{1021 inst.encode(&bw, .{
1022 .allow_frame_locs = true,1022 .allow_frame_locs = true,
1023 .allow_symbols = true,1023 .allow_symbols = true,
src/arch/x86_64/bits.zig+6-2
...@@ -6,6 +6,8 @@ const Allocator = std.mem.Allocator;...@@ -6,6 +6,8 @@ const Allocator = std.mem.Allocator;
6const ArrayList = std.ArrayList;6const ArrayList = std.ArrayList;
7const InternPool = @import("../../InternPool.zig");7const InternPool = @import("../../InternPool.zig");
8const link = @import("../../link.zig");8const link = @import("../../link.zig");
9const Writer = std.io.Writer;
10
9const Mir = @import("Mir.zig");11const Mir = @import("Mir.zig");
1012
11/// EFLAGS condition codes13/// EFLAGS condition codes
...@@ -728,7 +730,8 @@ pub const FrameIndex = enum(u32) {...@@ -728,7 +730,8 @@ pub const FrameIndex = enum(u32) {
728 return @intFromEnum(fi) < named_count;730 return @intFromEnum(fi) < named_count;
729 }731 }
730732
731 pub fn format(fi: FrameIndex, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {733 pub fn format(fi: FrameIndex, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
734 comptime assert(fmt.len == 0);
732 try bw.writeAll("FrameIndex");735 try bw.writeAll("FrameIndex");
733 if (fi.isNamed())736 if (fi.isNamed())
734 try bw.print(".{s}", .{@tagName(fi)})737 try bw.print(".{s}", .{@tagName(fi)})
...@@ -835,7 +838,8 @@ pub const Memory = struct {...@@ -835,7 +838,8 @@ pub const Memory = struct {
835 };838 };
836 }839 }
837840
838 pub fn format(s: Size, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {841 pub fn format(s: Size, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
842 comptime assert(fmt.len == 0);
839 if (s == .none) return;843 if (s == .none) return;
840 try bw.writeAll(@tagName(s));844 try bw.writeAll(@tagName(s));
841 switch (s) {845 switch (s) {
src/arch/x86_64/encoder.zig+7-6
...@@ -3,6 +3,7 @@ const assert = std.debug.assert;...@@ -3,6 +3,7 @@ const assert = std.debug.assert;
3const log = std.log.scoped(.x86_64_encoder);3const log = std.log.scoped(.x86_64_encoder);
4const math = std.math;4const math = std.math;
5const testing = std.testing;5const testing = std.testing;
6const Writer = std.io.Writer;
67
7const bits = @import("bits.zig");8const bits = @import("bits.zig");
8const Encoding = @import("Encoding.zig");9const Encoding = @import("Encoding.zig");
...@@ -226,7 +227,7 @@ pub const Instruction = struct {...@@ -226,7 +227,7 @@ pub const Instruction = struct {
226 };227 };
227 }228 }
228229
229 fn format(op: Operand, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) !void {230 fn format(op: Operand, bw: *Writer, comptime unused_format_string: []const u8) !void {
230 _ = op;231 _ = op;
231 _ = bw;232 _ = bw;
232 _ = unused_format_string;233 _ = unused_format_string;
...@@ -238,7 +239,7 @@ pub const Instruction = struct {...@@ -238,7 +239,7 @@ pub const Instruction = struct {
238 enc_op: Encoding.Op,239 enc_op: Encoding.Op,
239 };240 };
240241
241 fn fmtContext(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {242 fn fmtContext(ctx: FormatContext, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
242 _ = unused_format_string;243 _ = unused_format_string;
243 const op = ctx.op;244 const op = ctx.op;
244 const enc_op = ctx.enc_op;245 const enc_op = ctx.enc_op;
...@@ -360,7 +361,7 @@ pub const Instruction = struct {...@@ -360,7 +361,7 @@ pub const Instruction = struct {
360 return inst;361 return inst;
361 }362 }
362363
363 pub fn format(inst: Instruction, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {364 pub fn format(inst: Instruction, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
364 _ = unused_format_string;365 _ = unused_format_string;
365 switch (inst.prefix) {366 switch (inst.prefix) {
366 .none, .directive => {},367 .none, .directive => {},
...@@ -374,7 +375,7 @@ pub const Instruction = struct {...@@ -374,7 +375,7 @@ pub const Instruction = struct {
374 }375 }
375 }376 }
376377
377 pub fn encode(inst: Instruction, bw: *std.io.BufferedWriter, comptime opts: Options) !void {378 pub fn encode(inst: Instruction, bw: *Writer, comptime opts: Options) !void {
378 assert(inst.prefix != .directive);379 assert(inst.prefix != .directive);
379 const encoder: Encoder(opts) = .{ .bw = bw };380 const encoder: Encoder(opts) = .{ .bw = bw };
380 const enc = inst.encoding;381 const enc = inst.encoding;
...@@ -784,7 +785,7 @@ pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool...@@ -784,7 +785,7 @@ pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool
784785
785fn Encoder(comptime opts: Options) type {786fn Encoder(comptime opts: Options) type {
786 return struct {787 return struct {
787 bw: *std.io.BufferedWriter,788 bw: *Writer,
788789
789 const Self = @This();790 const Self = @This();
790 pub const options = opts;791 pub const options = opts;
...@@ -2198,7 +2199,7 @@ const Assembler = struct {...@@ -2198,7 +2199,7 @@ const Assembler = struct {
2198 };2199 };
2199 }2200 }
22002201
2201 pub fn assemble(as: *Assembler, bw: *std.io.BufferedWriter) !void {2202 pub fn assemble(as: *Assembler, bw: *Writer) !void {
2202 while (try as.next()) |parsed_inst| {2203 while (try as.next()) |parsed_inst| {
2203 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);2204 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);
2204 try inst.encode(bw, .{});2205 try inst.encode(bw, .{});
src/codegen.zig+5-4
...@@ -8,6 +8,7 @@ const mem = std.mem;...@@ -8,6 +8,7 @@ const mem = std.mem;
8const math = std.math;8const math = std.math;
9const target_util = @import("target.zig");9const target_util = @import("target.zig");
10const trace = @import("tracy.zig").trace;10const trace = @import("tracy.zig").trace;
11const Writer = std.io.Writer;
1112
12const Air = @import("Air.zig");13const Air = @import("Air.zig");
13const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
...@@ -326,7 +327,7 @@ pub fn generateSymbolInner(...@@ -326,7 +327,7 @@ pub fn generateSymbolInner(
326 pt: Zcu.PerThread,327 pt: Zcu.PerThread,
327 src_loc: Zcu.LazySrcLoc,328 src_loc: Zcu.LazySrcLoc,
328 val: Value,329 val: Value,
329 bw: *std.io.BufferedWriter,330 bw: *Writer,
330 reloc_parent: link.File.RelocInfo.Parent,331 reloc_parent: link.File.RelocInfo.Parent,
331) GenerateSymbolError!void {332) GenerateSymbolError!void {
332 const zcu = pt.zcu;333 const zcu = pt.zcu;
...@@ -707,7 +708,7 @@ fn lowerPtr(...@@ -707,7 +708,7 @@ fn lowerPtr(
707 pt: Zcu.PerThread,708 pt: Zcu.PerThread,
708 src_loc: Zcu.LazySrcLoc,709 src_loc: Zcu.LazySrcLoc,
709 ptr_val: InternPool.Index,710 ptr_val: InternPool.Index,
710 bw: *std.io.BufferedWriter,711 bw: *Writer,
711 reloc_parent: link.File.RelocInfo.Parent,712 reloc_parent: link.File.RelocInfo.Parent,
712 prev_offset: u64,713 prev_offset: u64,
713) GenerateSymbolError!void {714) GenerateSymbolError!void {
...@@ -760,7 +761,7 @@ fn lowerUavRef(...@@ -760,7 +761,7 @@ fn lowerUavRef(
760 pt: Zcu.PerThread,761 pt: Zcu.PerThread,
761 src_loc: Zcu.LazySrcLoc,762 src_loc: Zcu.LazySrcLoc,
762 uav: InternPool.Key.Ptr.BaseAddr.Uav,763 uav: InternPool.Key.Ptr.BaseAddr.Uav,
763 bw: *std.io.BufferedWriter,764 bw: *Writer,
764 reloc_parent: link.File.RelocInfo.Parent,765 reloc_parent: link.File.RelocInfo.Parent,
765 offset: u64,766 offset: u64,
766) GenerateSymbolError!void {767) GenerateSymbolError!void {
...@@ -814,7 +815,7 @@ fn lowerNavRef(...@@ -814,7 +815,7 @@ fn lowerNavRef(
814 lf: *link.File,815 lf: *link.File,
815 pt: Zcu.PerThread,816 pt: Zcu.PerThread,
816 nav_index: InternPool.Nav.Index,817 nav_index: InternPool.Nav.Index,
817 bw: *std.io.BufferedWriter,818 bw: *Writer,
818 reloc_parent: link.File.RelocInfo.Parent,819 reloc_parent: link.File.RelocInfo.Parent,
819 offset: u64,820 offset: u64,
820) GenerateSymbolError!void {821) GenerateSymbolError!void {
src/codegen/c.zig+68-67
...@@ -4,6 +4,7 @@ const assert = std.debug.assert;...@@ -4,6 +4,7 @@ const assert = std.debug.assert;
4const mem = std.mem;4const mem = std.mem;
5const log = std.log.scoped(.c);5const log = std.log.scoped(.c);
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
7const Writer = std.io.Writer;
78
8const dev = @import("../dev.zig");9const dev = @import("../dev.zig");
9const link = @import("../link.zig");10const link = @import("../link.zig");
...@@ -69,7 +70,7 @@ pub const Mir = struct {...@@ -69,7 +70,7 @@ pub const Mir = struct {
69 }70 }
70};71};
7172
72pub const Error = std.io.Writer.Error || std.mem.Allocator.Error || error{AnalysisFail};73pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail};
7374
74pub const CType = @import("c/Type.zig");75pub const CType = @import("c/Type.zig");
7576
...@@ -344,9 +345,9 @@ fn isReservedIdent(ident: []const u8) bool {...@@ -344,9 +345,9 @@ fn isReservedIdent(ident: []const u8) bool {
344345
345fn formatIdent(346fn formatIdent(
346 ident: []const u8,347 ident: []const u8,
347 bw: *std.io.BufferedWriter,348 bw: *Writer,
348 comptime fmt_str: []const u8,349 comptime fmt_str: []const u8,
349) std.io.Writer.Error!void {350) Writer.Error!void {
350 const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident.351 const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident.
351 if (solo and isReservedIdent(ident)) {352 if (solo and isReservedIdent(ident)) {
352 try bw.writeAll("zig_e_");353 try bw.writeAll("zig_e_");
...@@ -374,9 +375,9 @@ const CTypePoolStringFormatData = struct {...@@ -374,9 +375,9 @@ const CTypePoolStringFormatData = struct {
374};375};
375fn formatCTypePoolString(376fn formatCTypePoolString(
376 data: CTypePoolStringFormatData,377 data: CTypePoolStringFormatData,
377 bw: *std.io.BufferedWriter,378 bw: *Writer,
378 comptime fmt_str: []const u8,379 comptime fmt_str: []const u8,
379) std.io.Writer.Error!void {380) Writer.Error!void {
380 if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice|381 if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice|
381 try formatIdent(slice, bw, fmt_str)382 try formatIdent(slice, bw, fmt_str)
382 else383 else
...@@ -504,7 +505,7 @@ pub const Function = struct {...@@ -504,7 +505,7 @@ pub const Function = struct {
504 return result;505 return result;
505 }506 }
506507
507 fn writeCValue(f: *Function, bw: *std.io.BufferedWriter, c_value: CValue, location: ValueRenderLocation) !void {508 fn writeCValue(f: *Function, bw: *Writer, c_value: CValue, location: ValueRenderLocation) !void {
508 switch (c_value) {509 switch (c_value) {
509 .none => unreachable,510 .none => unreachable,
510 .new_local, .local => |i| try bw.print("t{d}", .{i}),511 .new_local, .local => |i| try bw.print("t{d}", .{i}),
...@@ -517,7 +518,7 @@ pub const Function = struct {...@@ -517,7 +518,7 @@ pub const Function = struct {
517 }518 }
518 }519 }
519520
520 fn writeCValueDeref(f: *Function, bw: *std.io.BufferedWriter, c_value: CValue) !void {521 fn writeCValueDeref(f: *Function, bw: *Writer, c_value: CValue) !void {
521 switch (c_value) {522 switch (c_value) {
522 .none => unreachable,523 .none => unreachable,
523 .new_local, .local, .constant => {524 .new_local, .local, .constant => {
...@@ -538,7 +539,7 @@ pub const Function = struct {...@@ -538,7 +539,7 @@ pub const Function = struct {
538539
539 fn writeCValueMember(540 fn writeCValueMember(
540 f: *Function,541 f: *Function,
541 bw: *std.io.BufferedWriter,542 bw: *Writer,
542 c_value: CValue,543 c_value: CValue,
543 member: CValue,544 member: CValue,
544 ) Error!void {545 ) Error!void {
...@@ -552,7 +553,7 @@ pub const Function = struct {...@@ -552,7 +553,7 @@ pub const Function = struct {
552 }553 }
553 }554 }
554555
555 fn writeCValueDerefMember(f: *Function, bw: *std.io.BufferedWriter, c_value: CValue, member: CValue) !void {556 fn writeCValueDerefMember(f: *Function, bw: *Writer, c_value: CValue, member: CValue) !void {
556 switch (c_value) {557 switch (c_value) {
557 .new_local, .local, .arg, .arg_array => {558 .new_local, .local, .arg, .arg_array => {
558 try f.writeCValue(bw, c_value, .Other);559 try f.writeCValue(bw, c_value, .Other);
...@@ -584,15 +585,15 @@ pub const Function = struct {...@@ -584,15 +585,15 @@ pub const Function = struct {
584 return f.object.dg.byteSize(ctype);585 return f.object.dg.byteSize(ctype);
585 }586 }
586587
587 fn renderType(f: *Function, bw: *std.io.BufferedWriter, ctype: Type) !void {588 fn renderType(f: *Function, bw: *Writer, ctype: Type) !void {
588 return f.object.dg.renderType(bw, ctype);589 return f.object.dg.renderType(bw, ctype);
589 }590 }
590591
591 fn renderCType(f: *Function, bw: *std.io.BufferedWriter, ctype: CType) !void {592 fn renderCType(f: *Function, bw: *Writer, ctype: CType) !void {
592 return f.object.dg.renderCType(bw, ctype);593 return f.object.dg.renderCType(bw, ctype);
593 }594 }
594595
595 fn renderIntCast(f: *Function, bw: *std.io.BufferedWriter, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {596 fn renderIntCast(f: *Function, bw: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
596 return f.object.dg.renderIntCast(bw, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);597 return f.object.dg.renderIntCast(bw, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
597 }598 }
598599
...@@ -757,7 +758,7 @@ pub const DeclGen = struct {...@@ -757,7 +758,7 @@ pub const DeclGen = struct {
757758
758 fn renderUav(759 fn renderUav(
759 dg: *DeclGen,760 dg: *DeclGen,
760 bw: *std.io.BufferedWriter,761 bw: *Writer,
761 uav: InternPool.Key.Ptr.BaseAddr.Uav,762 uav: InternPool.Key.Ptr.BaseAddr.Uav,
762 location: ValueRenderLocation,763 location: ValueRenderLocation,
763 ) Error!void {764 ) Error!void {
...@@ -819,7 +820,7 @@ pub const DeclGen = struct {...@@ -819,7 +820,7 @@ pub const DeclGen = struct {
819820
820 fn renderNav(821 fn renderNav(
821 dg: *DeclGen,822 dg: *DeclGen,
822 bw: *std.io.BufferedWriter,823 bw: *Writer,
823 nav_index: InternPool.Nav.Index,824 nav_index: InternPool.Nav.Index,
824 location: ValueRenderLocation,825 location: ValueRenderLocation,
825 ) Error!void {826 ) Error!void {
...@@ -868,7 +869,7 @@ pub const DeclGen = struct {...@@ -868,7 +869,7 @@ pub const DeclGen = struct {
868869
869 fn renderPointer(870 fn renderPointer(
870 dg: *DeclGen,871 dg: *DeclGen,
871 bw: *std.io.BufferedWriter,872 bw: *Writer,
872 derivation: Value.PointerDeriveStep,873 derivation: Value.PointerDeriveStep,
873 location: ValueRenderLocation,874 location: ValueRenderLocation,
874 ) Error!void {875 ) Error!void {
...@@ -972,13 +973,13 @@ pub const DeclGen = struct {...@@ -972,13 +973,13 @@ pub const DeclGen = struct {
972 }973 }
973 }974 }
974975
975 fn renderErrorName(dg: *DeclGen, bw: *std.io.BufferedWriter, err_name: InternPool.NullTerminatedString) !void {976 fn renderErrorName(dg: *DeclGen, bw: *Writer, err_name: InternPool.NullTerminatedString) !void {
976 try bw.print("zig_error_{f}", .{fmtIdent(err_name.toSlice(&dg.pt.zcu.intern_pool))});977 try bw.print("zig_error_{f}", .{fmtIdent(err_name.toSlice(&dg.pt.zcu.intern_pool))});
977 }978 }
978979
979 fn renderValue(980 fn renderValue(
980 dg: *DeclGen,981 dg: *DeclGen,
981 writer: *std.io.BufferedWriter,982 writer: *Writer,
982 val: Value,983 val: Value,
983 location: ValueRenderLocation,984 location: ValueRenderLocation,
984 ) Error!void {985 ) Error!void {
...@@ -1587,7 +1588,7 @@ pub const DeclGen = struct {...@@ -1587,7 +1588,7 @@ pub const DeclGen = struct {
15871588
1588 fn renderUndefValue(1589 fn renderUndefValue(
1589 dg: *DeclGen,1590 dg: *DeclGen,
1590 bw: *std.io.BufferedWriter,1591 bw: *Writer,
1591 ty: Type,1592 ty: Type,
1592 location: ValueRenderLocation,1593 location: ValueRenderLocation,
1593 ) Error!void {1594 ) Error!void {
...@@ -1890,7 +1891,7 @@ pub const DeclGen = struct {...@@ -1890,7 +1891,7 @@ pub const DeclGen = struct {
18901891
1891 fn renderFunctionSignature(1892 fn renderFunctionSignature(
1892 dg: *DeclGen,1893 dg: *DeclGen,
1893 bw: *std.io.BufferedWriter,1894 bw: *Writer,
1894 fn_val: Value,1895 fn_val: Value,
1895 fn_align: InternPool.Alignment,1896 fn_align: InternPool.Alignment,
1896 kind: CType.Kind,1897 kind: CType.Kind,
...@@ -2011,11 +2012,11 @@ pub const DeclGen = struct {...@@ -2011,11 +2012,11 @@ pub const DeclGen = struct {
2011 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |2012 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2012 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |2013 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2013 ///2014 ///
2014 fn renderType(dg: *DeclGen, bw: *std.io.BufferedWriter, t: Type) Error!void {2015 fn renderType(dg: *DeclGen, bw: *Writer, t: Type) Error!void {
2015 try dg.renderCType(bw, try dg.ctypeFromType(t, .complete));2016 try dg.renderCType(bw, try dg.ctypeFromType(t, .complete));
2016 }2017 }
20172018
2018 fn renderCType(dg: *DeclGen, bw: *std.io.BufferedWriter, ctype: CType) Error!void {2019 fn renderCType(dg: *DeclGen, bw: *Writer, ctype: CType) Error!void {
2019 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, bw, ctype, .suffix, .{});2020 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, bw, ctype, .suffix, .{});
2020 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, bw, ctype, .suffix, .{});2021 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, bw, ctype, .suffix, .{});
2021 }2022 }
...@@ -2030,7 +2031,7 @@ pub const DeclGen = struct {...@@ -2030,7 +2031,7 @@ pub const DeclGen = struct {
2030 value: Value,2031 value: Value,
2031 },2032 },
20322033
2033 pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, bw: *std.io.BufferedWriter, location: ValueRenderLocation) !void {2034 pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, bw: *Writer, location: ValueRenderLocation) !void {
2034 switch (self.*) {2035 switch (self.*) {
2035 .c_value => |v| {2036 .c_value => |v| {
2036 try v.f.writeCValue(bw, v.value, location);2037 try v.f.writeCValue(bw, v.value, location);
...@@ -2076,7 +2077,7 @@ pub const DeclGen = struct {...@@ -2076,7 +2077,7 @@ pub const DeclGen = struct {
2076 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))2077 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
2077 fn renderIntCast(2078 fn renderIntCast(
2078 dg: *DeclGen,2079 dg: *DeclGen,
2079 bw: *std.io.BufferedWriter,2080 bw: *Writer,
2080 dest_ty: Type,2081 dest_ty: Type,
2081 context: IntCastContext,2082 context: IntCastContext,
2082 src_ty: Type,2083 src_ty: Type,
...@@ -2160,7 +2161,7 @@ pub const DeclGen = struct {...@@ -2160,7 +2161,7 @@ pub const DeclGen = struct {
2160 ///2161 ///
2161 fn renderTypeAndName(2162 fn renderTypeAndName(
2162 dg: *DeclGen,2163 dg: *DeclGen,
2163 bw: *std.io.BufferedWriter,2164 bw: *Writer,
2164 ty: Type,2165 ty: Type,
2165 name: CValue,2166 name: CValue,
2166 qualifiers: CQualifiers,2167 qualifiers: CQualifiers,
...@@ -2181,7 +2182,7 @@ pub const DeclGen = struct {...@@ -2181,7 +2182,7 @@ pub const DeclGen = struct {
21812182
2182 fn renderCTypeAndName(2183 fn renderCTypeAndName(
2183 dg: *DeclGen,2184 dg: *DeclGen,
2184 bw: *std.io.BufferedWriter,2185 bw: *Writer,
2185 ctype: CType,2186 ctype: CType,
2186 name: CValue,2187 name: CValue,
2187 qualifiers: CQualifiers,2188 qualifiers: CQualifiers,
...@@ -2201,7 +2202,7 @@ pub const DeclGen = struct {...@@ -2201,7 +2202,7 @@ pub const DeclGen = struct {
2201 try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, bw, ctype, .suffix, .{});2202 try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, bw, ctype, .suffix, .{});
2202 }2203 }
22032204
2204 fn writeName(dg: *DeclGen, bw: *std.io.BufferedWriter, c_value: CValue) !void {2205 fn writeName(dg: *DeclGen, bw: *Writer, c_value: CValue) !void {
2205 switch (c_value) {2206 switch (c_value) {
2206 .new_local, .local => |i| try bw.print("t{d}", .{i}),2207 .new_local, .local => |i| try bw.print("t{d}", .{i}),
2207 .constant => |uav| try renderUavName(bw, uav),2208 .constant => |uav| try renderUavName(bw, uav),
...@@ -2211,7 +2212,7 @@ pub const DeclGen = struct {...@@ -2211,7 +2212,7 @@ pub const DeclGen = struct {
2211 }2212 }
2212 }2213 }
22132214
2214 fn writeCValue(dg: *DeclGen, bw: *std.io.BufferedWriter, c_value: CValue) Error!void {2215 fn writeCValue(dg: *DeclGen, bw: *Writer, c_value: CValue) Error!void {
2215 switch (c_value) {2216 switch (c_value) {
2216 .none, .new_local, .local, .local_ref => unreachable,2217 .none, .new_local, .local, .local_ref => unreachable,
2217 .constant => |uav| try renderUavName(bw, uav),2218 .constant => |uav| try renderUavName(bw, uav),
...@@ -2234,7 +2235,7 @@ pub const DeclGen = struct {...@@ -2234,7 +2235,7 @@ pub const DeclGen = struct {
2234 }2235 }
2235 }2236 }
22362237
2237 fn writeCValueDeref(dg: *DeclGen, bw: *std.io.BufferedWriter, c_value: CValue) !void {2238 fn writeCValueDeref(dg: *DeclGen, bw: *Writer, c_value: CValue) !void {
2238 switch (c_value) {2239 switch (c_value) {
2239 .none,2240 .none,
2240 .new_local,2241 .new_local,
...@@ -2263,7 +2264,7 @@ pub const DeclGen = struct {...@@ -2263,7 +2264,7 @@ pub const DeclGen = struct {
22632264
2264 fn writeCValueMember(2265 fn writeCValueMember(
2265 dg: *DeclGen,2266 dg: *DeclGen,
2266 bw: *std.io.BufferedWriter,2267 bw: *Writer,
2267 c_value: CValue,2268 c_value: CValue,
2268 member: CValue,2269 member: CValue,
2269 ) Error!void {2270 ) Error!void {
...@@ -2274,7 +2275,7 @@ pub const DeclGen = struct {...@@ -2274,7 +2275,7 @@ pub const DeclGen = struct {
22742275
2275 fn writeCValueDerefMember(2276 fn writeCValueDerefMember(
2276 dg: *DeclGen,2277 dg: *DeclGen,
2277 bw: *std.io.BufferedWriter,2278 bw: *Writer,
2278 c_value: CValue,2279 c_value: CValue,
2279 member: CValue,2280 member: CValue,
2280 ) !void {2281 ) !void {
...@@ -2341,7 +2342,7 @@ pub const DeclGen = struct {...@@ -2341,7 +2342,7 @@ pub const DeclGen = struct {
2341 try fwd.writeAll(";\n");2342 try fwd.writeAll(";\n");
2342 }2343 }
23432344
2344 fn renderNavName(dg: *DeclGen, bw: *std.io.BufferedWriter, nav_index: InternPool.Nav.Index) !void {2345 fn renderNavName(dg: *DeclGen, bw: *Writer, nav_index: InternPool.Nav.Index) !void {
2345 const zcu = dg.pt.zcu;2346 const zcu = dg.pt.zcu;
2346 const ip = &zcu.intern_pool;2347 const ip = &zcu.intern_pool;
2347 const nav = ip.getNav(nav_index);2348 const nav = ip.getNav(nav_index);
...@@ -2360,15 +2361,15 @@ pub const DeclGen = struct {...@@ -2360,15 +2361,15 @@ pub const DeclGen = struct {
2360 }2361 }
2361 }2362 }
23622363
2363 fn renderUavName(bw: *std.io.BufferedWriter, uav: Value) !void {2364 fn renderUavName(bw: *Writer, uav: Value) !void {
2364 try bw.print("__anon_{d}", .{@intFromEnum(uav.toIntern())});2365 try bw.print("__anon_{d}", .{@intFromEnum(uav.toIntern())});
2365 }2366 }
23662367
2367 fn renderTypeForBuiltinFnName(dg: *DeclGen, bw: *std.io.BufferedWriter, ty: Type) !void {2368 fn renderTypeForBuiltinFnName(dg: *DeclGen, bw: *Writer, ty: Type) !void {
2368 try dg.renderCTypeForBuiltinFnName(bw, try dg.ctypeFromType(ty, .complete));2369 try dg.renderCTypeForBuiltinFnName(bw, try dg.ctypeFromType(ty, .complete));
2369 }2370 }
23702371
2371 fn renderCTypeForBuiltinFnName(dg: *DeclGen, bw: *std.io.BufferedWriter, ctype: CType) !void {2372 fn renderCTypeForBuiltinFnName(dg: *DeclGen, bw: *Writer, ctype: CType) !void {
2372 switch (ctype.info(&dg.ctype_pool)) {2373 switch (ctype.info(&dg.ctype_pool)) {
2373 else => |ctype_info| try bw.print("{c}{d}", .{2374 else => |ctype_info| try bw.print("{c}{d}", .{
2374 if (ctype.isBool())2375 if (ctype.isBool())
...@@ -2387,7 +2388,7 @@ pub const DeclGen = struct {...@@ -2387,7 +2388,7 @@ pub const DeclGen = struct {
2387 }2388 }
2388 }2389 }
23892390
2390 fn renderBuiltinInfo(dg: *DeclGen, bw: *std.io.BufferedWriter, ty: Type, info: BuiltinInfo) !void {2391 fn renderBuiltinInfo(dg: *DeclGen, bw: *Writer, ty: Type, info: BuiltinInfo) !void {
2391 const ctype = try dg.ctypeFromType(ty, .complete);2392 const ctype = try dg.ctypeFromType(ty, .complete);
2392 const is_big = ctype.info(&dg.ctype_pool) == .array;2393 const is_big = ctype.info(&dg.ctype_pool) == .array;
2393 switch (info) {2394 switch (info) {
...@@ -2436,9 +2437,9 @@ const RenderCTypeTrailing = enum {...@@ -2436,9 +2437,9 @@ const RenderCTypeTrailing = enum {
24362437
2437 pub fn format(2438 pub fn format(
2438 self: @This(),2439 self: @This(),
2439 bw: *std.io.BufferedWriter,2440 bw: *Writer,
2440 comptime fmt: []const u8,2441 comptime fmt: []const u8,
2441 ) std.io.Writer.Error!void {2442 ) Writer.Error!void {
2442 if (fmt.len != 0) @compileError("invalid format string '" ++2443 if (fmt.len != 0) @compileError("invalid format string '" ++
2443 fmt ++ "' for type '" ++ @typeName(@This()) ++ "'");2444 fmt ++ "' for type '" ++ @typeName(@This()) ++ "'");
2444 switch (self) {2445 switch (self) {
...@@ -2447,12 +2448,12 @@ const RenderCTypeTrailing = enum {...@@ -2447,12 +2448,12 @@ const RenderCTypeTrailing = enum {
2447 }2448 }
2448 }2449 }
2449};2450};
2450fn renderAlignedTypeName(bw: *std.io.BufferedWriter, ctype: CType) !void {2451fn renderAlignedTypeName(bw: *Writer, ctype: CType) !void {
2451 try bw.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});2452 try bw.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});
2452}2453}
2453fn renderFwdDeclTypeName(2454fn renderFwdDeclTypeName(
2454 zcu: *Zcu,2455 zcu: *Zcu,
2455 bw: *std.io.BufferedWriter,2456 bw: *Writer,
2456 ctype: CType,2457 ctype: CType,
2457 fwd_decl: CType.Info.FwdDecl,2458 fwd_decl: CType.Info.FwdDecl,
2458 attributes: []const u8,2459 attributes: []const u8,
...@@ -2471,11 +2472,11 @@ fn renderTypePrefix(...@@ -2471,11 +2472,11 @@ fn renderTypePrefix(
2471 pass: DeclGen.Pass,2472 pass: DeclGen.Pass,
2472 ctype_pool: *const CType.Pool,2473 ctype_pool: *const CType.Pool,
2473 zcu: *Zcu,2474 zcu: *Zcu,
2474 bw: *std.io.BufferedWriter,2475 bw: *Writer,
2475 ctype: CType,2476 ctype: CType,
2476 parent_fix: CTypeFix,2477 parent_fix: CTypeFix,
2477 qualifiers: CQualifiers,2478 qualifiers: CQualifiers,
2478) std.io.Writer.Error!RenderCTypeTrailing {2479) Writer.Error!RenderCTypeTrailing {
2479 var trailing = RenderCTypeTrailing.maybe_space;2480 var trailing = RenderCTypeTrailing.maybe_space;
2480 switch (ctype.info(ctype_pool)) {2481 switch (ctype.info(ctype_pool)) {
2481 .basic => |basic_info| try bw.writeAll(@tagName(basic_info)),2482 .basic => |basic_info| try bw.writeAll(@tagName(basic_info)),
...@@ -2588,11 +2589,11 @@ fn renderTypeSuffix(...@@ -2588,11 +2589,11 @@ fn renderTypeSuffix(
2588 pass: DeclGen.Pass,2589 pass: DeclGen.Pass,
2589 ctype_pool: *const CType.Pool,2590 ctype_pool: *const CType.Pool,
2590 zcu: *Zcu,2591 zcu: *Zcu,
2591 bw: *std.io.BufferedWriter,2592 bw: *Writer,
2592 ctype: CType,2593 ctype: CType,
2593 parent_fix: CTypeFix,2594 parent_fix: CTypeFix,
2594 qualifiers: CQualifiers,2595 qualifiers: CQualifiers,
2595) std.io.Writer.Error!void {2596) Writer.Error!void {
2596 switch (ctype.info(ctype_pool)) {2597 switch (ctype.info(ctype_pool)) {
2597 .basic, .aligned, .fwd_decl, .aggregate => {},2598 .basic, .aligned, .fwd_decl, .aggregate => {},
2598 .pointer => |pointer_info| try renderTypeSuffix(2599 .pointer => |pointer_info| try renderTypeSuffix(
...@@ -2644,7 +2645,7 @@ fn renderTypeSuffix(...@@ -2644,7 +2645,7 @@ fn renderTypeSuffix(
2644}2645}
2645fn renderFields(2646fn renderFields(
2646 zcu: *Zcu,2647 zcu: *Zcu,
2647 bw: *std.io.BufferedWriter,2648 bw: *Writer,
2648 ctype_pool: *const CType.Pool,2649 ctype_pool: *const CType.Pool,
2649 aggregate_info: CType.Info.Aggregate,2650 aggregate_info: CType.Info.Aggregate,
2650 indent: usize,2651 indent: usize,
...@@ -2686,7 +2687,7 @@ fn renderFields(...@@ -2686,7 +2687,7 @@ fn renderFields(
26862687
2687pub fn genTypeDecl(2688pub fn genTypeDecl(
2688 zcu: *Zcu,2689 zcu: *Zcu,
2689 bw: *std.io.BufferedWriter,2690 bw: *Writer,
2690 global_ctype_pool: *const CType.Pool,2691 global_ctype_pool: *const CType.Pool,
2691 global_ctype: CType,2692 global_ctype: CType,
2692 pass: DeclGen.Pass,2693 pass: DeclGen.Pass,
...@@ -2766,7 +2767,7 @@ pub fn genTypeDecl(...@@ -2766,7 +2767,7 @@ pub fn genTypeDecl(
2766 }2767 }
2767}2768}
27682769
2769pub fn genGlobalAsm(zcu: *Zcu, bw: *std.io.BufferedWriter) !void {2770pub fn genGlobalAsm(zcu: *Zcu, bw: *Writer) !void {
2770 for (zcu.global_assembly.values()) |asm_source| {2771 for (zcu.global_assembly.values()) |asm_source| {
2771 try bw.print("__asm({fs});\n", .{fmtStringLiteral(asm_source, null)});2772 try bw.print("__asm({fs});\n", .{fmtStringLiteral(asm_source, null)});
2772 }2773 }
...@@ -5247,7 +5248,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5247,7 +5248,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5247 return local;5248 return local;
5248}5249}
52495250
5250fn airTrap(f: *Function, bw: *std.io.BufferedWriter) !void {5251fn airTrap(f: *Function, bw: *Writer) !void {
5251 // Not even allowed to call trap in a naked function.5252 // Not even allowed to call trap in a naked function.
5252 if (f.object.dg.is_naked_fn) return;5253 if (f.object.dg.is_naked_fn) return;
5253 try bw.writeAll("zig_trap();\n");5254 try bw.writeAll("zig_trap();\n");
...@@ -7052,7 +7053,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -7052,7 +7053,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
7052 return .none;7053 return .none;
7053}7054}
70547055
7055fn writeSliceOrPtr(f: *Function, bw: *std.io.BufferedWriter, ptr: CValue, ptr_ty: Type) !void {7056fn writeSliceOrPtr(f: *Function, bw: *Writer, ptr: CValue, ptr_ty: Type) !void {
7056 const pt = f.object.dg.pt;7057 const pt = f.object.dg.pt;
7057 const zcu = pt.zcu;7058 const zcu = pt.zcu;
7058 if (ptr_ty.isSlice(zcu)) {7059 if (ptr_ty.isSlice(zcu)) {
...@@ -7980,7 +7981,7 @@ fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {...@@ -7980,7 +7981,7 @@ fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
7980 };7981 };
7981}7982}
79827983
7983fn writeMemoryOrder(bw: *std.io.BufferedWriter, order: std.builtin.AtomicOrder) !void {7984fn writeMemoryOrder(bw: *Writer, order: std.builtin.AtomicOrder) !void {
7984 return bw.writeAll(toMemoryOrder(order));7985 return bw.writeAll(toMemoryOrder(order));
7985}7986}
79867987
...@@ -8125,7 +8126,7 @@ const StringLiteral = struct {...@@ -8125,7 +8126,7 @@ const StringLiteral = struct {
8125 len: usize,8126 len: usize,
8126 cur_len: usize,8127 cur_len: usize,
8127 start_count: usize,8128 start_count: usize,
8128 bw: *std.io.BufferedWriter,8129 bw: *Writer,
81298130
8130 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,8131 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
8131 // regardless of the length of the string literal initializing it. Array initializer syntax is8132 // regardless of the length of the string literal initializing it. Array initializer syntax is
...@@ -8138,7 +8139,7 @@ const StringLiteral = struct {...@@ -8138,7 +8139,7 @@ const StringLiteral = struct {
8138 const max_char_len = 4;8139 const max_char_len = 4;
8139 const max_literal_len = @min(16380 - max_char_len, 4095);8140 const max_literal_len = @min(16380 - max_char_len, 4095);
81408141
8141 fn init(bw: *std.io.BufferedWriter, len: usize) StringLiteral {8142 fn init(bw: *Writer, len: usize) StringLiteral {
8142 return .{8143 return .{
8143 .cur_len = 0,8144 .cur_len = 0,
8144 .len = len,8145 .len = len,
...@@ -8147,7 +8148,7 @@ const StringLiteral = struct {...@@ -8147,7 +8148,7 @@ const StringLiteral = struct {
8147 };8148 };
8148 }8149 }
81498150
8150 pub fn start(sl: *StringLiteral) std.io.Writer.Error!void {8151 pub fn start(sl: *StringLiteral) Writer.Error!void {
8151 if (sl.len <= max_string_initializer_len) {8152 if (sl.len <= max_string_initializer_len) {
8152 try sl.bw.writeByte('\"');8153 try sl.bw.writeByte('\"');
8153 } else {8154 } else {
...@@ -8155,7 +8156,7 @@ const StringLiteral = struct {...@@ -8155,7 +8156,7 @@ const StringLiteral = struct {
8155 }8156 }
8156 }8157 }
81578158
8158 pub fn end(sl: *StringLiteral) std.io.Writer.Error!void {8159 pub fn end(sl: *StringLiteral) Writer.Error!void {
8159 if (sl.len <= max_string_initializer_len) {8160 if (sl.len <= max_string_initializer_len) {
8160 try sl.bw.writeByte('\"');8161 try sl.bw.writeByte('\"');
8161 } else {8162 } else {
...@@ -8163,7 +8164,7 @@ const StringLiteral = struct {...@@ -8163,7 +8164,7 @@ const StringLiteral = struct {
8163 }8164 }
8164 }8165 }
81658166
8166 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void {8167 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) Writer.Error!void {
8167 switch (c) {8168 switch (c) {
8168 7 => try sl.bw.writeAll("\\a"),8169 7 => try sl.bw.writeAll("\\a"),
8169 8 => try sl.bw.writeAll("\\b"),8170 8 => try sl.bw.writeAll("\\b"),
...@@ -8180,7 +8181,7 @@ const StringLiteral = struct {...@@ -8180,7 +8181,7 @@ const StringLiteral = struct {
8180 }8181 }
8181 }8182 }
81828183
8183 pub fn writeChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void {8184 pub fn writeChar(sl: *StringLiteral, c: u8) Writer.Error!void {
8184 if (sl.len <= max_string_initializer_len) {8185 if (sl.len <= max_string_initializer_len) {
8185 if (sl.cur_len == 0 and sl.bw.count - sl.start_count > 1)8186 if (sl.cur_len == 0 and sl.bw.count - sl.start_count > 1)
8186 try sl.bw.writeAll("\"\"");8187 try sl.bw.writeAll("\"\"");
...@@ -8202,9 +8203,9 @@ const StringLiteral = struct {...@@ -8202,9 +8203,9 @@ const StringLiteral = struct {
8202const FormatStringContext = struct { str: []const u8, sentinel: ?u8 };8203const FormatStringContext = struct { str: []const u8, sentinel: ?u8 };
8203fn formatStringLiteral(8204fn formatStringLiteral(
8204 data: FormatStringContext,8205 data: FormatStringContext,
8205 bw: *std.io.BufferedWriter,8206 bw: *Writer,
8206 comptime fmt: []const u8,8207 comptime fmt: []const u8,
8207) std.io.Writer.Error!void {8208) Writer.Error!void {
8208 if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt);8209 if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt);
82098210
8210 var literal: StringLiteral = .init(bw, data.str.len + @intFromBool(data.sentinel != null));8211 var literal: StringLiteral = .init(bw, data.str.len + @intFromBool(data.sentinel != null));
...@@ -8233,9 +8234,9 @@ const FormatIntLiteralContext = struct {...@@ -8233,9 +8234,9 @@ const FormatIntLiteralContext = struct {
8233};8234};
8234fn formatIntLiteral(8235fn formatIntLiteral(
8235 data: FormatIntLiteralContext,8236 data: FormatIntLiteralContext,
8236 bw: *std.io.BufferedWriter,8237 bw: *Writer,
8237 comptime fmt: []const u8,8238 comptime fmt: []const u8,
8238) std.io.Writer.Error!void {8239) Writer.Error!void {
8239 const pt = data.dg.pt;8240 const pt = data.dg.pt;
8240 const zcu = pt.zcu;8241 const zcu = pt.zcu;
8241 const target = &data.dg.mod.resolved_target.result;8242 const target = &data.dg.mod.resolved_target.result;
...@@ -8423,7 +8424,7 @@ const Materialize = struct {...@@ -8423,7 +8424,7 @@ const Materialize = struct {
8423 } };8424 } };
8424 }8425 }
84258426
8426 pub fn mat(self: Materialize, f: *Function, bw: *std.io.BufferedWriter) !void {8427 pub fn mat(self: Materialize, f: *Function, bw: *Writer) !void {
8427 try f.writeCValue(bw, self.local, .Other);8428 try f.writeCValue(bw, self.local, .Other);
8428 }8429 }
84298430
...@@ -8435,27 +8436,27 @@ const Materialize = struct {...@@ -8435,27 +8436,27 @@ const Materialize = struct {
8435const Assignment = struct {8436const Assignment = struct {
8436 ctype: CType,8437 ctype: CType,
84378438
8438 pub fn start(f: *Function, bw: *std.io.BufferedWriter, ctype: CType) !Assignment {8439 pub fn start(f: *Function, bw: *Writer, ctype: CType) !Assignment {
8439 const self: Assignment = .{ .ctype = ctype };8440 const self: Assignment = .{ .ctype = ctype };
8440 try self.restart(f, bw);8441 try self.restart(f, bw);
8441 return self;8442 return self;
8442 }8443 }
84438444
8444 pub fn restart(self: Assignment, f: *Function, bw: *std.io.BufferedWriter) !void {8445 pub fn restart(self: Assignment, f: *Function, bw: *Writer) !void {
8445 switch (self.strategy(f)) {8446 switch (self.strategy(f)) {
8446 .assign => {},8447 .assign => {},
8447 .memcpy => try bw.writeAll("memcpy("),8448 .memcpy => try bw.writeAll("memcpy("),
8448 }8449 }
8449 }8450 }
84508451
8451 pub fn assign(self: Assignment, f: *Function, bw: *std.io.BufferedWriter) !void {8452 pub fn assign(self: Assignment, f: *Function, bw: *Writer) !void {
8452 switch (self.strategy(f)) {8453 switch (self.strategy(f)) {
8453 .assign => try bw.writeAll(" = "),8454 .assign => try bw.writeAll(" = "),
8454 .memcpy => try bw.writeAll(", "),8455 .memcpy => try bw.writeAll(", "),
8455 }8456 }
8456 }8457 }
84578458
8458 pub fn end(self: Assignment, f: *Function, bw: *std.io.BufferedWriter) !void {8459 pub fn end(self: Assignment, f: *Function, bw: *Writer) !void {
8459 switch (self.strategy(f)) {8460 switch (self.strategy(f)) {
8460 .assign => {},8461 .assign => {},
8461 .memcpy => {8462 .memcpy => {
...@@ -8479,7 +8480,7 @@ const Assignment = struct {...@@ -8479,7 +8480,7 @@ const Assignment = struct {
8479const Vectorize = struct {8480const Vectorize = struct {
8480 index: CValue = .none,8481 index: CValue = .none,
84818482
8482 pub fn start(f: *Function, inst: Air.Inst.Index, writer: *std.io.BufferedWriter, ty: Type) !Vectorize {8483 pub fn start(f: *Function, inst: Air.Inst.Index, writer: *Writer, ty: Type) !Vectorize {
8483 const pt = f.object.dg.pt;8484 const pt = f.object.dg.pt;
8484 const zcu = pt.zcu;8485 const zcu = pt.zcu;
8485 return if (ty.zigTypeTag(zcu) == .vector) index: {8486 return if (ty.zigTypeTag(zcu) == .vector) index: {
...@@ -8499,7 +8500,7 @@ const Vectorize = struct {...@@ -8499,7 +8500,7 @@ const Vectorize = struct {
8499 } else .{};8500 } else .{};
8500 }8501 }
85018502
8502 pub fn elem(self: Vectorize, f: *Function, bw: *std.io.BufferedWriter) !void {8503 pub fn elem(self: Vectorize, f: *Function, bw: *Writer) !void {
8503 if (self.index != .none) {8504 if (self.index != .none) {
8504 try bw.writeByte('[');8505 try bw.writeByte('[');
8505 try f.writeCValue(bw, self.index, .Other);8506 try f.writeCValue(bw, self.index, .Other);
...@@ -8507,7 +8508,7 @@ const Vectorize = struct {...@@ -8507,7 +8508,7 @@ const Vectorize = struct {
8507 }8508 }
8508 }8509 }
85098510
8510 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, bw: *std.io.BufferedWriter) !void {8511 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, bw: *Writer) !void {
8511 if (self.index != .none) {8512 if (self.index != .none) {
8512 try f.object.outdent();8513 try f.object.outdent();
8513 try bw.writeByte('}');8514 try bw.writeByte('}');
src/codegen/c/Type.zig+8-6
...@@ -209,7 +209,7 @@ pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {...@@ -209,7 +209,7 @@ pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {
209 };209 };
210}210}
211211
212pub fn renderLiteralPrefix(ctype: CType, bw: *std.io.BufferedWriter, kind: Kind, pool: *const Pool) std.io.Writer.Error!void {212pub fn renderLiteralPrefix(ctype: CType, bw: *Writer, kind: Kind, pool: *const Pool) Writer.Error!void {
213 switch (ctype.info(pool)) {213 switch (ctype.info(pool)) {
214 .basic => |basic_info| switch (basic_info) {214 .basic => |basic_info| switch (basic_info) {
215 .void => unreachable,215 .void => unreachable,
...@@ -270,7 +270,7 @@ pub fn renderLiteralPrefix(ctype: CType, bw: *std.io.BufferedWriter, kind: Kind,...@@ -270,7 +270,7 @@ pub fn renderLiteralPrefix(ctype: CType, bw: *std.io.BufferedWriter, kind: Kind,
270 }270 }
271}271}
272272
273pub fn renderLiteralSuffix(ctype: CType, bw: *std.io.BufferedWriter, pool: *const Pool) std.io.Writer.Error!void {273pub fn renderLiteralSuffix(ctype: CType, bw: *Writer, pool: *const Pool) Writer.Error!void {
274 switch (ctype.info(pool)) {274 switch (ctype.info(pool)) {
275 .basic => |basic_info| switch (basic_info) {275 .basic => |basic_info| switch (basic_info) {
276 .void => unreachable,276 .void => unreachable,
...@@ -940,10 +940,10 @@ pub const Pool = struct {...@@ -940,10 +940,10 @@ pub const Pool = struct {
940 const FormatData = struct { string: String, pool: *const Pool };940 const FormatData = struct { string: String, pool: *const Pool };
941 fn format(941 fn format(
942 data: FormatData,942 data: FormatData,
943 bw: *std.io.BufferedWriter,943 bw: *Writer,
944 comptime fmt_str: []const u8,944 comptime fmt_str: []const u8,
945 ) std.io.Writer.Error!void {945 ) Writer.Error!void {
946 if (fmt_str.len > 0) @compileError("invalid format string '" ++ fmt_str ++ "'");946 comptime assert(fmt_str.len == 0);
947 if (data.string.toSlice(data.pool)) |slice|947 if (data.string.toSlice(data.pool)) |slice|
948 try bw.writeAll(slice)948 try bw.writeAll(slice)
949 else949 else
...@@ -3280,10 +3280,12 @@ pub const AlignAs = packed struct {...@@ -3280,10 +3280,12 @@ pub const AlignAs = packed struct {
3280 }3280 }
3281};3281};
32823282
3283const std = @import("std");
3283const assert = std.debug.assert;3284const assert = std.debug.assert;
3285const Writer = std.io.Writer;
3286
3284const CType = @This();3287const CType = @This();
3285const InternPool = @import("../../InternPool.zig");3288const InternPool = @import("../../InternPool.zig");
3286const Module = @import("../../Package/Module.zig");3289const Module = @import("../../Package/Module.zig");
3287const std = @import("std");
3288const Type = @import("../../Type.zig");3290const Type = @import("../../Type.zig");
3289const Zcu = @import("../../Zcu.zig");3291const Zcu = @import("../../Zcu.zig");
src/codegen/spirv/spec.zig+2-1
...@@ -18,7 +18,8 @@ pub const IdResult = enum(Word) {...@@ -18,7 +18,8 @@ pub const IdResult = enum(Word) {
18 none,18 none,
19 _,19 _,
2020
21 pub fn format(self: IdResult, bw: *std.io.BufferedWriter, comptime _: []const u8) std.io.Writer.Error!void {21 pub fn format(self: IdResult, bw: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
22 comptime std.debug.assert(fmt.len == 0);
22 switch (self) {23 switch (self) {
23 .none => try bw.writeAll("(none)"),24 .none => try bw.writeAll("(none)"),
24 else => try bw.print("%{}", .{@intFromEnum(self)}),25 else => try bw.print("%{}", .{@intFromEnum(self)}),
src/fmt.zig+19-18
...@@ -1,3 +1,12 @@...@@ -1,3 +1,12 @@
1const std = @import("std");
2const mem = std.mem;
3const fs = std.fs;
4const process = std.process;
5const Allocator = std.mem.Allocator;
6const Color = std.zig.Color;
7const fatal = std.process.fatal;
8const File = std.fs.File;
9
1const usage_fmt =10const usage_fmt =
2 \\Usage: zig fmt [file]...11 \\Usage: zig fmt [file]...
3 \\12 \\
...@@ -27,7 +36,7 @@ const Fmt = struct {...@@ -27,7 +36,7 @@ const Fmt = struct {
27 gpa: Allocator,36 gpa: Allocator,
28 arena: Allocator,37 arena: Allocator,
29 out_buffer: std.ArrayListUnmanaged(u8),38 out_buffer: std.ArrayListUnmanaged(u8),
30 stdout: *std.io.BufferedWriter,39 stdout_writer: *File.Writer,
3140
32 const SeenMap = std.AutoHashMap(fs.File.INode, void);41 const SeenMap = std.AutoHashMap(fs.File.INode, void);
33};42};
...@@ -49,7 +58,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -49,7 +58,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
49 const arg = args[i];58 const arg = args[i];
50 if (mem.startsWith(u8, arg, "-")) {59 if (mem.startsWith(u8, arg, "-")) {
51 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {60 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
52 try std.fs.File.stdout().writeAll(usage_fmt);61 try File.stdout().writeAll(usage_fmt);
53 return process.cleanExit();62 return process.cleanExit();
54 } else if (mem.eql(u8, arg, "--color")) {63 } else if (mem.eql(u8, arg, "--color")) {
55 if (i + 1 >= args.len) {64 if (i + 1 >= args.len) {
...@@ -133,10 +142,9 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -133,10 +142,9 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
133 try std.zig.printAstErrorsToStderr(gpa, tree, "<stdin>", color);142 try std.zig.printAstErrorsToStderr(gpa, tree, "<stdin>", color);
134 process.exit(2);143 process.exit(2);
135 }144 }
136 var aw: std.io.AllocatingWriter = undefined;145 var aw: std.io.AllocatingWriter = .init(gpa);
137 aw.init(gpa);
138 defer aw.deinit();146 defer aw.deinit();
139 try tree.render(gpa, &aw.buffered_writer, .{});147 try tree.render(gpa, &aw.interface, .{});
140 const formatted = aw.getWritten();148 const formatted = aw.getWritten();
141149
142 if (check_flag) {150 if (check_flag) {
...@@ -144,7 +152,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -144,7 +152,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
144 process.exit(code);152 process.exit(code);
145 }153 }
146154
147 return std.fs.File.stdout().writeAll(formatted);155 return File.stdout().writeAll(formatted);
148 }156 }
149157
150 if (input_files.items.len == 0) {158 if (input_files.items.len == 0) {
...@@ -152,7 +160,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -152,7 +160,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
152 }160 }
153161
154 var stdout_buffer: [4096]u8 = undefined;162 var stdout_buffer: [4096]u8 = undefined;
155 var stdout: std.io.BufferedWriter = std.fs.File.stdout().writer().buffered(&stdout_buffer);163 var stdout_writer = File.stdout().writer(&stdout_buffer);
156164
157 var fmt: Fmt = .{165 var fmt: Fmt = .{
158 .gpa = gpa,166 .gpa = gpa,
...@@ -163,7 +171,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -163,7 +171,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
163 .force_zon = force_zon,171 .force_zon = force_zon,
164 .color = color,172 .color = color,
165 .out_buffer = .empty,173 .out_buffer = .empty,
166 .stdout = &stdout,174 .stdout_writer = &stdout_writer,
167 };175 };
168 defer fmt.seen.deinit();176 defer fmt.seen.deinit();
169 defer fmt.out_buffer.deinit(gpa);177 defer fmt.out_buffer.deinit(gpa);
...@@ -190,6 +198,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -190,6 +198,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
190 if (fmt.any_error) {198 if (fmt.any_error) {
191 process.exit(1);199 process.exit(1);
192 }200 }
201 try fmt.stdout_writer.flush();
193}202}
194203
195fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) anyerror!void {204fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) anyerror!void {
...@@ -336,7 +345,7 @@ fn fmtPathFile(...@@ -336,7 +345,7 @@ fn fmtPathFile(
336 return;345 return;
337346
338 if (check_mode) {347 if (check_mode) {
339 try fmt.stdout.print("{s}\n", .{file_path});348 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
340 fmt.any_error = true;349 fmt.any_error = true;
341 } else {350 } else {
342 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });351 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });
...@@ -344,18 +353,10 @@ fn fmtPathFile(...@@ -344,18 +353,10 @@ fn fmtPathFile(
344353
345 try af.file.writeAll(fmt.out_buffer.items);354 try af.file.writeAll(fmt.out_buffer.items);
346 try af.finish();355 try af.finish();
347 try fmt.stdout.print("{s}\n", .{file_path});356 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
348 }357 }
349}358}
350359
351const std = @import("std");
352const mem = std.mem;
353const fs = std.fs;
354const process = std.process;
355const Allocator = std.mem.Allocator;
356const Color = std.zig.Color;
357const fatal = std.process.fatal;
358
359/// Provided for debugging/testing purposes; unused by the compiler.360/// Provided for debugging/testing purposes; unused by the compiler.
360pub fn main() !void {361pub fn main() !void {
361 const gpa = std.heap.smp_allocator;362 const gpa = std.heap.smp_allocator;
src/link/Coff.zig+39-39
...@@ -1,5 +1,41 @@...@@ -1,5 +1,41 @@
1//! The main driver of the self-hosted COFF linker.1//! The main driver of the self-hosted COFF linker.
22
3const Coff = @This();
4
5const std = @import("std");
6const build_options = @import("build_options");
7const builtin = @import("builtin");
8const assert = std.debug.assert;
9const coff_util = std.coff;
10const fmt = std.fmt;
11const fs = std.fs;
12const log = std.log.scoped(.link);
13const math = std.math;
14const mem = std.mem;
15
16const Allocator = std.mem.Allocator;
17const Path = std.Build.Cache.Path;
18const Directory = std.Build.Cache.Directory;
19const Cache = std.Build.Cache;
20const Writer = std.io.Writer;
21
22const aarch64_util = @import("../arch/aarch64/bits.zig");
23const allocPrint = std.fmt.allocPrint;
24const codegen = @import("../codegen.zig");
25const link = @import("../link.zig");
26const target_util = @import("../target.zig");
27const trace = @import("../tracy.zig").trace;
28
29const Compilation = @import("../Compilation.zig");
30const Zcu = @import("../Zcu.zig");
31const InternPool = @import("../InternPool.zig");
32const TableSection = @import("table_section.zig").TableSection;
33const StringTable = @import("StringTable.zig");
34const Type = @import("../Type.zig");
35const Value = @import("../Value.zig");
36const AnalUnit = InternPool.AnalUnit;
37const dev = @import("../dev.zig");
38
3base: link.File,39base: link.File,
4image_base: u64,40image_base: u64,
5/// TODO this and minor_subsystem_version should be combined into one property and left as41/// TODO this and minor_subsystem_version should be combined into one property and left as
...@@ -2175,8 +2211,7 @@ fn writeDataDirectoriesHeaders(coff: *Coff) !void {...@@ -2175,8 +2211,7 @@ fn writeDataDirectoriesHeaders(coff: *Coff) !void {
2175fn writeHeader(coff: *Coff) !void {2211fn writeHeader(coff: *Coff) !void {
2176 const target = &coff.base.comp.root_mod.resolved_target.result;2212 const target = &coff.base.comp.root_mod.resolved_target.result;
2177 const gpa = coff.base.comp.gpa;2213 const gpa = coff.base.comp.gpa;
2178 var bw: std.io.BufferedWriter = undefined;2214 var bw: Writer = .fixed(try gpa.alloc(u8, coff.getSizeOfHeaders()));
2179 bw.initFixed(try gpa.alloc(u8, coff.getSizeOfHeaders()));
2180 defer gpa.free(bw.buffer);2215 defer gpa.free(bw.buffer);
21812216
2182 bw.writeAll(&msdos_stub) catch unreachable;2217 bw.writeAll(&msdos_stub) catch unreachable;
...@@ -3066,14 +3101,14 @@ const ImportTable = struct {...@@ -3066,14 +3101,14 @@ const ImportTable = struct {
3066 ctx: Context,3101 ctx: Context,
3067 };3102 };
30683103
3069 fn format(itab: ImportTable, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {3104 fn format(itab: ImportTable, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
3070 _ = itab;3105 _ = itab;
3071 _ = bw;3106 _ = bw;
3072 _ = unused_format_string;3107 _ = unused_format_string;
3073 @compileError("do not format ImportTable directly; use itab.fmtDebug()");3108 @compileError("do not format ImportTable directly; use itab.fmtDebug()");
3074 }3109 }
30753110
3076 fn format2(fmt_ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {3111 fn format2(fmt_ctx: FormatContext, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
3077 comptime assert(unused_format_string.len == 0);3112 comptime assert(unused_format_string.len == 0);
3078 const lib_name = fmt_ctx.ctx.coff.temp_strtab.getAssumeExists(fmt_ctx.ctx.name_off);3113 const lib_name = fmt_ctx.ctx.coff.temp_strtab.getAssumeExists(fmt_ctx.ctx.name_off);
3079 const base_vaddr = getBaseAddress(fmt_ctx.ctx);3114 const base_vaddr = getBaseAddress(fmt_ctx.ctx);
...@@ -3105,41 +3140,6 @@ fn pwriteAll(coff: *Coff, bytes: []const u8, offset: u64) error{LinkFailure}!voi...@@ -3105,41 +3140,6 @@ fn pwriteAll(coff: *Coff, bytes: []const u8, offset: u64) error{LinkFailure}!voi
3105 };3140 };
3106}3141}
31073142
3108const Coff = @This();
3109
3110const std = @import("std");
3111const build_options = @import("build_options");
3112const builtin = @import("builtin");
3113const assert = std.debug.assert;
3114const coff_util = std.coff;
3115const fmt = std.fmt;
3116const fs = std.fs;
3117const log = std.log.scoped(.link);
3118const math = std.math;
3119const mem = std.mem;
3120
3121const Allocator = std.mem.Allocator;
3122const Path = std.Build.Cache.Path;
3123const Directory = std.Build.Cache.Directory;
3124const Cache = std.Build.Cache;
3125
3126const aarch64_util = @import("../arch/aarch64/bits.zig");
3127const allocPrint = std.fmt.allocPrint;
3128const codegen = @import("../codegen.zig");
3129const link = @import("../link.zig");
3130const target_util = @import("../target.zig");
3131const trace = @import("../tracy.zig").trace;
3132
3133const Compilation = @import("../Compilation.zig");
3134const Zcu = @import("../Zcu.zig");
3135const InternPool = @import("../InternPool.zig");
3136const TableSection = @import("table_section.zig").TableSection;
3137const StringTable = @import("StringTable.zig");
3138const Type = @import("../Type.zig");
3139const Value = @import("../Value.zig");
3140const AnalUnit = InternPool.AnalUnit;
3141const dev = @import("../dev.zig");
3142
3143/// This is the start of a Portable Executable (PE) file.3143/// This is the start of a Portable Executable (PE) file.
3144/// It starts with a MS-DOS header followed by a MS-DOS stub program.3144/// It starts with a MS-DOS header followed by a MS-DOS stub program.
3145/// This data does not change so we include it as follows in all binaries.3145/// This data does not change so we include it as follows in all binaries.
src/link/Dwarf.zig+21-25
...@@ -648,8 +648,7 @@ const Unit = struct {...@@ -648,8 +648,7 @@ const Unit = struct {
648 assert(len >= unit.trailer_len);648 assert(len >= unit.trailer_len);
649 if (sec == &dwarf.debug_line.section) {649 if (sec == &dwarf.debug_line.section) {
650 var buf: [1 + uleb128Bytes(std.math.maxInt(u32)) + 1]u8 = undefined;650 var buf: [1 + uleb128Bytes(std.math.maxInt(u32)) + 1]u8 = undefined;
651 var bw: std.io.BufferedWriter = undefined;651 var bw: Writer = .fixed(&buf);
652 bw.initFixed(&buf);
653 bw.writeByte(DW.LNS.extended_op) catch unreachable;652 bw.writeByte(DW.LNS.extended_op) catch unreachable;
654 const extended_op_bytes = bw.end;653 const extended_op_bytes = bw.end;
655 var op_len_bytes: u5 = 1;654 var op_len_bytes: u5 = 1;
...@@ -668,8 +667,7 @@ const Unit = struct {...@@ -668,8 +667,7 @@ const Unit = struct {
668 assert(bw.end >= unit.trailer_len and bw.end <= len);667 assert(bw.end >= unit.trailer_len and bw.end <= len);
669 return dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + start);668 return dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + start);
670 }669 }
671 var trailer_bw: std.io.BufferedWriter = undefined;670 var trailer_bw: Writer = .fixed(try dwarf.gpa.alloc(u8, len));
672 trailer_bw.initFixed(try dwarf.gpa.alloc(u8, len));
673 defer dwarf.gpa.free(trailer_bw.buffer);671 defer dwarf.gpa.free(trailer_bw.buffer);
674 const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: {672 const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: {
675 assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);673 assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);
...@@ -833,8 +831,7 @@ const Entry = struct {...@@ -833,8 +831,7 @@ const Entry = struct {
833 1 + uleb128Bytes(std.math.maxInt(u32)) + 1,831 1 + uleb128Bytes(std.math.maxInt(u32)) + 1,
834 )832 )
835 ]u8 = undefined;833 ]u8 = undefined;
836 var bw: std.io.BufferedWriter = undefined;834 var bw: Writer = .fixed(&buf);
837 bw.initFixed(&buf);
838 if (sec == &dwarf.debug_info.section) switch (len) {835 if (sec == &dwarf.debug_info.section) switch (len) {
839 0 => {},836 0 => {},
840 1 => bw.writeLeb128(try dwarf.refAbbrevCode(.pad_1)) catch unreachable,837 1 => bw.writeLeb128(try dwarf.refAbbrevCode(.pad_1)) catch unreachable,
...@@ -1134,7 +1131,7 @@ pub const Loc = union(enum) {...@@ -1134,7 +1131,7 @@ pub const Loc = union(enum) {
1134 };1131 };
1135 }1132 }
11361133
1137 fn writeReg(bw: *std.io.BufferedWriter, reg: u32, op0: u8, opx: u8) std.io.Writer.Error!void {1134 fn writeReg(bw: *Writer, reg: u32, op0: u8, opx: u8) Writer.Error!void {
1138 if (std.math.cast(u5, reg)) |small_reg| {1135 if (std.math.cast(u5, reg)) |small_reg| {
1139 try bw.writeByte(op0 + small_reg);1136 try bw.writeByte(op0 + small_reg);
1140 } else {1137 } else {
...@@ -1143,7 +1140,7 @@ pub const Loc = union(enum) {...@@ -1143,7 +1140,7 @@ pub const Loc = union(enum) {
1143 }1140 }
1144 }1141 }
11451142
1146 fn write(loc: Loc, bw: *std.io.BufferedWriter, adapter: anytype) UpdateError!void {1143 fn write(loc: Loc, bw: *Writer, adapter: anytype) UpdateError!void {
1147 switch (loc) {1144 switch (loc) {
1148 .empty => {},1145 .empty => {},
1149 .addr_reloc => |sym_index| {1146 .addr_reloc => |sym_index| {
...@@ -1795,10 +1792,10 @@ pub const WipNav = struct {...@@ -1795,10 +1792,10 @@ pub const WipNav = struct {
1795 fn endian(_: ExprLocCounter) std.builtin.Endian {1792 fn endian(_: ExprLocCounter) std.builtin.Endian {
1796 return @import("builtin").cpu.arch.endian();1793 return @import("builtin").cpu.arch.endian();
1797 }1794 }
1798 fn addrSym(counter: ExprLocCounter, bw: *std.io.BufferedWriter, _: u32) error{}!void {1795 fn addrSym(counter: ExprLocCounter, bw: *Writer, _: u32) error{}!void {
1799 bw.count += @intFromEnum(counter.address_size);1796 bw.count += @intFromEnum(counter.address_size);
1800 }1797 }
1801 fn infoEntry(counter: ExprLocCounter, bw: *std.io.BufferedWriter, _: Unit.Index, _: Entry.Index) error{}!void {1798 fn infoEntry(counter: ExprLocCounter, bw: *Writer, _: Unit.Index, _: Entry.Index) error{}!void {
1802 bw.count += counter.section_offset_bytes;1799 bw.count += counter.section_offset_bytes;
1803 }1800 }
1804 };1801 };
...@@ -1817,10 +1814,10 @@ pub const WipNav = struct {...@@ -1817,10 +1814,10 @@ pub const WipNav = struct {
1817 fn endian(ctx: @This()) std.builtin.Endian {1814 fn endian(ctx: @This()) std.builtin.Endian {
1818 return ctx.wip_nav.dwarf.endian;1815 return ctx.wip_nav.dwarf.endian;
1819 }1816 }
1820 fn addrSym(ctx: @This(), _: *std.io.BufferedWriter, sym_index: u32) UpdateError!void {1817 fn addrSym(ctx: @This(), _: *Writer, sym_index: u32) UpdateError!void {
1821 try ctx.wip_nav.infoAddrSym(sym_index, 0);1818 try ctx.wip_nav.infoAddrSym(sym_index, 0);
1822 }1819 }
1823 fn infoEntry(ctx: @This(), _: *std.io.BufferedWriter, unit: Unit.Index, entry: Entry.Index) UpdateError!void {1820 fn infoEntry(ctx: @This(), _: *Writer, unit: Unit.Index, entry: Entry.Index) UpdateError!void {
1824 try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1821 try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1825 }1822 }
1826 } = .{ .wip_nav = wip_nav };1823 } = .{ .wip_nav = wip_nav };
...@@ -1852,10 +1849,10 @@ pub const WipNav = struct {...@@ -1852,10 +1849,10 @@ pub const WipNav = struct {
1852 fn endian(ctx: @This()) std.builtin.Endian {1849 fn endian(ctx: @This()) std.builtin.Endian {
1853 return ctx.wip_nav.dwarf.endian;1850 return ctx.wip_nav.dwarf.endian;
1854 }1851 }
1855 fn addrSym(ctx: @This(), _: *std.io.BufferedWriter, sym_index: u32) UpdateError!void {1852 fn addrSym(ctx: @This(), _: *Writer, sym_index: u32) UpdateError!void {
1856 try ctx.wip_nav.frameAddrSym(sym_index, 0);1853 try ctx.wip_nav.frameAddrSym(sym_index, 0);
1857 }1854 }
1858 fn infoEntry(ctx: @This(), _: *std.io.BufferedWriter, unit: Unit.Index, entry: Entry.Index) UpdateError!void {1855 fn infoEntry(ctx: @This(), _: *Writer, unit: Unit.Index, entry: Entry.Index) UpdateError!void {
1859 try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0);1856 try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0);
1860 }1857 }
1861 } = .{ .wip_nav = wip_nav };1858 } = .{ .wip_nav = wip_nav };
...@@ -2756,8 +2753,7 @@ fn finishWipNavFuncInner(...@@ -2756,8 +2753,7 @@ fn finishWipNavFuncInner(
2756 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));2753 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
2757 } else {2754 } else {
2758 const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes];2755 const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes];
2759 var abbrev_code_br: std.io.Reader = undefined;2756 var abbrev_code_br: std.io.Reader = .fixed(abbrev_code_buf);
2760 abbrev_code_br.initFixed(abbrev_code_buf);
2761 const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);2757 const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
2762 std.leb.writeUnsignedFixed(2758 std.leb.writeUnsignedFixed(
2763 AbbrevCode.decl_bytes,2759 AbbrevCode.decl_bytes,
...@@ -4565,14 +4561,14 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4565,14 +4561,14 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
45654561
4566 var header: std.ArrayListUnmanaged(u8) = .empty;4562 var header: std.ArrayListUnmanaged(u8) = .empty;
4567 defer header.deinit(gpa);4563 defer header.deinit(gpa);
4568 var header_bw: std.io.BufferedWriter = undefined;4564 var header_bw: Writer = undefined;
4569 if (dwarf.debug_aranges.section.dirty) {4565 if (dwarf.debug_aranges.section.dirty) {
4570 for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {4566 for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
4571 const unit: Unit.Index = @enumFromInt(unit_index);4567 const unit: Unit.Index = @enumFromInt(unit_index);
4572 unit_ptr.clear();4568 unit_ptr.clear();
4573 try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 1);4569 try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 1);
4574 try header.resize(gpa, unit_ptr.header_len);4570 try header.resize(gpa, unit_ptr.header_len);
4575 header_bw.initFixed(header.items);4571 header_bw = .fixed(header.items);
4576 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|4572 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
4577 dwarf.debug_aranges.section.getUnit(next_unit).off4573 dwarf.debug_aranges.section.getUnit(next_unit).off
4578 else4574 else
...@@ -4610,7 +4606,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4610,7 +4606,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4610 const Register = @import("../arch/x86_64/bits.zig").Register;4606 const Register = @import("../arch/x86_64/bits.zig").Register;
4611 for (dwarf.debug_frame.section.units.items) |*unit| {4607 for (dwarf.debug_frame.section.units.items) |*unit| {
4612 try header.resize(gpa, unit.header_len);4608 try header.resize(gpa, unit.header_len);
4613 header_bw.initFixed(header.items);4609 header_bw = .fixed(header.items);
4614 const unit_len = unit.header_len - dwarf.unitLengthBytes();4610 const unit_len = unit.header_len - dwarf.unitLengthBytes();
4615 switch (dwarf.format) {4611 switch (dwarf.format) {
4616 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,4612 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
...@@ -4651,7 +4647,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4651,7 +4647,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4651 try unit_ptr.cross_unit_relocs.ensureTotalCapacity(gpa, 1);4647 try unit_ptr.cross_unit_relocs.ensureTotalCapacity(gpa, 1);
4652 try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 7);4648 try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 7);
4653 try header.resize(gpa, unit_ptr.header_len);4649 try header.resize(gpa, unit_ptr.header_len);
4654 header_bw.initFixed(header.items);4650 header_bw = .fixed(header.items);
4655 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|4651 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
4656 dwarf.debug_info.section.getUnit(next_unit).off4652 dwarf.debug_info.section.getUnit(next_unit).off
4657 else4653 else
...@@ -4751,7 +4747,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4751,7 +4747,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4751 unit.clear();4747 unit.clear();
4752 try unit.cross_section_relocs.ensureTotalCapacity(gpa, mod_info.dirs.count() + 2 * (mod_info.files.count()));4748 try unit.cross_section_relocs.ensureTotalCapacity(gpa, mod_info.dirs.count() + 2 * (mod_info.files.count()));
4753 try header.resize(gpa, unit.header_len);4749 try header.resize(gpa, unit.header_len);
4754 header_bw.initFixed(header.items);4750 header_bw = .fixed(header.items);
4755 const unit_len = (if (unit.next.unwrap()) |next_unit|4751 const unit_len = (if (unit.next.unwrap()) |next_unit|
4756 dwarf.debug_line.section.getUnit(next_unit).off4752 dwarf.debug_line.section.getUnit(next_unit).off
4757 else4753 else
...@@ -4859,7 +4855,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4859,7 +4855,7 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4859 if (dwarf.debug_rnglists.section.dirty) {4855 if (dwarf.debug_rnglists.section.dirty) {
4860 for (dwarf.debug_rnglists.section.units.items) |*unit| {4856 for (dwarf.debug_rnglists.section.units.items) |*unit| {
4861 try header.resize(gpa, unit.header_len);4857 try header.resize(gpa, unit.header_len);
4862 header_bw.initFixed(header.items);4858 header_bw = .fixed(header.items);
4863 const unit_len = (if (unit.next.unwrap()) |next_unit|4859 const unit_len = (if (unit.next.unwrap()) |next_unit|
4864 dwarf.debug_rnglists.section.getUnit(next_unit).off4860 dwarf.debug_rnglists.section.getUnit(next_unit).off
4865 else4861 else
...@@ -6078,7 +6074,7 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {...@@ -6078,7 +6074,7 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {
6078 }6074 }
6079}6075}
60806076
6081fn writeIntTo(dwarf: *Dwarf, bw: *std.io.BufferedWriter, len: usize, int: u64) !void {6077fn writeIntTo(dwarf: *Dwarf, bw: *Writer, len: usize, int: u64) !void {
6082 dwarf.writeInt(try bw.writableSlice(len), int);6078 dwarf.writeInt(try bw.writableSlice(len), int);
6083}6079}
60846080
...@@ -6127,8 +6123,7 @@ fn leb128Bytes(value: anytype) u32 {...@@ -6127,8 +6123,7 @@ fn leb128Bytes(value: anytype) u32 {
6127 var buffer: [6123 var buffer: [
6128 std.math.divCeil(u16, @intFromBool(value_info.signedness == .signed) + value_info.bits, 7) catch unreachable6124 std.math.divCeil(u16, @intFromBool(value_info.signedness == .signed) + value_info.bits, 7) catch unreachable
6129 ]u8 = undefined;6125 ]u8 = undefined;
6130 var bw: std.io.BufferedWriter = undefined;6126 var bw: Writer = .fixed(&buffer);
6131 bw.initFixed(&buffer);
6132 bw.writeLeb128(value) catch unreachable;6127 bw.writeLeb128(value) catch unreachable;
6133 return @intCast(bw.end);6128 return @intCast(bw.end);
6134}6129}
...@@ -6155,3 +6150,4 @@ const log = std.log.scoped(.dwarf);...@@ -6155,3 +6150,4 @@ const log = std.log.scoped(.dwarf);
6155const std = @import("std");6150const std = @import("std");
6156const target_info = @import("../target.zig");6151const target_info = @import("../target.zig");
6157const Allocator = std.mem.Allocator;6152const Allocator = std.mem.Allocator;
6153const Writer = std.io.Writer;
src/link/Elf.zig+18-18
...@@ -3029,8 +3029,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -3029,8 +3029,7 @@ fn writeAtoms(self: *Elf) !void {
3029 if (self.requiresThunks()) {3029 if (self.requiresThunks()) {
3030 for (self.thunks.items) |th| {3030 for (self.thunks.items) |th| {
3031 try buffer.resize(th.size(self));3031 try buffer.resize(th.size(self));
3032 var bw: std.io.BufferedWriter = undefined;3032 var bw: Writer = .fixed(buffer.items);
3033 bw.initFixed(buffer.items);
3034 const shdr = slice.items(.shdr)[th.output_section_index];3033 const shdr = slice.items(.shdr)[th.output_section_index];
3035 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;3034 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
3036 try th.write(self, &bw);3035 try th.write(self, &bw);
...@@ -3136,7 +3135,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3136,7 +3135,7 @@ fn writeSyntheticSections(self: *Elf) !void {
31363135
3137 var buffer: std.ArrayListUnmanaged(u8) = .empty;3136 var buffer: std.ArrayListUnmanaged(u8) = .empty;
3138 defer buffer.deinit(gpa);3137 defer buffer.deinit(gpa);
3139 var bw: std.io.BufferedWriter = undefined;3138 var bw: Writer = undefined;
31403139
3141 if (self.section_indexes.interp) |shndx| {3140 if (self.section_indexes.interp) |shndx| {
3142 const shdr = slice.items(.shdr)[shndx];3141 const shdr = slice.items(.shdr)[shndx];
...@@ -3156,7 +3155,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3156,7 +3155,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3156 if (self.section_indexes.gnu_hash) |shndx| {3155 if (self.section_indexes.gnu_hash) |shndx| {
3157 const shdr = slice.items(.shdr)[shndx];3156 const shdr = slice.items(.shdr)[shndx];
3158 try buffer.resize(gpa, self.gnu_hash.size());3157 try buffer.resize(gpa, self.gnu_hash.size());
3159 bw.initFixed(buffer.items);3158 bw = .fixed(buffer.items);
3160 try self.gnu_hash.write(self, &bw);3159 try self.gnu_hash.write(self, &bw);
3161 assert(bw.end == bw.buffer.len);3160 assert(bw.end == bw.buffer.len);
3162 try self.pwriteAll(bw.buffer, shdr.sh_offset);3161 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3170,7 +3169,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3170,7 +3169,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3170 if (self.section_indexes.verneed) |shndx| {3169 if (self.section_indexes.verneed) |shndx| {
3171 const shdr = slice.items(.shdr)[shndx];3170 const shdr = slice.items(.shdr)[shndx];
3172 try buffer.resize(gpa, self.verneed.size());3171 try buffer.resize(gpa, self.verneed.size());
3173 bw.initFixed(buffer.items);3172 bw = .fixed(buffer.items);
3174 try self.verneed.write(&bw);3173 try self.verneed.write(&bw);
3175 assert(bw.end == bw.buffer.len);3174 assert(bw.end == bw.buffer.len);
3176 try self.pwriteAll(bw.buffer, shdr.sh_offset);3175 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3179,7 +3178,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3179,7 +3178,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3179 if (self.section_indexes.dynamic) |shndx| {3178 if (self.section_indexes.dynamic) |shndx| {
3180 const shdr = slice.items(.shdr)[shndx];3179 const shdr = slice.items(.shdr)[shndx];
3181 try buffer.resize(gpa, self.dynamic.size(self));3180 try buffer.resize(gpa, self.dynamic.size(self));
3182 bw.initFixed(buffer.items);3181 bw = .fixed(buffer.items);
3183 try self.dynamic.write(self, &bw);3182 try self.dynamic.write(self, &bw);
3184 assert(bw.end == bw.buffer.len);3183 assert(bw.end == bw.buffer.len);
3185 try self.pwriteAll(bw.buffer, shdr.sh_offset);3184 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3188,7 +3187,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3188,7 +3187,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3188 if (self.section_indexes.dynsymtab) |shndx| {3187 if (self.section_indexes.dynsymtab) |shndx| {
3189 const shdr = slice.items(.shdr)[shndx];3188 const shdr = slice.items(.shdr)[shndx];
3190 try buffer.resize(gpa, self.dynsym.size());3189 try buffer.resize(gpa, self.dynsym.size());
3191 bw.initFixed(buffer.items);3190 bw = .fixed(buffer.items);
3192 try self.dynsym.write(self, &bw);3191 try self.dynsym.write(self, &bw);
3193 assert(bw.end == bw.buffer.len);3192 assert(bw.end == bw.buffer.len);
3194 try self.pwriteAll(bw.buffer, shdr.sh_offset);3193 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3208,7 +3207,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3208,7 +3207,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3208 const shdr = slice.items(.shdr)[shndx];3207 const shdr = slice.items(.shdr)[shndx];
3209 const sh_size = try self.cast(usize, shdr.sh_size);3208 const sh_size = try self.cast(usize, shdr.sh_size);
3210 try buffer.resize(gpa, @intCast(sh_size - existing_size));3209 try buffer.resize(gpa, @intCast(sh_size - existing_size));
3211 bw.initFixed(buffer.items);3210 bw = .fixed(buffer.items);
3212 try eh_frame.writeEhFrame(self, &bw);3211 try eh_frame.writeEhFrame(self, &bw);
3213 assert(bw.end == bw.buffer.len);3212 assert(bw.end == bw.buffer.len);
3214 try self.pwriteAll(bw.buffer, shdr.sh_offset + existing_size);3213 try self.pwriteAll(bw.buffer, shdr.sh_offset + existing_size);
...@@ -3218,7 +3217,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3218,7 +3217,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3218 const shdr = slice.items(.shdr)[shndx];3217 const shdr = slice.items(.shdr)[shndx];
3219 const sh_size = try self.cast(usize, shdr.sh_size);3218 const sh_size = try self.cast(usize, shdr.sh_size);
3220 try buffer.resize(gpa, sh_size);3219 try buffer.resize(gpa, sh_size);
3221 bw.initFixed(buffer.items);3220 bw = .fixed(buffer.items);
3222 try eh_frame.writeEhFrameHdr(self, &bw);3221 try eh_frame.writeEhFrameHdr(self, &bw);
3223 assert(bw.end == bw.buffer.len);3222 assert(bw.end == bw.buffer.len);
3224 try self.pwriteAll(bw.buffer, shdr.sh_offset);3223 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3227,7 +3226,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3227,7 +3226,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3227 if (self.section_indexes.got) |index| {3226 if (self.section_indexes.got) |index| {
3228 const shdr = slice.items(.shdr)[index];3227 const shdr = slice.items(.shdr)[index];
3229 try buffer.resize(gpa, self.got.size(self));3228 try buffer.resize(gpa, self.got.size(self));
3230 bw.initFixed(buffer.items);3229 bw = .fixed(buffer.items);
3231 try self.got.write(self, &bw);3230 try self.got.write(self, &bw);
3232 assert(bw.end == bw.buffer.len);3231 assert(bw.end == bw.buffer.len);
3233 try self.pwriteAll(bw.buffer, shdr.sh_offset);3232 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3244,7 +3243,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3244,7 +3243,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3244 if (self.section_indexes.plt) |shndx| {3243 if (self.section_indexes.plt) |shndx| {
3245 const shdr = slice.items(.shdr)[shndx];3244 const shdr = slice.items(.shdr)[shndx];
3246 try buffer.resize(gpa, self.plt.size(self));3245 try buffer.resize(gpa, self.plt.size(self));
3247 bw.initFixed(buffer.items);3246 bw = .fixed(buffer.items);
3248 try self.plt.write(self, &bw);3247 try self.plt.write(self, &bw);
3249 assert(bw.end == bw.buffer.len);3248 assert(bw.end == bw.buffer.len);
3250 try self.pwriteAll(bw.buffer, shdr.sh_offset);3249 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3253,7 +3252,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3253,7 +3252,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3253 if (self.section_indexes.got_plt) |shndx| {3252 if (self.section_indexes.got_plt) |shndx| {
3254 const shdr = slice.items(.shdr)[shndx];3253 const shdr = slice.items(.shdr)[shndx];
3255 try buffer.resize(gpa, self.got_plt.size(self));3254 try buffer.resize(gpa, self.got_plt.size(self));
3256 bw.initFixed(buffer.items);3255 bw = .fixed(buffer.items);
3257 try self.got_plt.write(self, &bw);3256 try self.got_plt.write(self, &bw);
3258 assert(bw.end == bw.buffer.len);3257 assert(bw.end == bw.buffer.len);
3259 try self.pwriteAll(bw.buffer, shdr.sh_offset);3258 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3262,7 +3261,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3262,7 +3261,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3262 if (self.section_indexes.plt_got) |shndx| {3261 if (self.section_indexes.plt_got) |shndx| {
3263 const shdr = slice.items(.shdr)[shndx];3262 const shdr = slice.items(.shdr)[shndx];
3264 try buffer.resize(gpa, self.plt_got.size(self));3263 try buffer.resize(gpa, self.plt_got.size(self));
3265 bw.initFixed(buffer.items);3264 bw = .fixed(buffer.items);
3266 try self.plt_got.write(self, &bw);3265 try self.plt_got.write(self, &bw);
3267 assert(bw.end == bw.buffer.len);3266 assert(bw.end == bw.buffer.len);
3268 try self.pwriteAll(bw.buffer, shdr.sh_offset);3267 try self.pwriteAll(bw.buffer, shdr.sh_offset);
...@@ -3883,7 +3882,7 @@ fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(formatShdr) {...@@ -3883,7 +3882,7 @@ fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(formatShdr) {
3883 } };3882 } };
3884}3883}
38853884
3886fn formatShdr(ctx: FormatShdrCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {3885fn formatShdr(ctx: FormatShdrCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
3887 _ = unused_fmt_string;3886 _ = unused_fmt_string;
3888 const shdr = ctx.shdr;3887 const shdr = ctx.shdr;
3889 try bw.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({f})", .{3888 try bw.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({f})", .{
...@@ -3898,7 +3897,7 @@ pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) {...@@ -3898,7 +3897,7 @@ pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) {
3898 return .{ .data = sh_flags };3897 return .{ .data = sh_flags };
3899}3898}
39003899
3901fn formatShdrFlags(sh_flags: u64, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) !void {3900fn formatShdrFlags(sh_flags: u64, bw: *Writer, comptime unused_fmt_string: []const u8) !void {
3902 _ = unused_fmt_string;3901 _ = unused_fmt_string;
3903 if (elf.SHF_WRITE & sh_flags != 0) {3902 if (elf.SHF_WRITE & sh_flags != 0) {
3904 try bw.writeByte('W');3903 try bw.writeByte('W');
...@@ -3958,7 +3957,7 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(formatPhdr) {...@@ -3958,7 +3957,7 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(formatPhdr) {
39583957
3959fn formatPhdr(3958fn formatPhdr(
3960 ctx: FormatPhdrCtx,3959 ctx: FormatPhdrCtx,
3961 bw: *std.io.BufferedWriter,3960 bw: *Writer,
3962 comptime unused_fmt_string: []const u8,3961 comptime unused_fmt_string: []const u8,
3963) !void {3962) !void {
3964 _ = unused_fmt_string;3963 _ = unused_fmt_string;
...@@ -3994,7 +3993,7 @@ pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {...@@ -3994,7 +3993,7 @@ pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {
39943993
3995fn fmtDumpState(3994fn fmtDumpState(
3996 self: *Elf,3995 self: *Elf,
3997 bw: *std.io.BufferedWriter,3996 bw: *Writer,
3998 comptime unused_fmt_string: []const u8,3997 comptime unused_fmt_string: []const u8,
3999) !void {3998) !void {
4000 _ = unused_fmt_string;3999 _ = unused_fmt_string;
...@@ -4216,7 +4215,7 @@ pub const Ref = struct {...@@ -4216,7 +4215,7 @@ pub const Ref = struct {
4216 return ref.index == other.index and ref.file == other.file;4215 return ref.index == other.index and ref.file == other.file;
4217 }4216 }
42184217
4219 pub fn format(ref: Ref, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {4218 pub fn format(ref: Ref, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
4220 _ = unused_fmt_string;4219 _ = unused_fmt_string;
4221 try bw.print("ref({},{})", .{ ref.index, ref.file });4220 try bw.print("ref({},{})", .{ ref.index, ref.file });
4222 }4221 }
...@@ -4493,6 +4492,7 @@ const Allocator = std.mem.Allocator;...@@ -4493,6 +4492,7 @@ const Allocator = std.mem.Allocator;
4493const Hash = std.hash.Wyhash;4492const Hash = std.hash.Wyhash;
4494const Path = std.Build.Cache.Path;4493const Path = std.Build.Cache.Path;
4495const Stat = std.Build.Cache.File.Stat;4494const Stat = std.Build.Cache.File.Stat;
4495const Writer = std.io.Writer;
44964496
4497const codegen = @import("../codegen.zig");4497const codegen = @import("../codegen.zig");
4498const dev = @import("../dev.zig");4498const dev = @import("../dev.zig");
src/link/Elf/Archive.zig+5-4
...@@ -184,7 +184,7 @@ pub const ArSymtab = struct {...@@ -184,7 +184,7 @@ pub const ArSymtab = struct {
184 }184 }
185 }185 }
186186
187 pub fn format(ar: ArSymtab, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {187 pub fn format(ar: ArSymtab, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
188 _ = ar;188 _ = ar;
189 _ = bw;189 _ = bw;
190 _ = unused_fmt_string;190 _ = unused_fmt_string;
...@@ -203,7 +203,7 @@ pub const ArSymtab = struct {...@@ -203,7 +203,7 @@ pub const ArSymtab = struct {
203 } };203 } };
204 }204 }
205205
206 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {206 fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
207 _ = unused_fmt_string;207 _ = unused_fmt_string;
208 const ar = ctx.ar;208 const ar = ctx.ar;
209 const elf_file = ctx.elf_file;209 const elf_file = ctx.elf_file;
...@@ -251,8 +251,8 @@ pub const ArStrtab = struct {...@@ -251,8 +251,8 @@ pub const ArStrtab = struct {
251 try writer.writeAll(ar.buffer.items);251 try writer.writeAll(ar.buffer.items);
252 }252 }
253253
254 pub fn format(ar: ArStrtab, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {254 pub fn format(ar: ArStrtab, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
255 _ = unused_fmt_string;255 comptime assert(unused_fmt_string.len == 0);
256 try bw.print("{f}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});256 try bw.print("{f}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});
257 }257 }
258};258};
...@@ -277,6 +277,7 @@ const log = std.log.scoped(.link);...@@ -277,6 +277,7 @@ const log = std.log.scoped(.link);
277const mem = std.mem;277const mem = std.mem;
278const Path = std.Build.Cache.Path;278const Path = std.Build.Cache.Path;
279const Allocator = std.mem.Allocator;279const Allocator = std.mem.Allocator;
280const Writer = std.io.Writer;
280281
281const Diags = @import("../../link.zig").Diags;282const Diags = @import("../../link.zig").Diags;
282const Archive = @This();283const Archive = @This();
src/link/Elf/Atom.zig+23-25
...@@ -622,8 +622,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -622,8 +622,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
622 const cpu_arch = elf_file.getTarget().cpu.arch;622 const cpu_arch = elf_file.getTarget().cpu.arch;
623 const file_ptr = self.file(elf_file).?;623 const file_ptr = self.file(elf_file).?;
624624
625 var bw: std.io.BufferedWriter = undefined;625 var bw: Writer = .fixed(code);
626 bw.initFixed(code);
627626
628 const rels = self.relocs(elf_file);627 const rels = self.relocs(elf_file);
629 var it = RelocsIterator{ .relocs = rels };628 var it = RelocsIterator{ .relocs = rels };
...@@ -807,8 +806,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -807,8 +806,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
807 const cpu_arch = elf_file.getTarget().cpu.arch;806 const cpu_arch = elf_file.getTarget().cpu.arch;
808 const file_ptr = self.file(elf_file).?;807 const file_ptr = self.file(elf_file).?;
809808
810 var bw: std.io.BufferedWriter = undefined;809 var bw: Writer = .fixed(code);
811 bw.initFixed(code);
812810
813 const rels = self.relocs(elf_file);811 const rels = self.relocs(elf_file);
814 var has_reloc_errors = false;812 var has_reloc_errors = false;
...@@ -908,7 +906,7 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {...@@ -908,7 +906,7 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
908 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);906 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);
909}907}
910908
911pub fn format(atom: Atom, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {909pub fn format(atom: Atom, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
912 _ = atom;910 _ = atom;
913 _ = bw;911 _ = bw;
914 _ = unused_fmt_string;912 _ = unused_fmt_string;
...@@ -927,7 +925,7 @@ const FormatContext = struct {...@@ -927,7 +925,7 @@ const FormatContext = struct {
927 elf_file: *Elf,925 elf_file: *Elf,
928};926};
929927
930fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {928fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
931 _ = unused_fmt_string;929 _ = unused_fmt_string;
932 const atom = ctx.atom;930 const atom = ctx.atom;
933 const elf_file = ctx.elf_file;931 const elf_file = ctx.elf_file;
...@@ -1079,8 +1077,8 @@ const x86_64 = struct {...@@ -1079,8 +1077,8 @@ const x86_64 = struct {
1079 target: *const Symbol,1077 target: *const Symbol,
1080 args: ResolveArgs,1078 args: ResolveArgs,
1081 it: *RelocsIterator,1079 it: *RelocsIterator,
1082 bw: *std.io.BufferedWriter,1080 bw: *Writer,
1083 ) std.io.Writer.Error!void {1081 ) Writer.Error!void {
1084 dev.check(.x86_64_backend);1082 dev.check(.x86_64_backend);
1085 const t = &elf_file.base.comp.root_mod.resolved_target.result;1083 const t = &elf_file.base.comp.root_mod.resolved_target.result;
1086 const diags = &elf_file.base.comp.link_diags;1084 const diags = &elf_file.base.comp.link_diags;
...@@ -1211,8 +1209,8 @@ const x86_64 = struct {...@@ -1211,8 +1209,8 @@ const x86_64 = struct {
1211 rel: elf.Elf64_Rela,1209 rel: elf.Elf64_Rela,
1212 target: *const Symbol,1210 target: *const Symbol,
1213 args: ResolveArgs,1211 args: ResolveArgs,
1214 bw: *std.io.BufferedWriter,1212 bw: *Writer,
1215 ) std.io.Writer.Error!void {1213 ) Writer.Error!void {
1216 dev.check(.x86_64_backend);1214 dev.check(.x86_64_backend);
12171215
1218 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());1216 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
...@@ -1287,7 +1285,7 @@ const x86_64 = struct {...@@ -1287,7 +1285,7 @@ const x86_64 = struct {
1287 rels: []const elf.Elf64_Rela,1285 rels: []const elf.Elf64_Rela,
1288 value: i32,1286 value: i32,
1289 elf_file: *Elf,1287 elf_file: *Elf,
1290 bw: *std.io.BufferedWriter,1288 bw: *Writer,
1291 ) !void {1289 ) !void {
1292 dev.check(.x86_64_backend);1290 dev.check(.x86_64_backend);
1293 assert(rels.len == 2);1291 assert(rels.len == 2);
...@@ -1327,7 +1325,7 @@ const x86_64 = struct {...@@ -1327,7 +1325,7 @@ const x86_64 = struct {
1327 rels: []const elf.Elf64_Rela,1325 rels: []const elf.Elf64_Rela,
1328 value: i32,1326 value: i32,
1329 elf_file: *Elf,1327 elf_file: *Elf,
1330 bw: *std.io.BufferedWriter,1328 bw: *Writer,
1331 ) !void {1329 ) !void {
1332 dev.check(.x86_64_backend);1330 dev.check(.x86_64_backend);
1333 assert(rels.len == 2);1331 assert(rels.len == 2);
...@@ -1388,7 +1386,7 @@ const x86_64 = struct {...@@ -1388,7 +1386,7 @@ const x86_64 = struct {
1388 .{ .imm = .s(-129) },1386 .{ .imm = .s(-129) },
1389 }, t) catch return false;1387 }, t) catch return false;
1390 var buf: [std.atomic.cache_line]u8 = undefined;1388 var buf: [std.atomic.cache_line]u8 = undefined;
1391 var bw = std.io.Writer.null.buffered(&buf);1389 var bw = Writer.null.buffered(&buf);
1392 inst.encode(&bw, .{}) catch return false;1390 inst.encode(&bw, .{}) catch return false;
1393 return true;1391 return true;
1394 },1392 },
...@@ -1435,7 +1433,7 @@ const x86_64 = struct {...@@ -1435,7 +1433,7 @@ const x86_64 = struct {
1435 rels: []const elf.Elf64_Rela,1433 rels: []const elf.Elf64_Rela,
1436 value: i32,1434 value: i32,
1437 elf_file: *Elf,1435 elf_file: *Elf,
1438 bw: *std.io.BufferedWriter,1436 bw: *Writer,
1439 ) !void {1437 ) !void {
1440 dev.check(.x86_64_backend);1438 dev.check(.x86_64_backend);
1441 assert(rels.len == 2);1439 assert(rels.len == 2);
...@@ -1483,8 +1481,7 @@ const x86_64 = struct {...@@ -1483,8 +1481,7 @@ const x86_64 = struct {
1483 }1481 }
14841482
1485 fn encode(insts: []const Instruction, code: []u8) !void {1483 fn encode(insts: []const Instruction, code: []u8) !void {
1486 var bw: std.io.BufferedWriter = undefined;1484 var bw: Writer = .fixed(code);
1487 bw.initFixed(code);
1488 for (insts) |inst| try inst.encode(&bw, .{});1485 for (insts) |inst| try inst.encode(&bw, .{});
1489 }1486 }
14901487
...@@ -1589,8 +1586,8 @@ const aarch64 = struct {...@@ -1589,8 +1586,8 @@ const aarch64 = struct {
1589 target: *const Symbol,1586 target: *const Symbol,
1590 args: ResolveArgs,1587 args: ResolveArgs,
1591 it: *RelocsIterator,1588 it: *RelocsIterator,
1592 bw: *std.io.BufferedWriter,1589 bw: *Writer,
1593 ) std.io.Writer.Error!void {1590 ) Writer.Error!void {
1594 _ = it;1591 _ = it;
15951592
1596 const diags = &elf_file.base.comp.link_diags;1593 const diags = &elf_file.base.comp.link_diags;
...@@ -1792,7 +1789,7 @@ const aarch64 = struct {...@@ -1792,7 +1789,7 @@ const aarch64 = struct {
1792 rel: elf.Elf64_Rela,1789 rel: elf.Elf64_Rela,
1793 target: *const Symbol,1790 target: *const Symbol,
1794 args: ResolveArgs,1791 args: ResolveArgs,
1795 bw: *std.io.BufferedWriter,1792 bw: *Writer,
1796 ) !void {1793 ) !void {
1797 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1794 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1798 _, const A, const S, _, _, _, _ = args;1795 _, const A, const S, _, _, _, _ = args;
...@@ -1865,7 +1862,7 @@ const riscv = struct {...@@ -1865,7 +1862,7 @@ const riscv = struct {
1865 target: *const Symbol,1862 target: *const Symbol,
1866 args: ResolveArgs,1863 args: ResolveArgs,
1867 it: *RelocsIterator,1864 it: *RelocsIterator,
1868 bw: *std.io.BufferedWriter,1865 bw: *Writer,
1869 ) !void {1866 ) !void {
1870 const diags = &elf_file.base.comp.link_diags;1867 const diags = &elf_file.base.comp.link_diags;
1871 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());1868 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
...@@ -2000,8 +1997,8 @@ const riscv = struct {...@@ -2000,8 +1997,8 @@ const riscv = struct {
2000 rel: elf.Elf64_Rela,1997 rel: elf.Elf64_Rela,
2001 target: *const Symbol,1998 target: *const Symbol,
2002 args: ResolveArgs,1999 args: ResolveArgs,
2003 bw: *std.io.BufferedWriter,2000 bw: *Writer,
2004 ) std.io.Writer.Error!void {2001 ) Writer.Error!void {
2005 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());2002 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
20062003
2007 _, const A, const S, const GOT, _, _, const DTP = args;2004 _, const A, const S, const GOT, _, _, const DTP = args;
...@@ -2105,14 +2102,15 @@ pub const Extra = struct {...@@ -2105,14 +2102,15 @@ pub const Extra = struct {
2105const std = @import("std");2102const std = @import("std");
2106const assert = std.debug.assert;2103const assert = std.debug.assert;
2107const elf = std.elf;2104const elf = std.elf;
2108const eh_frame = @import("eh_frame.zig");
2109const log = std.log.scoped(.link);2105const log = std.log.scoped(.link);
2110const math = std.math;2106const math = std.math;
2111const mem = std.mem;2107const mem = std.mem;
2112const relocs_log = std.log.scoped(.link_relocs);2108const relocs_log = std.log.scoped(.link_relocs);
2113const relocation = @import("relocation.zig");
2114
2115const Allocator = mem.Allocator;2109const Allocator = mem.Allocator;
2110const Writer = std.io.Writer;
2111
2112const eh_frame = @import("eh_frame.zig");
2113const relocation = @import("relocation.zig");
2116const Atom = @This();2114const Atom = @This();
2117const Elf = @import("../Elf.zig");2115const Elf = @import("../Elf.zig");
2118const Fde = eh_frame.Fde;2116const Fde = eh_frame.Fde;
src/link/Elf/AtomList.zig+6-5
...@@ -167,7 +167,7 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {...@@ -167,7 +167,7 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {
167 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;167 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;
168}168}
169169
170pub fn format(list: AtomList, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {170pub fn format(list: AtomList, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
171 _ = list;171 _ = list;
172 _ = bw;172 _ = bw;
173 _ = unused_fmt_string;173 _ = unused_fmt_string;
...@@ -180,8 +180,8 @@ pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) {...@@ -180,8 +180,8 @@ pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) {
180 return .{ .data = .{ list, elf_file } };180 return .{ .data = .{ list, elf_file } };
181}181}
182182
183fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {183fn format2(ctx: FormatCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
184 _ = unused_fmt_string;184 comptime assert(unused_fmt_string.len == 0);
185 const list, const elf_file = ctx;185 const list, const elf_file = ctx;
186 try bw.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{186 try bw.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{
187 list.address(elf_file), list.output_section_index,187 list.address(elf_file), list.output_section_index,
...@@ -195,13 +195,14 @@ fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_strin...@@ -195,13 +195,14 @@ fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_strin
195 try bw.writeAll(" }");195 try bw.writeAll(" }");
196}196}
197197
198const std = @import("std");
198const assert = std.debug.assert;199const assert = std.debug.assert;
199const elf = std.elf;200const elf = std.elf;
200const log = std.log.scoped(.link);201const log = std.log.scoped(.link);
201const math = std.math;202const math = std.math;
202const std = @import("std");
203
204const Allocator = std.mem.Allocator;203const Allocator = std.mem.Allocator;
204const Writer = std.io.Writer;
205
205const Atom = @import("Atom.zig");206const Atom = @import("Atom.zig");
206const AtomList = @This();207const AtomList = @This();
207const Elf = @import("../Elf.zig");208const Elf = @import("../Elf.zig");
src/link/Elf/LinkerDefined.zig+5-4
...@@ -449,8 +449,8 @@ const FormatContext = struct {...@@ -449,8 +449,8 @@ const FormatContext = struct {
449 elf_file: *Elf,449 elf_file: *Elf,
450};450};
451451
452fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {452fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
453 _ = unused_fmt_string;453 comptime assert(unused_fmt_string.len == 0);
454 const self = ctx.self;454 const self = ctx.self;
455 const elf_file = ctx.elf_file;455 const elf_file = ctx.elf_file;
456 try bw.writeAll(" globals\n");456 try bw.writeAll(" globals\n");
...@@ -464,12 +464,13 @@ fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_...@@ -464,12 +464,13 @@ fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_
464 }464 }
465}465}
466466
467const std = @import("std");
468const Allocator = mem.Allocator;
467const assert = std.debug.assert;469const assert = std.debug.assert;
468const elf = std.elf;470const elf = std.elf;
469const mem = std.mem;471const mem = std.mem;
470const std = @import("std");472const Writer = std.io.Writer;
471473
472const Allocator = mem.Allocator;
473const Atom = @import("Atom.zig");474const Atom = @import("Atom.zig");
474const Elf = @import("../Elf.zig");475const Elf = @import("../Elf.zig");
475const File = @import("file.zig").File;476const File = @import("file.zig").File;
src/link/Elf/Merge.zig+7-6
...@@ -157,7 +157,7 @@ pub const Section = struct {...@@ -157,7 +157,7 @@ pub const Section = struct {
157 }157 }
158 };158 };
159159
160 pub fn format(msec: Section, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {160 pub fn format(msec: Section, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
161 _ = msec;161 _ = msec;
162 _ = bw;162 _ = bw;
163 _ = unused_fmt_string;163 _ = unused_fmt_string;
...@@ -176,7 +176,7 @@ pub const Section = struct {...@@ -176,7 +176,7 @@ pub const Section = struct {
176 elf_file: *Elf,176 elf_file: *Elf,
177 };177 };
178178
179 pub fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {179 pub fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
180 _ = unused_fmt_string;180 _ = unused_fmt_string;
181 const msec = ctx.msec;181 const msec = ctx.msec;
182 const elf_file = ctx.elf_file;182 const elf_file = ctx.elf_file;
...@@ -219,7 +219,7 @@ pub const Subsection = struct {...@@ -219,7 +219,7 @@ pub const Subsection = struct {
219 return msec.bytes.items[msub.string_index..][0..msub.size];219 return msec.bytes.items[msub.string_index..][0..msub.size];
220 }220 }
221221
222 pub fn format(msub: Subsection, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {222 pub fn format(msub: Subsection, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
223 _ = msub;223 _ = msub;
224 _ = bw;224 _ = bw;
225 _ = unused_fmt_string;225 _ = unused_fmt_string;
...@@ -238,7 +238,7 @@ pub const Subsection = struct {...@@ -238,7 +238,7 @@ pub const Subsection = struct {
238 elf_file: *Elf,238 elf_file: *Elf,
239 };239 };
240240
241 pub fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {241 pub fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
242 _ = unused_fmt_string;242 _ = unused_fmt_string;
243 const msub = ctx.msub;243 const msub = ctx.msub;
244 const elf_file = ctx.elf_file;244 const elf_file = ctx.elf_file;
...@@ -307,11 +307,12 @@ pub const InputSection = struct {...@@ -307,11 +307,12 @@ pub const InputSection = struct {
307307
308const String = struct { pos: u32, len: u32 };308const String = struct { pos: u32, len: u32 };
309309
310const std = @import("std");
310const assert = std.debug.assert;311const assert = std.debug.assert;
311const mem = std.mem;312const mem = std.mem;
312const std = @import("std");
313
314const Allocator = mem.Allocator;313const Allocator = mem.Allocator;
314const Writer = std.io.Writer;
315
315const Atom = @import("Atom.zig");316const Atom = @import("Atom.zig");
316const Elf = @import("../Elf.zig");317const Elf = @import("../Elf.zig");
317const Merge = @This();318const Merge = @This();
src/link/Elf/Object.zig+11-12
...@@ -448,8 +448,7 @@ fn parseEhFrame(...@@ -448,8 +448,7 @@ fn parseEhFrame(
448 const fdes_start = self.fdes.items.len;448 const fdes_start = self.fdes.items.len;
449 const cies_start = self.cies.items.len;449 const cies_start = self.cies.items.len;
450450
451 var it: eh_frame.Iterator = undefined;451 var it: eh_frame.Iterator = .{ .br = .fixed(raw) };
452 it.br.initFixed(raw);
453 while (try it.next()) |rec| {452 while (try it.next()) |rec| {
454 const rel_range = filterRelocs(self.relocs.items[rel_start..][0..relocs.len], rec.offset, rec.size + 4);453 const rel_range = filterRelocs(self.relocs.items[rel_start..][0..relocs.len], rec.offset, rec.size + 4);
455 switch (rec.tag) {454 switch (rec.tag) {
...@@ -1199,8 +1198,7 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index...@@ -1199,8 +1198,7 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
1199 const chdr = (try r.takeStruct(elf.Elf64_Chdr)).*;1198 const chdr = (try r.takeStruct(elf.Elf64_Chdr)).*;
1200 switch (chdr.ch_type) {1199 switch (chdr.ch_type) {
1201 .ZLIB => {1200 .ZLIB => {
1202 var bw: std.io.BufferedWriter = undefined;1201 var bw: Writer = .fixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow));
1203 bw.initFixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow));
1204 errdefer gpa.free(bw.buffer);1202 errdefer gpa.free(bw.buffer);
1205 try std.compress.zlib.decompress(&r, &bw);1203 try std.compress.zlib.decompress(&r, &bw);
1206 if (bw.end != bw.buffer.len) return error.InputOutput;1204 if (bw.end != bw.buffer.len) return error.InputOutput;
...@@ -1430,7 +1428,7 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {...@@ -1430,7 +1428,7 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {
1430 return &self.groups.items[index];1428 return &self.groups.items[index];
1431}1429}
14321430
1433pub fn format(self: *Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1431pub fn format(self: *Object, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1434 _ = self;1432 _ = self;
1435 _ = bw;1433 _ = bw;
1436 _ = unused_fmt_string;1434 _ = unused_fmt_string;
...@@ -1449,7 +1447,7 @@ const FormatContext = struct {...@@ -1449,7 +1447,7 @@ const FormatContext = struct {
1449 elf_file: *Elf,1447 elf_file: *Elf,
1450};1448};
14511449
1452fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1450fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1453 _ = unused_fmt_string;1451 _ = unused_fmt_string;
1454 const object = ctx.object;1452 const object = ctx.object;
1455 const elf_file = ctx.elf_file;1453 const elf_file = ctx.elf_file;
...@@ -1476,7 +1474,7 @@ pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {...@@ -1476,7 +1474,7 @@ pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {
1476 } };1474 } };
1477}1475}
14781476
1479fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1477fn formatAtoms(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1480 _ = unused_fmt_string;1478 _ = unused_fmt_string;
1481 const object = ctx.object;1479 const object = ctx.object;
1482 try bw.writeAll(" atoms\n");1480 try bw.writeAll(" atoms\n");
...@@ -1493,7 +1491,7 @@ pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {...@@ -1493,7 +1491,7 @@ pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {
1493 } };1491 } };
1494}1492}
14951493
1496fn formatCies(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1494fn formatCies(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1497 _ = unused_fmt_string;1495 _ = unused_fmt_string;
1498 const object = ctx.object;1496 const object = ctx.object;
1499 try bw.writeAll(" cies\n");1497 try bw.writeAll(" cies\n");
...@@ -1509,7 +1507,7 @@ pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatFdes) {...@@ -1509,7 +1507,7 @@ pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatFdes) {
1509 } };1507 } };
1510}1508}
15111509
1512fn formatFdes(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1510fn formatFdes(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1513 _ = unused_fmt_string;1511 _ = unused_fmt_string;
1514 const object = ctx.object;1512 const object = ctx.object;
1515 try bw.writeAll(" fdes\n");1513 try bw.writeAll(" fdes\n");
...@@ -1525,7 +1523,7 @@ pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups)...@@ -1525,7 +1523,7 @@ pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups)
1525 } };1523 } };
1526}1524}
15271525
1528fn formatGroups(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1526fn formatGroups(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1529 comptime assert(unused_fmt_string.len == 0);1527 comptime assert(unused_fmt_string.len == 0);
1530 const object = ctx.object;1528 const object = ctx.object;
1531 const elf_file = ctx.elf_file;1529 const elf_file = ctx.elf_file;
...@@ -1547,8 +1545,8 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {...@@ -1547,8 +1545,8 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {
1547 return .{ .data = self };1545 return .{ .data = self };
1548}1546}
15491547
1550fn formatPath(object: Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1548fn formatPath(object: Object, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1551 _ = unused_fmt_string;1549 comptime assert(unused_fmt_string.len == 0);
1552 if (object.archive) |ar| {1550 if (object.archive) |ar| {
1553 try bw.print("{f}({f})", .{ ar.path, object.path });1551 try bw.print("{f}({f})", .{ ar.path, object.path });
1554 } else {1552 } else {
...@@ -1574,6 +1572,7 @@ const math = std.math;...@@ -1574,6 +1572,7 @@ const math = std.math;
1574const mem = std.mem;1572const mem = std.mem;
1575const Path = std.Build.Cache.Path;1573const Path = std.Build.Cache.Path;
1576const Allocator = std.mem.Allocator;1574const Allocator = std.mem.Allocator;
1575const Writer = std.io.Writer;
15771576
1578const Diags = @import("../../link.zig").Diags;1577const Diags = @import("../../link.zig").Diags;
1579const Archive = @import("Archive.zig");1578const Archive = @import("Archive.zig");
src/link/Elf/SharedObject.zig+4-3
...@@ -509,7 +509,7 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void...@@ -509,7 +509,7 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void
509 }509 }
510}510}
511511
512pub fn format(self: SharedObject, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {512pub fn format(self: SharedObject, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
513 _ = self;513 _ = self;
514 _ = bw;514 _ = bw;
515 _ = unused_fmt_string;515 _ = unused_fmt_string;
...@@ -528,8 +528,8 @@ const FormatContext = struct {...@@ -528,8 +528,8 @@ const FormatContext = struct {
528 elf_file: *Elf,528 elf_file: *Elf,
529};529};
530530
531fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {531fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
532 _ = unused_fmt_string;532 comptime assert(unused_fmt_string.len == 0);
533 const shared = ctx.shared;533 const shared = ctx.shared;
534 const elf_file = ctx.elf_file;534 const elf_file = ctx.elf_file;
535 try bw.writeAll(" globals\n");535 try bw.writeAll(" globals\n");
...@@ -553,6 +553,7 @@ const mem = std.mem;...@@ -553,6 +553,7 @@ const mem = std.mem;
553const Path = std.Build.Cache.Path;553const Path = std.Build.Cache.Path;
554const Stat = std.Build.Cache.File.Stat;554const Stat = std.Build.Cache.File.Stat;
555const Allocator = mem.Allocator;555const Allocator = mem.Allocator;
556const Writer = std.io.Writer;
556557
557const Elf = @import("../Elf.zig");558const Elf = @import("../Elf.zig");
558const File = @import("file.zig").File;559const File = @import("file.zig").File;
src/link/Elf/Symbol.zig+7-6
...@@ -316,7 +316,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -316,7 +316,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
316 out.st_size = esym.st_size;316 out.st_size = esym.st_size;
317}317}
318318
319pub fn format(symbol: Symbol, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {319pub fn format(symbol: Symbol, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
320 _ = symbol;320 _ = symbol;
321 _ = bw;321 _ = bw;
322 _ = unused_fmt_string;322 _ = unused_fmt_string;
...@@ -335,7 +335,7 @@ pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(formatName) {...@@ -335,7 +335,7 @@ pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(formatName) {
335 } };335 } };
336}336}
337337
338fn formatName(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {338fn formatName(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
339 _ = unused_fmt_string;339 _ = unused_fmt_string;
340 const elf_file = ctx.elf_file;340 const elf_file = ctx.elf_file;
341 const symbol = ctx.symbol;341 const symbol = ctx.symbol;
...@@ -358,8 +358,8 @@ pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(format2) {...@@ -358,8 +358,8 @@ pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(format2) {
358 } };358 } };
359}359}
360360
361fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {361fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
362 _ = unused_fmt_string;362 comptime assert(unused_fmt_string.len == 0);
363 const symbol = ctx.symbol;363 const symbol = ctx.symbol;
364 const elf_file = ctx.elf_file;364 const elf_file = ctx.elf_file;
365 try bw.print("%{d} : {f} : @{x}", .{365 try bw.print("%{d} : {f} : @{x}", .{
...@@ -461,12 +461,13 @@ pub const Extra = struct {...@@ -461,12 +461,13 @@ pub const Extra = struct {
461461
462pub const Index = u32;462pub const Index = u32;
463463
464const std = @import("std");
464const assert = std.debug.assert;465const assert = std.debug.assert;
465const elf = std.elf;466const elf = std.elf;
466const mem = std.mem;467const mem = std.mem;
467const std = @import("std");468const Writer = std.io.Writer;
468const synthetic_sections = @import("synthetic_sections.zig");
469469
470const synthetic_sections = @import("synthetic_sections.zig");
470const Atom = @import("Atom.zig");471const Atom = @import("Atom.zig");
471const Elf = @import("../Elf.zig");472const Elf = @import("../Elf.zig");
472const File = @import("file.zig").File;473const File = @import("file.zig").File;
src/link/Elf/Thunk.zig+6-5
...@@ -65,7 +65,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {...@@ -65,7 +65,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {
65 };65 };
66}66}
6767
68pub fn format(thunk: Thunk, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {68pub fn format(thunk: Thunk, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
69 _ = thunk;69 _ = thunk;
70 _ = bw;70 _ = bw;
71 _ = unused_fmt_string;71 _ = unused_fmt_string;
...@@ -84,8 +84,8 @@ const FormatContext = struct {...@@ -84,8 +84,8 @@ const FormatContext = struct {
84 elf_file: *Elf,84 elf_file: *Elf,
85};85};
8686
87fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {87fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
88 _ = unused_fmt_string;88 comptime assert(unused_fmt_string.len == 0);
89 const thunk = ctx.thunk;89 const thunk = ctx.thunk;
90 const elf_file = ctx.elf_file;90 const elf_file = ctx.elf_file;
91 try bw.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });91 try bw.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
...@@ -117,14 +117,15 @@ const aarch64 = struct {...@@ -117,14 +117,15 @@ const aarch64 = struct {
117 const Instruction = util.Instruction;117 const Instruction = util.Instruction;
118};118};
119119
120const std = @import("std");
120const assert = std.debug.assert;121const assert = std.debug.assert;
121const elf = std.elf;122const elf = std.elf;
122const log = std.log.scoped(.link);123const log = std.log.scoped(.link);
123const math = std.math;124const math = std.math;
124const mem = std.mem;125const mem = std.mem;
125const std = @import("std");
126
127const Allocator = mem.Allocator;126const Allocator = mem.Allocator;
127const Writer = std.io.Writer;
128
128const Atom = @import("Atom.zig");129const Atom = @import("Atom.zig");
129const Elf = @import("../Elf.zig");130const Elf = @import("../Elf.zig");
130const Symbol = @import("Symbol.zig");131const Symbol = @import("Symbol.zig");
src/link/Elf/ZigObject.zig+4-3
...@@ -2198,7 +2198,7 @@ const FormatContext = struct {...@@ -2198,7 +2198,7 @@ const FormatContext = struct {
2198 elf_file: *Elf,2198 elf_file: *Elf,
2199};2199};
22002200
2201fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2201fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2202 _ = unused_fmt_string;2202 _ = unused_fmt_string;
2203 const self = ctx.self;2203 const self = ctx.self;
2204 const elf_file = ctx.elf_file;2204 const elf_file = ctx.elf_file;
...@@ -2221,8 +2221,8 @@ pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatAtoms)...@@ -2221,8 +2221,8 @@ pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatAtoms)
2221 } };2221 } };
2222}2222}
22232223
2224fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2224fn formatAtoms(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2225 _ = unused_fmt_string;2225 comptime assert(unused_fmt_string.len == 0);
2226 try bw.writeAll(" atoms\n");2226 try bw.writeAll(" atoms\n");
2227 for (ctx.self.atoms_indexes.items) |atom_index| {2227 for (ctx.self.atoms_indexes.items) |atom_index| {
2228 const atom_ptr = ctx.self.atom(atom_index) orelse continue;2228 const atom_ptr = ctx.self.atom(atom_index) orelse continue;
...@@ -2326,6 +2326,7 @@ const target_util = @import("../../target.zig");...@@ -2326,6 +2326,7 @@ const target_util = @import("../../target.zig");
2326const trace = @import("../../tracy.zig").trace;2326const trace = @import("../../tracy.zig").trace;
2327const std = @import("std");2327const std = @import("std");
2328const Allocator = std.mem.Allocator;2328const Allocator = std.mem.Allocator;
2329const Writer = std.io.Writer;
23292330
2330const Archive = @import("Archive.zig");2331const Archive = @import("Archive.zig");
2331const Atom = @import("Atom.zig");2332const Atom = @import("Atom.zig");
src/link/Elf/eh_frame.zig+10-9
...@@ -49,7 +49,7 @@ pub const Fde = struct {...@@ -49,7 +49,7 @@ pub const Fde = struct {
4949
50 pub fn format(50 pub fn format(
51 fde: Fde,51 fde: Fde,
52 bw: *std.io.BufferedWriter,52 bw: *Writer,
53 comptime unused_fmt_string: []const u8,53 comptime unused_fmt_string: []const u8,
54 ) !void {54 ) !void {
55 _ = fde;55 _ = fde;
...@@ -72,7 +72,7 @@ pub const Fde = struct {...@@ -72,7 +72,7 @@ pub const Fde = struct {
7272
73 fn format2(73 fn format2(
74 ctx: FdeFormatContext,74 ctx: FdeFormatContext,
75 bw: *std.io.BufferedWriter,75 bw: *Writer,
76 comptime unused_fmt_string: []const u8,76 comptime unused_fmt_string: []const u8,
77 ) !void {77 ) !void {
78 _ = unused_fmt_string;78 _ = unused_fmt_string;
...@@ -148,7 +148,7 @@ pub const Cie = struct {...@@ -148,7 +148,7 @@ pub const Cie = struct {
148148
149 pub fn format(149 pub fn format(
150 cie: Cie,150 cie: Cie,
151 bw: *std.io.BufferedWriter,151 bw: *Writer,
152 comptime unused_fmt_string: []const u8,152 comptime unused_fmt_string: []const u8,
153 ) !void {153 ) !void {
154 _ = cie;154 _ = cie;
...@@ -171,7 +171,7 @@ pub const Cie = struct {...@@ -171,7 +171,7 @@ pub const Cie = struct {
171171
172 fn format2(172 fn format2(
173 ctx: CieFormatContext,173 ctx: CieFormatContext,
174 bw: *std.io.BufferedWriter,174 bw: *Writer,
175 comptime unused_fmt_string: []const u8,175 comptime unused_fmt_string: []const u8,
176 ) !void {176 ) !void {
177 _ = unused_fmt_string;177 _ = unused_fmt_string;
...@@ -319,7 +319,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -319,7 +319,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
319 }319 }
320}320}
321321
322pub fn writeEhFrame(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {322pub fn writeEhFrame(elf_file: *Elf, bw: *Writer) !void {
323 relocs_log.debug("{x}: .eh_frame", .{323 relocs_log.debug("{x}: .eh_frame", .{
324 elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr,324 elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr,
325 });325 });
...@@ -380,7 +380,7 @@ pub fn writeEhFrame(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {...@@ -380,7 +380,7 @@ pub fn writeEhFrame(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {
380 if (has_reloc_errors) return error.RelocFailure;380 if (has_reloc_errors) return error.RelocFailure;
381}381}
382382
383pub fn writeEhFrameRelocatable(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {383pub fn writeEhFrameRelocatable(elf_file: *Elf, bw: *Writer) !void {
384 for (elf_file.objects.items) |index| {384 for (elf_file.objects.items) |index| {
385 const object = elf_file.file(index).?.object;385 const object = elf_file.file(index).?.object;
386386
...@@ -482,7 +482,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, relocs: *std.ArrayList(elf.Elf64_Rela)...@@ -482,7 +482,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, relocs: *std.ArrayList(elf.Elf64_Rela)
482 }482 }
483}483}
484484
485pub fn writeEhFrameHdr(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {485pub fn writeEhFrameHdr(elf_file: *Elf, bw: *Writer) !void {
486 const comp = elf_file.base.comp;486 const comp = elf_file.base.comp;
487 const gpa = comp.gpa;487 const gpa = comp.gpa;
488488
...@@ -607,9 +607,10 @@ const assert = std.debug.assert;...@@ -607,9 +607,10 @@ const assert = std.debug.assert;
607const elf = std.elf;607const elf = std.elf;
608const math = std.math;608const math = std.math;
609const relocs_log = std.log.scoped(.link_relocs);609const relocs_log = std.log.scoped(.link_relocs);
610const relocation = @import("relocation.zig");610const Writer = std.io.Writer;
611
612const Allocator = std.mem.Allocator;611const Allocator = std.mem.Allocator;
612
613const relocation = @import("relocation.zig");
613const Atom = @import("Atom.zig");614const Atom = @import("Atom.zig");
614const DW_EH_PE = std.dwarf.EH.PE;615const DW_EH_PE = std.dwarf.EH.PE;
615const Elf = @import("../Elf.zig");616const Elf = @import("../Elf.zig");
src/link/Elf/file.zig+4-2
...@@ -14,8 +14,8 @@ pub const File = union(enum) {...@@ -14,8 +14,8 @@ pub const File = union(enum) {
14 return .{ .data = file };14 return .{ .data = file };
15 }15 }
1616
17 fn formatPath(file: File, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {17 fn formatPath(file: File, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
18 _ = unused_fmt_string;18 comptime assert(unused_fmt_string.len == 0);
19 switch (file) {19 switch (file) {
20 .zig_object => |zo| try bw.writeAll(zo.basename),20 .zig_object => |zo| try bw.writeAll(zo.basename),
21 .linker_defined => try bw.writeAll("(linker defined)"),21 .linker_defined => try bw.writeAll("(linker defined)"),
...@@ -289,6 +289,8 @@ const elf = std.elf;...@@ -289,6 +289,8 @@ const elf = std.elf;
289const log = std.log.scoped(.link);289const log = std.log.scoped(.link);
290const Path = std.Build.Cache.Path;290const Path = std.Build.Cache.Path;
291const Allocator = std.mem.Allocator;291const Allocator = std.mem.Allocator;
292const Writer = std.io.Writer;
293const assert = std.debug.assert;
292294
293const Archive = @import("Archive.zig");295const Archive = @import("Archive.zig");
294const Atom = @import("Atom.zig");296const Atom = @import("Atom.zig");
src/link/Elf/gc.zig+4-3
...@@ -185,8 +185,8 @@ const Level = struct {...@@ -185,8 +185,8 @@ const Level = struct {
185 self.value += 1;185 self.value += 1;
186 }186 }
187187
188 pub fn format(self: *const @This(), bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {188 pub fn format(self: *const @This(), bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
189 _ = unused_fmt_string;189 comptime assert(unused_fmt_string.len == 0);
190 try bw.splatByteAll(' ', self.value);190 try bw.splatByteAll(' ', self.value);
191 }191 }
192};192};
...@@ -198,8 +198,9 @@ const assert = std.debug.assert;...@@ -198,8 +198,9 @@ const assert = std.debug.assert;
198const elf = std.elf;198const elf = std.elf;
199const gc_track_live_log = std.log.scoped(.gc_track_live);199const gc_track_live_log = std.log.scoped(.gc_track_live);
200const mem = std.mem;200const mem = std.mem;
201
202const Allocator = mem.Allocator;201const Allocator = mem.Allocator;
202const Writer = std.io.Writer;
203
203const Atom = @import("Atom.zig");204const Atom = @import("Atom.zig");
204const Elf = @import("../Elf.zig");205const Elf = @import("../Elf.zig");
205const File = @import("file.zig").File;206const File = @import("file.zig").File;
src/link/Elf/relocatable.zig+7-8
...@@ -100,8 +100,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -100,8 +100,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
101 }101 }
102102
103 var bw: std.io.BufferedWriter = undefined;103 var bw: Writer = .fixed(try gpa.alloc(u8, total_size));
104 bw.initFixed(try gpa.alloc(u8, total_size));
105 defer gpa.free(bw.buffer);104 defer gpa.free(bw.buffer);
106105
107 // Write magic106 // Write magic
...@@ -406,8 +405,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -406,8 +405,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
406 };405 };
407 const shdr = slice.items(.shdr)[shndx];406 const shdr = slice.items(.shdr)[shndx];
408 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;407 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
409 var bw: std.io.BufferedWriter = undefined;408 var bw: Writer = .fixed(try gpa.alloc(u8, sh_size - existing_size));
410 bw.initFixed(try gpa.alloc(u8, sh_size - existing_size));
411 defer gpa.free(bw.buffer);409 defer gpa.free(bw.buffer);
412 try eh_frame.writeEhFrameRelocatable(elf_file, &bw);410 try eh_frame.writeEhFrameRelocatable(elf_file, &bw);
413 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{411 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{
...@@ -458,18 +456,19 @@ fn writeGroups(elf_file: *Elf) !void {...@@ -458,18 +456,19 @@ fn writeGroups(elf_file: *Elf) !void {
458 }456 }
459}457}
460458
459const std = @import("std");
461const assert = std.debug.assert;460const assert = std.debug.assert;
462const build_options = @import("build_options");
463const eh_frame = @import("eh_frame.zig");
464const elf = std.elf;461const elf = std.elf;
465const link = @import("../../link.zig");
466const log = std.log.scoped(.link);462const log = std.log.scoped(.link);
467const math = std.math;463const math = std.math;
468const mem = std.mem;464const mem = std.mem;
469const state_log = std.log.scoped(.link_state);465const state_log = std.log.scoped(.link_state);
470const Path = std.Build.Cache.Path;466const Path = std.Build.Cache.Path;
471const std = @import("std");467const Writer = std.io.Writer;
472468
469const link = @import("../../link.zig");
470const build_options = @import("build_options");
471const eh_frame = @import("eh_frame.zig");
473const Archive = @import("Archive.zig");472const Archive = @import("Archive.zig");
474const Compilation = @import("../../Compilation.zig");473const Compilation = @import("../../Compilation.zig");
475const Elf = @import("../Elf.zig");474const Elf = @import("../Elf.zig");
src/link/Elf/relocation.zig+4-3
...@@ -148,8 +148,8 @@ pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatte...@@ -148,8 +148,8 @@ pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatte
148 } };148 } };
149}149}
150150
151fn formatRelocType(ctx: FormatRelocTypeCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {151fn formatRelocType(ctx: FormatRelocTypeCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
152 _ = unused_fmt_string;152 comptime assert(unused_fmt_string.len == 0);
153 const r_type = ctx.r_type;153 const r_type = ctx.r_type;
154 switch (ctx.cpu_arch) {154 switch (ctx.cpu_arch) {
155 .x86_64 => try bw.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),155 .x86_64 => try bw.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),
...@@ -159,9 +159,10 @@ fn formatRelocType(ctx: FormatRelocTypeCtx, bw: *std.io.BufferedWriter, comptime...@@ -159,9 +159,10 @@ fn formatRelocType(ctx: FormatRelocTypeCtx, bw: *std.io.BufferedWriter, comptime
159 }159 }
160}160}
161161
162const std = @import("std");
162const assert = std.debug.assert;163const assert = std.debug.assert;
163const elf = std.elf;164const elf = std.elf;
164const std = @import("std");165const Writer = std.io.Writer;
165166
166const Dwarf = @import("../Dwarf.zig");167const Dwarf = @import("../Dwarf.zig");
167const Elf = @import("../Elf.zig");168const Elf = @import("../Elf.zig");
src/link/Elf/synthetic_sections.zig+22-20
...@@ -94,7 +94,7 @@ pub const DynamicSection = struct {...@@ -94,7 +94,7 @@ pub const DynamicSection = struct {
94 return nentries * @sizeOf(elf.Elf64_Dyn);94 return nentries * @sizeOf(elf.Elf64_Dyn);
95 }95 }
9696
97 pub fn write(dt: DynamicSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {97 pub fn write(dt: DynamicSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
98 const shdrs = elf_file.sections.items(.shdr);98 const shdrs = elf_file.sections.items(.shdr);
9999
100 // NEEDED100 // NEEDED
...@@ -360,7 +360,7 @@ pub const GotSection = struct {...@@ -360,7 +360,7 @@ pub const GotSection = struct {
360 return s;360 return s;
361 }361 }
362362
363 pub fn write(got: GotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {363 pub fn write(got: GotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
364 const comp = elf_file.base.comp;364 const comp = elf_file.base.comp;
365 const is_dyn_lib = elf_file.isEffectivelyDynLib();365 const is_dyn_lib = elf_file.isEffectivelyDynLib();
366 const apply_relocs = true; // TODO add user option for this366 const apply_relocs = true; // TODO add user option for this
...@@ -615,7 +615,7 @@ pub const GotSection = struct {...@@ -615,7 +615,7 @@ pub const GotSection = struct {
615 return .{ .data = .{ .got = got, .elf_file = elf_file } };615 return .{ .data = .{ .got = got, .elf_file = elf_file } };
616 }616 }
617617
618 pub fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {618 pub fn format2(ctx: FormatCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
619 _ = unused_fmt_string;619 _ = unused_fmt_string;
620 const got = ctx.got;620 const got = ctx.got;
621 const elf_file = ctx.elf_file;621 const elf_file = ctx.elf_file;
...@@ -672,7 +672,7 @@ pub const PltSection = struct {...@@ -672,7 +672,7 @@ pub const PltSection = struct {
672 };672 };
673 }673 }
674674
675 pub fn write(plt: PltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {675 pub fn write(plt: PltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
676 const cpu_arch = elf_file.getTarget().cpu.arch;676 const cpu_arch = elf_file.getTarget().cpu.arch;
677 switch (cpu_arch) {677 switch (cpu_arch) {
678 .x86_64 => try x86_64.write(plt, elf_file, bw),678 .x86_64 => try x86_64.write(plt, elf_file, bw),
...@@ -752,7 +752,7 @@ pub const PltSection = struct {...@@ -752,7 +752,7 @@ pub const PltSection = struct {
752 return .{ .data = .{ .plt = plt, .elf_file = elf_file } };752 return .{ .data = .{ .plt = plt, .elf_file = elf_file } };
753 }753 }
754754
755 pub fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {755 pub fn format2(ctx: FormatCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
756 _ = unused_fmt_string;756 _ = unused_fmt_string;
757 const plt = ctx.plt;757 const plt = ctx.plt;
758 const elf_file = ctx.elf_file;758 const elf_file = ctx.elf_file;
...@@ -770,7 +770,7 @@ pub const PltSection = struct {...@@ -770,7 +770,7 @@ pub const PltSection = struct {
770 }770 }
771771
772 const x86_64 = struct {772 const x86_64 = struct {
773 fn write(plt: PltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {773 fn write(plt: PltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
774 const shdrs = elf_file.sections.items(.shdr);774 const shdrs = elf_file.sections.items(.shdr);
775 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;775 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;
776 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;776 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
...@@ -805,7 +805,7 @@ pub const PltSection = struct {...@@ -805,7 +805,7 @@ pub const PltSection = struct {
805 };805 };
806806
807 const aarch64 = struct {807 const aarch64 = struct {
808 fn write(plt: PltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {808 fn write(plt: PltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
809 {809 {
810 const shdrs = elf_file.sections.items(.shdr);810 const shdrs = elf_file.sections.items(.shdr);
811 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);811 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);
...@@ -871,7 +871,7 @@ pub const GotPltSection = struct {...@@ -871,7 +871,7 @@ pub const GotPltSection = struct {
871 return preamble_size + elf_file.plt.symbols.items.len * 8;871 return preamble_size + elf_file.plt.symbols.items.len * 8;
872 }872 }
873873
874 pub fn write(got_plt: GotPltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {874 pub fn write(got_plt: GotPltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
875 _ = got_plt;875 _ = got_plt;
876 {876 {
877 // [0]: _DYNAMIC877 // [0]: _DYNAMIC
...@@ -922,7 +922,7 @@ pub const PltGotSection = struct {...@@ -922,7 +922,7 @@ pub const PltGotSection = struct {
922 };922 };
923 }923 }
924924
925 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {925 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
926 const cpu_arch = elf_file.getTarget().cpu.arch;926 const cpu_arch = elf_file.getTarget().cpu.arch;
927 switch (cpu_arch) {927 switch (cpu_arch) {
928 .x86_64 => try x86_64.write(plt_got, elf_file, bw),928 .x86_64 => try x86_64.write(plt_got, elf_file, bw),
...@@ -958,7 +958,7 @@ pub const PltGotSection = struct {...@@ -958,7 +958,7 @@ pub const PltGotSection = struct {
958 }958 }
959959
960 const x86_64 = struct {960 const x86_64 = struct {
961 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {961 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
962 for (plt_got.symbols.items) |ref| {962 for (plt_got.symbols.items) |ref| {
963 const sym = elf_file.symbol(ref).?;963 const sym = elf_file.symbol(ref).?;
964 const target_addr = sym.gotAddress(elf_file);964 const target_addr = sym.gotAddress(elf_file);
...@@ -976,7 +976,7 @@ pub const PltGotSection = struct {...@@ -976,7 +976,7 @@ pub const PltGotSection = struct {
976 };976 };
977977
978 const aarch64 = struct {978 const aarch64 = struct {
979 fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {979 fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
980 for (plt_got.symbols.items) |ref| {980 for (plt_got.symbols.items) |ref| {
981 const sym = elf_file.symbol(ref).?;981 const sym = elf_file.symbol(ref).?;
982 const target_addr = sym.gotAddress(elf_file);982 const target_addr = sym.gotAddress(elf_file);
...@@ -1155,7 +1155,7 @@ pub const DynsymSection = struct {...@@ -1155,7 +1155,7 @@ pub const DynsymSection = struct {
1155 return @as(u32, @intCast(dynsym.entries.items.len + 1));1155 return @as(u32, @intCast(dynsym.entries.items.len + 1));
1156 }1156 }
11571157
1158 pub fn write(dynsym: DynsymSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1158 pub fn write(dynsym: DynsymSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
1159 try bw.writeStruct(Elf.null_sym);1159 try bw.writeStruct(Elf.null_sym);
1160 for (dynsym.entries.items) |entry| {1160 for (dynsym.entries.items) |entry| {
1161 const sym = elf_file.symbol(entry.ref).?;1161 const sym = elf_file.symbol(entry.ref).?;
...@@ -1249,7 +1249,7 @@ pub const GnuHashSection = struct {...@@ -1249,7 +1249,7 @@ pub const GnuHashSection = struct {
1249 return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4;1249 return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4;
1250 }1250 }
12511251
1252 pub fn write(hash: GnuHashSection, elf_file: *Elf, br: *std.io.BufferedWriter) !void {1252 pub fn write(hash: GnuHashSection, elf_file: *Elf, br: *Writer) !void {
1253 const exports = getExports(elf_file);1253 const exports = getExports(elf_file);
1254 const export_off = elf_file.dynsym.count() - hash.num_exports;1254 const export_off = elf_file.dynsym.count() - hash.num_exports;
12551255
...@@ -1458,7 +1458,7 @@ pub const VerneedSection = struct {...@@ -1458,7 +1458,7 @@ pub const VerneedSection = struct {
1458 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);1458 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);
1459 }1459 }
14601460
1461 pub fn write(vern: VerneedSection, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1461 pub fn write(vern: VerneedSection, bw: *Writer) Writer.Error!void {
1462 try bw.writeAll(mem.sliceAsBytes(vern.verneed.items));1462 try bw.writeAll(mem.sliceAsBytes(vern.verneed.items));
1463 try bw.writeAll(mem.sliceAsBytes(vern.vernaux.items));1463 try bw.writeAll(mem.sliceAsBytes(vern.vernaux.items));
1464 }1464 }
...@@ -1486,7 +1486,7 @@ pub const GroupSection = struct {...@@ -1486,7 +1486,7 @@ pub const GroupSection = struct {
1486 return (members.len + 1) * @sizeOf(u32);1486 return (members.len + 1) * @sizeOf(u32);
1487 }1487 }
14881488
1489 pub fn write(cgs: GroupSection, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1489 pub fn write(cgs: GroupSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {
1490 const cg = cgs.comdatGroup(elf_file);1490 const cg = cgs.comdatGroup(elf_file);
1491 const object = cg.file(elf_file).object;1491 const object = cg.file(elf_file).object;
1492 const members = cg.members(elf_file);1492 const members = cg.members(elf_file);
...@@ -1514,7 +1514,7 @@ pub const GroupSection = struct {...@@ -1514,7 +1514,7 @@ pub const GroupSection = struct {
1514 }1514 }
1515};1515};
15161516
1517fn writeInt(value: anytype, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1517fn writeInt(value: anytype, elf_file: *Elf, bw: *Writer) Writer.Error!void {
1518 const entry_size = elf_file.archPtrWidthBytes();1518 const entry_size = elf_file.archPtrWidthBytes();
1519 const target = elf_file.getTarget();1519 const target = elf_file.getTarget();
1520 const endian = target.cpu.arch.endian();1520 const endian = target.cpu.arch.endian();
...@@ -1526,17 +1526,19 @@ fn writeInt(value: anytype, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.W...@@ -1526,17 +1526,19 @@ fn writeInt(value: anytype, elf_file: *Elf, bw: *std.io.BufferedWriter) std.io.W
1526 }1526 }
1527}1527}
15281528
1529const assert = std.debug.assert;
1530const builtin = @import("builtin");1529const builtin = @import("builtin");
1530
1531const std = @import("std");
1532const assert = std.debug.assert;
1531const elf = std.elf;1533const elf = std.elf;
1532const math = std.math;1534const math = std.math;
1533const mem = std.mem;1535const mem = std.mem;
1534const log = std.log.scoped(.link);1536const log = std.log.scoped(.link);
1535const relocs_log = std.log.scoped(.link_relocs);1537const relocs_log = std.log.scoped(.link_relocs);
1536const relocation = @import("relocation.zig");
1537const std = @import("std");
1538
1539const Allocator = std.mem.Allocator;1538const Allocator = std.mem.Allocator;
1539const Writer = std.io.Writer;
1540
1541const relocation = @import("relocation.zig");
1540const Elf = @import("../Elf.zig");1542const Elf = @import("../Elf.zig");
1541const File = @import("file.zig").File;1543const File = @import("file.zig").File;
1542const SharedObject = @import("SharedObject.zig");1544const SharedObject = @import("SharedObject.zig");
src/link/MachO.zig+17-24
...@@ -2527,8 +2527,7 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void {...@@ -2527,8 +2527,7 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void {
25272527
2528 const doWork = struct {2528 const doWork = struct {
2529 fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void {2529 fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void {
2530 var bw: std.io.BufferedWriter = undefined;2530 var bw: Writer = .fixed(buffer[try macho_file.cast(usize, th.value)..][0..th.size()]);
2531 bw.initFixed(buffer[try macho_file.cast(usize, th.value)..][0..th.size()]);
2532 try th.write(macho_file, &bw);2531 try th.write(macho_file, &bw);
2533 }2532 }
2534 }.doWork;2533 }.doWork;
...@@ -2556,8 +2555,7 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void {...@@ -2556,8 +2555,7 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void {
25562555
2557 const doWork = struct {2556 const doWork = struct {
2558 fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void {2557 fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void {
2559 var bw: std.io.BufferedWriter = undefined;2558 var bw: Writer = .fixed(buffer);
2560 bw.initFixed(buffer);
2561 switch (tag) {2559 switch (tag) {
2562 .eh_frame => eh_frame.write(macho_file, buffer),2560 .eh_frame => eh_frame.write(macho_file, buffer),
2563 .unwind_info => try macho_file.unwind_info.write(macho_file, &bw),2561 .unwind_info => try macho_file.unwind_info.write(macho_file, &bw),
...@@ -2606,8 +2604,7 @@ fn updateLazyBindSizeWorker(self: *MachO) void {...@@ -2606,8 +2604,7 @@ fn updateLazyBindSizeWorker(self: *MachO) void {
2606 try macho_file.lazy_bind_section.updateSize(macho_file);2604 try macho_file.lazy_bind_section.updateSize(macho_file);
2607 const sect_id = macho_file.stubs_helper_sect_index.?;2605 const sect_id = macho_file.stubs_helper_sect_index.?;
2608 const out = &macho_file.sections.items(.out)[sect_id];2606 const out = &macho_file.sections.items(.out)[sect_id];
2609 var bw: std.io.BufferedWriter = undefined;2607 var bw: Writer = .fixed(out.items);
2610 bw.initFixed(out.items);
2611 try macho_file.stubs_helper.write(macho_file, &bw);2608 try macho_file.stubs_helper.write(macho_file, &bw);
2612 }2609 }
2613 }.doWork;2610 }.doWork;
...@@ -2667,8 +2664,7 @@ fn writeDyldInfo(self: *MachO) !void {...@@ -2667,8 +2664,7 @@ fn writeDyldInfo(self: *MachO) !void {
2667 needed_size += cmd.lazy_bind_size;2664 needed_size += cmd.lazy_bind_size;
2668 needed_size += cmd.export_size;2665 needed_size += cmd.export_size;
26692666
2670 var bw: std.io.BufferedWriter = undefined;2667 var bw: Writer = .fixed(try gpa.alloc(u8, needed_size));
2671 bw.initFixed(try gpa.alloc(u8, needed_size));
2672 defer gpa.free(bw.buffer);2668 defer gpa.free(bw.buffer);
2673 @memset(bw.buffer, 0);2669 @memset(bw.buffer, 0);
26742670
...@@ -2690,8 +2686,7 @@ pub fn writeDataInCode(self: *MachO) !void {...@@ -2690,8 +2686,7 @@ pub fn writeDataInCode(self: *MachO) !void {
2690 const gpa = self.base.comp.gpa;2686 const gpa = self.base.comp.gpa;
2691 const cmd = self.data_in_code_cmd;2687 const cmd = self.data_in_code_cmd;
26922688
2693 var bw: std.io.BufferedWriter = undefined;2689 var bw: Writer = .fixed(try gpa.alloc(u8, self.data_in_code.size()));
2694 bw.initFixed(try gpa.alloc(u8, self.data_in_code.size()));
2695 defer gpa.free(bw.buffer);2690 defer gpa.free(bw.buffer);
26962691
2697 try self.data_in_code.write(self, &bw);2692 try self.data_in_code.write(self, &bw);
...@@ -2706,8 +2701,7 @@ fn writeIndsymtab(self: *MachO) !void {...@@ -2706,8 +2701,7 @@ fn writeIndsymtab(self: *MachO) !void {
2706 const gpa = self.base.comp.gpa;2701 const gpa = self.base.comp.gpa;
2707 const cmd = self.dysymtab_cmd;2702 const cmd = self.dysymtab_cmd;
27082703
2709 var bw: std.io.BufferedWriter = undefined;2704 var bw: Writer = .fixed(try gpa.alloc(u8, @sizeOf(u32) * cmd.nindirectsyms));
2710 bw.initFixed(try gpa.alloc(u8, @sizeOf(u32) * cmd.nindirectsyms));
2711 defer gpa.free(bw.buffer);2705 defer gpa.free(bw.buffer);
27122706
2713 try self.indsymtab.write(self, &bw);2707 try self.indsymtab.write(self, &bw);
...@@ -2822,12 +2816,11 @@ fn calcSymtabSize(self: *MachO) !void {...@@ -2822,12 +2816,11 @@ fn calcSymtabSize(self: *MachO) !void {
2822 }2816 }
2823}2817}
28242818
2825fn writeLoadCommands(self: *MachO) std.io.Writer.Error!struct { usize, usize, u64 } {2819fn writeLoadCommands(self: *MachO) Writer.Error!struct { usize, usize, u64 } {
2826 const comp = self.base.comp;2820 const comp = self.base.comp;
2827 const gpa = comp.gpa;2821 const gpa = comp.gpa;
28282822
2829 var bw: std.io.BufferedWriter = undefined;2823 var bw: Writer = .fixed(try gpa.alloc(u8, try load_commands.calcLoadCommandsSize(self, false)));
2830 bw.initFixed(try gpa.alloc(u8, try load_commands.calcLoadCommandsSize(self, false)));
2831 defer gpa.free(bw.buffer);2824 defer gpa.free(bw.buffer);
28322825
2833 var ncmds: usize = 0;2826 var ncmds: usize = 0;
...@@ -3021,8 +3014,7 @@ pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void {...@@ -3021,8 +3014,7 @@ pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void {
3021 const seg = self.getTextSegment();3014 const seg = self.getTextSegment();
3022 const offset = self.codesig_cmd.dataoff;3015 const offset = self.codesig_cmd.dataoff;
30233016
3024 var bw: std.io.BufferedWriter = undefined;3017 var bw: Writer = .fixed(try gpa.alloc(u8, code_sig.size()));
3025 bw.initFixed(try gpa.alloc(u8, code_sig.size()));
3026 defer gpa.free(bw.buffer);3018 defer gpa.free(bw.buffer);
3027 try code_sig.writeAdhocSignature(self, .{3019 try code_sig.writeAdhocSignature(self, .{
3028 .file = self.base.file.?,3020 .file = self.base.file.?,
...@@ -3910,7 +3902,7 @@ pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) {...@@ -3910,7 +3902,7 @@ pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) {
3910 return .{ .data = self };3902 return .{ .data = self };
3911}3903}
39123904
3913fn fmtDumpState(self: *MachO, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {3905fn fmtDumpState(self: *MachO, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
3914 _ = unused_fmt_string;3906 _ = unused_fmt_string;
3915 if (self.getZigObject()) |zo| {3907 if (self.getZigObject()) |zo| {
3916 try bw.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename });3908 try bw.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename });
...@@ -3969,7 +3961,7 @@ fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) {...@@ -3969,7 +3961,7 @@ fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) {
3969 return .{ .data = self };3961 return .{ .data = self };
3970}3962}
39713963
3972fn formatSections(self: *MachO, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {3964fn formatSections(self: *MachO, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
3973 _ = unused_fmt_string;3965 _ = unused_fmt_string;
3974 const slice = self.sections.slice();3966 const slice = self.sections.slice();
3975 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {3967 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {
...@@ -3987,7 +3979,7 @@ fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) {...@@ -3987,7 +3979,7 @@ fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) {
3987 return .{ .data = self };3979 return .{ .data = self };
3988}3980}
39893981
3990fn formatSegments(self: *MachO, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {3982fn formatSegments(self: *MachO, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
3991 _ = unused_fmt_string;3983 _ = unused_fmt_string;
3992 for (self.segments.items, 0..) |seg, i| {3984 for (self.segments.items, 0..) |seg, i| {
3993 try bw.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{3985 try bw.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{
...@@ -4001,7 +3993,7 @@ pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) {...@@ -4001,7 +3993,7 @@ pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) {
4001 return .{ .data = tt };3993 return .{ .data = tt };
4002}3994}
40033995
4004fn formatSectType(tt: u8, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {3996fn formatSectType(tt: u8, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
4005 _ = unused_fmt_string;3997 _ = unused_fmt_string;
4006 const name = switch (tt) {3998 const name = switch (tt) {
4007 macho.S_REGULAR => "REGULAR",3999 macho.S_REGULAR => "REGULAR",
...@@ -4270,7 +4262,7 @@ pub const Platform = struct {...@@ -4270,7 +4262,7 @@ pub const Platform = struct {
4270 cpu_arch: std.Target.Cpu.Arch,4262 cpu_arch: std.Target.Cpu.Arch,
4271 };4263 };
42724264
4273 pub fn formatTarget(ctx: FmtCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {4265 pub fn formatTarget(ctx: FmtCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
4274 _ = unused_fmt_string;4266 _ = unused_fmt_string;
4275 try bw.print("{s}-{s}", .{ @tagName(ctx.cpu_arch), @tagName(ctx.platform.os_tag) });4267 try bw.print("{s}-{s}", .{ @tagName(ctx.cpu_arch), @tagName(ctx.platform.os_tag) });
4276 if (ctx.platform.abi != .none) {4268 if (ctx.platform.abi != .none) {
...@@ -4483,8 +4475,8 @@ pub const Ref = struct {...@@ -4483,8 +4475,8 @@ pub const Ref = struct {
4483 };4475 };
4484 }4476 }
44854477
4486 pub fn format(ref: Ref, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {4478 pub fn format(ref: Ref, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
4487 _ = unused_fmt_string;4479 comptime assert(unused_fmt_string.len == 0);
4488 try bw.print("%{d} in file({d})", .{ ref.index, ref.file });4480 try bw.print("%{d} in file({d})", .{ ref.index, ref.file });
4489 }4481 }
4490};4482};
...@@ -5387,6 +5379,7 @@ const macho = std.macho;...@@ -5387,6 +5379,7 @@ const macho = std.macho;
5387const math = std.math;5379const math = std.math;
5388const mem = std.mem;5380const mem = std.mem;
5389const meta = std.meta;5381const meta = std.meta;
5382const Writer = std.io.Writer;
53905383
5391const aarch64 = @import("../arch/aarch64/bits.zig");5384const aarch64 = @import("../arch/aarch64/bits.zig");
5392const bind = @import("MachO/dyld_info/bind.zig");5385const bind = @import("MachO/dyld_info/bind.zig");
src/link/MachO/Archive.zig+7-6
...@@ -78,11 +78,11 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File...@@ -78,11 +78,11 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
78}78}
7979
80pub fn writeHeader(80pub fn writeHeader(
81 bw: *std.io.BufferedWriter,81 bw: *Writer,
82 object_name: []const u8,82 object_name: []const u8,
83 object_size: usize,83 object_size: usize,
84 format: Format,84 format: Format,
85) std.io.Writer.Error!void {85) Writer.Error!void {
86 var hdr: ar_hdr = undefined;86 var hdr: ar_hdr = undefined;
87 @memset(mem.asBytes(&hdr), ' ');87 @memset(mem.asBytes(&hdr), ' ');
88 inline for (@typeInfo(ar_hdr).@"struct".fields) |field| @field(hdr, field.name)[0] = '0';88 inline for (@typeInfo(ar_hdr).@"struct".fields) |field| @field(hdr, field.name)[0] = '0';
...@@ -177,7 +177,7 @@ pub const ArSymtab = struct {...@@ -177,7 +177,7 @@ pub const ArSymtab = struct {
177 return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);177 return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);
178 }178 }
179179
180 pub fn write(ar: ArSymtab, bw: *std.io.BufferedWriter, format: Format, macho_file: *MachO) std.io.Writer.Error!void {180 pub fn write(ar: ArSymtab, bw: *Writer, format: Format, macho_file: *MachO) Writer.Error!void {
181 const ptr_width = ptrWidth(format);181 const ptr_width = ptrWidth(format);
182 // Header182 // Header
183 try writeHeader(bw, SYMDEF, ar.size(format), format);183 try writeHeader(bw, SYMDEF, ar.size(format), format);
...@@ -212,7 +212,7 @@ pub const ArSymtab = struct {...@@ -212,7 +212,7 @@ pub const ArSymtab = struct {
212 return .{ .data = .{ .ar = ar, .macho_file = macho_file } };212 return .{ .data = .{ .ar = ar, .macho_file = macho_file } };
213 }213 }
214214
215 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {215 fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
216 _ = unused_fmt_string;216 _ = unused_fmt_string;
217 const ar = ctx.ar;217 const ar = ctx.ar;
218 const macho_file = ctx.macho_file;218 const macho_file = ctx.macho_file;
...@@ -249,7 +249,7 @@ pub fn ptrWidth(format: Format) usize {...@@ -249,7 +249,7 @@ pub fn ptrWidth(format: Format) usize {
249 };249 };
250}250}
251251
252pub fn writeInt(bw: *std.io.BufferedWriter, format: Format, value: u64) std.io.Writer.Error!void {252pub fn writeInt(bw: *Writer, format: Format, value: u64) Writer.Error!void {
253 switch (format) {253 switch (format) {
254 .p32 => try bw.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little),254 .p32 => try bw.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little),
255 .p64 => try bw.writeInt(u64, value, .little),255 .p64 => try bw.writeInt(u64, value, .little),
...@@ -271,8 +271,9 @@ const log = std.log.scoped(.link);...@@ -271,8 +271,9 @@ const log = std.log.scoped(.link);
271const macho = std.macho;271const macho = std.macho;
272const mem = std.mem;272const mem = std.mem;
273const std = @import("std");273const std = @import("std");
274const Allocator = mem.Allocator;274const Allocator = std.mem.Allocator;
275const Path = std.Build.Cache.Path;275const Path = std.Build.Cache.Path;
276const Writer = std.io.Writer;
276277
277const Archive = @This();278const Archive = @This();
278const File = @import("file.zig").File;279const File = @import("file.zig").File;
src/link/MachO/Atom.zig+12-13
...@@ -580,8 +580,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -580,8 +580,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
580580
581 relocs_log.debug("{x}: {s}", .{ self.value, name });581 relocs_log.debug("{x}: {s}", .{ self.value, name });
582582
583 var bw: std.io.BufferedWriter = undefined;583 var bw: Writer = .fixed(buffer);
584 bw.initFixed(buffer);
585584
586 var has_error = false;585 var has_error = false;
587 var i: usize = 0;586 var i: usize = 0;
...@@ -638,8 +637,8 @@ fn resolveRelocInner(...@@ -638,8 +637,8 @@ fn resolveRelocInner(
638 subtractor: ?Relocation,637 subtractor: ?Relocation,
639 code: []u8,638 code: []u8,
640 macho_file: *MachO,639 macho_file: *MachO,
641 bw: *std.io.BufferedWriter,640 bw: *Writer,
642) std.io.Writer.Error!void {641) Writer.Error!void {
643 const t = &macho_file.base.comp.root_mod.resolved_target.result;642 const t = &macho_file.base.comp.root_mod.resolved_target.result;
644 const cpu_arch = t.cpu.arch;643 const cpu_arch = t.cpu.arch;
645 const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;644 const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;
...@@ -938,8 +937,7 @@ const x86_64 = struct {...@@ -938,8 +937,7 @@ const x86_64 = struct {
938 }937 }
939938
940 fn encode(insts: []const Instruction, code: []u8) !void {939 fn encode(insts: []const Instruction, code: []u8) !void {
941 var bw: std.io.BufferedWriter = undefined;940 var bw: Writer = .fixed(code);
942 bw.initFixed(code);
943 for (insts) |inst| try inst.encode(&bw, .{});941 for (insts) |inst| try inst.encode(&bw, .{});
944 }942 }
945943
...@@ -1140,8 +1138,8 @@ const FormatContext = struct {...@@ -1140,8 +1138,8 @@ const FormatContext = struct {
1140 macho_file: *MachO,1138 macho_file: *MachO,
1141};1139};
11421140
1143fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1141fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1144 _ = unused_fmt_string;1142 comptime assert(unused_fmt_string.len == 0);
1145 const atom = ctx.atom;1143 const atom = ctx.atom;
1146 const macho_file = ctx.macho_file;1144 const macho_file = ctx.macho_file;
1147 const file = atom.getFile(macho_file);1145 const file = atom.getFile(macho_file);
...@@ -1197,19 +1195,20 @@ pub const Extra = struct {...@@ -1197,19 +1195,20 @@ pub const Extra = struct {
11971195
1198pub const Alignment = @import("../../InternPool.zig").Alignment;1196pub const Alignment = @import("../../InternPool.zig").Alignment;
11991197
1200const aarch64 = @import("../aarch64.zig");1198const std = @import("std");
1201const assert = std.debug.assert;1199const assert = std.debug.assert;
1202const macho = std.macho;1200const macho = std.macho;
1203const math = std.math;1201const math = std.math;
1204const mem = std.mem;1202const mem = std.mem;
1205const log = std.log.scoped(.link);1203const log = std.log.scoped(.link);
1206const relocs_log = std.log.scoped(.link_relocs);1204const relocs_log = std.log.scoped(.link_relocs);
1207const std = @import("std");1205const Writer = std.io.Writer;
1208const trace = @import("../../tracy.zig").trace;
1209
1210const Allocator = mem.Allocator;1206const Allocator = mem.Allocator;
1211const Atom = @This();
1212const AtomicBool = std.atomic.Value(bool);1207const AtomicBool = std.atomic.Value(bool);
1208
1209const aarch64 = @import("../aarch64.zig");
1210const trace = @import("../../tracy.zig").trace;
1211const Atom = @This();
1213const File = @import("file.zig").File;1212const File = @import("file.zig").File;
1214const MachO = @import("../MachO.zig");1213const MachO = @import("../MachO.zig");
1215const Object = @import("Object.zig");1214const Object = @import("Object.zig");
src/link/MachO/DebugSymbols.zig+2-2
...@@ -269,8 +269,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {...@@ -269,8 +269,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
269269
270fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {270fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {
271 const gpa = self.allocator;271 const gpa = self.allocator;
272 var bw: std.io.BufferedWriter = undefined;272 var bw: Writer = .fixed(try gpa.alloc(u8, load_commands.calcLoadCommandsSizeDsym(macho_file, self)));
273 bw.initFixed(try gpa.alloc(u8, load_commands.calcLoadCommandsSizeDsym(macho_file, self)));
274 defer gpa.free(bw.buffer);273 defer gpa.free(bw.buffer);
275274
276 var ncmds: usize = 0;275 var ncmds: usize = 0;
...@@ -456,6 +455,7 @@ const math = std.math;...@@ -456,6 +455,7 @@ const math = std.math;
456const mem = std.mem;455const mem = std.mem;
457const padToIdeal = MachO.padToIdeal;456const padToIdeal = MachO.padToIdeal;
458const trace = @import("../../tracy.zig").trace;457const trace = @import("../../tracy.zig").trace;
458const Writer = std.io.Writer;
459459
460const Allocator = mem.Allocator;460const Allocator = mem.Allocator;
461const MachO = @import("../MachO.zig");461const MachO = @import("../MachO.zig");
src/link/MachO/Dylib.zig+6-5
...@@ -675,7 +675,7 @@ const FormatContext = struct {...@@ -675,7 +675,7 @@ const FormatContext = struct {
675 macho_file: *MachO,675 macho_file: *MachO,
676};676};
677677
678fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {678fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
679 _ = unused_fmt_string;679 _ = unused_fmt_string;
680 const dylib = ctx.dylib;680 const dylib = ctx.dylib;
681 const macho_file = ctx.macho_file;681 const macho_file = ctx.macho_file;
...@@ -901,19 +901,17 @@ const Export = struct {...@@ -901,19 +901,17 @@ const Export = struct {
901 };901 };
902};902};
903903
904const std = @import("std");
904const assert = std.debug.assert;905const assert = std.debug.assert;
905const fat = @import("fat.zig");
906const fs = std.fs;906const fs = std.fs;
907const fmt = std.fmt;907const fmt = std.fmt;
908const log = std.log.scoped(.link);908const log = std.log.scoped(.link);
909const macho = std.macho;909const macho = std.macho;
910const math = std.math;910const math = std.math;
911const mem = std.mem;911const mem = std.mem;
912const tapi = @import("../tapi.zig");
913const trace = @import("../../tracy.zig").trace;
914const std = @import("std");
915const Allocator = mem.Allocator;912const Allocator = mem.Allocator;
916const Path = std.Build.Cache.Path;913const Path = std.Build.Cache.Path;
914const Writer = std.io.Writer;
917915
918const Dylib = @This();916const Dylib = @This();
919const File = @import("file.zig").File;917const File = @import("file.zig").File;
...@@ -922,3 +920,6 @@ const LoadCommandIterator = macho.LoadCommandIterator;...@@ -922,3 +920,6 @@ const LoadCommandIterator = macho.LoadCommandIterator;
922const MachO = @import("../MachO.zig");920const MachO = @import("../MachO.zig");
923const Symbol = @import("Symbol.zig");921const Symbol = @import("Symbol.zig");
924const Tbd = tapi.Tbd;922const Tbd = tapi.Tbd;
923const fat = @import("fat.zig");
924const tapi = @import("../tapi.zig");
925const trace = @import("../../tracy.zig").trace;
src/link/MachO/InternalObject.zig+4-3
...@@ -848,7 +848,7 @@ pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(for...@@ -848,7 +848,7 @@ pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(for
848 } };848 } };
849}849}
850850
851fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {851fn formatAtoms(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
852 _ = unused_fmt_string;852 _ = unused_fmt_string;
853 try bw.writeAll(" atoms\n");853 try bw.writeAll(" atoms\n");
854 for (ctx.self.getAtoms()) |atom_index| {854 for (ctx.self.getAtoms()) |atom_index| {
...@@ -864,8 +864,8 @@ pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(fo...@@ -864,8 +864,8 @@ pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(fo
864 } };864 } };
865}865}
866866
867fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {867fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
868 _ = unused_fmt_string;868 comptime assert(unused_fmt_string.len == 0);
869 const macho_file = ctx.macho_file;869 const macho_file = ctx.macho_file;
870 const self = ctx.self;870 const self = ctx.self;
871 try bw.writeAll(" symbols\n");871 try bw.writeAll(" symbols\n");
...@@ -896,6 +896,7 @@ const macho = std.macho;...@@ -896,6 +896,7 @@ const macho = std.macho;
896const mem = std.mem;896const mem = std.mem;
897const std = @import("std");897const std = @import("std");
898const trace = @import("../../tracy.zig").trace;898const trace = @import("../../tracy.zig").trace;
899const Writer = std.io.Writer;
899900
900const Allocator = std.mem.Allocator;901const Allocator = std.mem.Allocator;
901const Atom = @import("Atom.zig");902const Atom = @import("Atom.zig");
src/link/MachO/Object.zig+16-16
...@@ -1065,8 +1065,7 @@ fn initEhFrameRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fi...@@ -1065,8 +1065,7 @@ fn initEhFrameRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fi
1065 }1065 }
1066 }1066 }
10671067
1068 var it: eh_frame.Iterator = undefined;1068 var it: eh_frame.Iterator = .{ .br = .fixed(self.eh_frame_data.items) };
1069 it.br.initFixed(self.eh_frame_data.items);
1070 while (try it.next()) |rec| {1069 while (try it.next()) |rec| {
1071 switch (rec.tag) {1070 switch (rec.tag) {
1072 .cie => try self.cies.append(allocator, .{1071 .cie => try self.cies.append(allocator, .{
...@@ -1695,7 +1694,7 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void {...@@ -1695,7 +1694,7 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void {
1695 };1694 };
1696}1695}
16971696
1698pub fn writeAr(self: Object, bw: *std.io.BufferedWriter, ar_format: Archive.Format, macho_file: *MachO) !void {1697pub fn writeAr(self: Object, bw: *Writer, ar_format: Archive.Format, macho_file: *MachO) !void {
1699 // Header1698 // Header
1700 const size = try macho_file.cast(usize, self.output_ar_state.size);1699 const size = try macho_file.cast(usize, self.output_ar_state.size);
1701 const basename = std.fs.path.basename(self.path.sub_path);1700 const basename = std.fs.path.basename(self.path.sub_path);
...@@ -2513,7 +2512,7 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_...@@ -2513,7 +2512,7 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_
2513 return data;2512 return data;
2514}2513}
25152514
2516pub fn format(self: *Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2515pub fn format(self: *Object, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2517 _ = self;2516 _ = self;
2518 _ = bw;2517 _ = bw;
2519 _ = unused_fmt_string;2518 _ = unused_fmt_string;
...@@ -2532,7 +2531,7 @@ pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatAtoms...@@ -2532,7 +2531,7 @@ pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatAtoms
2532 } };2531 } };
2533}2532}
25342533
2535fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2534fn formatAtoms(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2536 _ = unused_fmt_string;2535 _ = unused_fmt_string;
2537 const object = ctx.object;2536 const object = ctx.object;
2538 const macho_file = ctx.macho_file;2537 const macho_file = ctx.macho_file;
...@@ -2550,7 +2549,7 @@ pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatCies)...@@ -2550,7 +2549,7 @@ pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatCies)
2550 } };2549 } };
2551}2550}
25522551
2553fn formatCies(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2552fn formatCies(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2554 _ = unused_fmt_string;2553 _ = unused_fmt_string;
2555 const object = ctx.object;2554 const object = ctx.object;
2556 try bw.writeAll(" cies\n");2555 try bw.writeAll(" cies\n");
...@@ -2566,7 +2565,7 @@ pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatFdes)...@@ -2566,7 +2565,7 @@ pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatFdes)
2566 } };2565 } };
2567}2566}
25682567
2569fn formatFdes(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2568fn formatFdes(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2570 _ = unused_fmt_string;2569 _ = unused_fmt_string;
2571 const object = ctx.object;2570 const object = ctx.object;
2572 try bw.writeAll(" fdes\n");2571 try bw.writeAll(" fdes\n");
...@@ -2582,7 +2581,7 @@ pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(for...@@ -2582,7 +2581,7 @@ pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(for
2582 } };2581 } };
2583}2582}
25842583
2585fn formatUnwindRecords(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2584fn formatUnwindRecords(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2586 _ = unused_fmt_string;2585 _ = unused_fmt_string;
2587 const object = ctx.object;2586 const object = ctx.object;
2588 const macho_file = ctx.macho_file;2587 const macho_file = ctx.macho_file;
...@@ -2599,7 +2598,7 @@ pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatSymt...@@ -2599,7 +2598,7 @@ pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatSymt
2599 } };2598 } };
2600}2599}
26012600
2602fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2601fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2603 _ = unused_fmt_string;2602 _ = unused_fmt_string;
2604 const object = ctx.object;2603 const object = ctx.object;
2605 const macho_file = ctx.macho_file;2604 const macho_file = ctx.macho_file;
...@@ -2629,7 +2628,7 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {...@@ -2629,7 +2628,7 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {
2629 return .{ .data = self };2628 return .{ .data = self };
2630}2629}
26312630
2632fn formatPath(object: Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2631fn formatPath(object: Object, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2633 _ = unused_fmt_string;2632 _ = unused_fmt_string;
2634 if (object.in_archive) |ar| {2633 if (object.in_archive) |ar| {
2635 try bw.print("{f}({s})", .{2634 try bw.print("{f}({s})", .{
...@@ -2690,7 +2689,7 @@ const StabFile = struct {...@@ -2690,7 +2689,7 @@ const StabFile = struct {
2690 return object.symbols.items[index];2689 return object.symbols.items[index];
2691 }2690 }
26922691
2693 pub fn format(stab: Stab, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2692 pub fn format(stab: Stab, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2694 _ = stab;2693 _ = stab;
2695 _ = bw;2694 _ = bw;
2696 _ = unused_fmt_string;2695 _ = unused_fmt_string;
...@@ -2703,7 +2702,7 @@ const StabFile = struct {...@@ -2703,7 +2702,7 @@ const StabFile = struct {
2703 return .{ .data = .{ stab, object } };2702 return .{ .data = .{ stab, object } };
2704 }2703 }
27052704
2706 fn format2(ctx: StabFormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {2705 fn format2(ctx: StabFormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
2707 _ = unused_fmt_string;2706 _ = unused_fmt_string;
2708 const stab, const object = ctx;2707 const stab, const object = ctx;
2709 const sym = stab.getSymbol(object).?;2708 const sym = stab.getSymbol(object).?;
...@@ -3104,17 +3103,18 @@ const aarch64 = struct {...@@ -3104,17 +3103,18 @@ const aarch64 = struct {
3104 }3103 }
3105};3104};
31063105
3106const std = @import("std");
3107const assert = std.debug.assert;3107const assert = std.debug.assert;
3108const eh_frame = @import("eh_frame.zig");
3109const log = std.log.scoped(.link);3108const log = std.log.scoped(.link);
3110const macho = std.macho;3109const macho = std.macho;
3111const math = std.math;3110const math = std.math;
3112const mem = std.mem;3111const mem = std.mem;
3113const trace = @import("../../tracy.zig").trace;
3114const std = @import("std");
3115const Path = std.Build.Cache.Path;3112const Path = std.Build.Cache.Path;
3113const Allocator = std.mem.Allocator;
3114const Writer = std.io.Writer;
31163115
3117const Allocator = mem.Allocator;3116const eh_frame = @import("eh_frame.zig");
3117const trace = @import("../../tracy.zig").trace;
3118const Archive = @import("Archive.zig");3118const Archive = @import("Archive.zig");
3119const Atom = @import("Atom.zig");3119const Atom = @import("Atom.zig");
3120const Cie = eh_frame.Cie;3120const Cie = eh_frame.Cie;
src/link/MachO/Relocation.zig+3-2
...@@ -76,7 +76,7 @@ pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatt...@@ -76,7 +76,7 @@ pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatt
76 return .{ .data = .{ rel, cpu_arch } };76 return .{ .data = .{ rel, cpu_arch } };
77}77}
7878
79fn formatPretty(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {79fn formatPretty(ctx: FormatCtx, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
80 _ = unused_fmt_string;80 _ = unused_fmt_string;
81 const rel, const cpu_arch = ctx;81 const rel, const cpu_arch = ctx;
82 try bw.writeAll(switch (rel.type) {82 try bw.writeAll(switch (rel.type) {
...@@ -157,10 +157,11 @@ pub const Type = enum {...@@ -157,10 +157,11 @@ pub const Type = enum {
157157
158const Tag = enum { local, @"extern" };158const Tag = enum { local, @"extern" };
159159
160const std = @import("std");
160const assert = std.debug.assert;161const assert = std.debug.assert;
161const macho = std.macho;162const macho = std.macho;
162const math = std.math;163const math = std.math;
163const std = @import("std");164const Writer = std.io.Writer;
164165
165const Atom = @import("Atom.zig");166const Atom = @import("Atom.zig");
166const MachO = @import("../MachO.zig");167const MachO = @import("../MachO.zig");
src/link/MachO/Symbol.zig+4-3
...@@ -286,7 +286,7 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo...@@ -286,7 +286,7 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo
286 }286 }
287}287}
288288
289pub fn format(symbol: Symbol, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {289pub fn format(symbol: Symbol, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
290 _ = symbol;290 _ = symbol;
291 _ = bw;291 _ = bw;
292 _ = unused_fmt_string;292 _ = unused_fmt_string;
...@@ -305,8 +305,8 @@ pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(format2) {...@@ -305,8 +305,8 @@ pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(format2) {
305 } };305 } };
306}306}
307307
308fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {308fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
309 _ = unused_fmt_string;309 comptime assert(unused_fmt_string.len == 0);
310 const symbol = ctx.symbol;310 const symbol = ctx.symbol;
311 try bw.print("%{d} : {s} : @{x}", .{311 try bw.print("%{d} : {s} : @{x}", .{
312 symbol.nlist_idx,312 symbol.nlist_idx,
...@@ -425,6 +425,7 @@ pub const Index = u32;...@@ -425,6 +425,7 @@ pub const Index = u32;
425const assert = std.debug.assert;425const assert = std.debug.assert;
426const macho = std.macho;426const macho = std.macho;
427const std = @import("std");427const std = @import("std");
428const Writer = std.io.Writer;
428429
429const Atom = @import("Atom.zig");430const Atom = @import("Atom.zig");
430const File = @import("file.zig").File;431const File = @import("file.zig").File;
src/link/MachO/Thunk.zig+4-3
...@@ -20,7 +20,7 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {...@@ -20,7 +20,7 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {
20 return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;20 return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;
21}21}
2222
23pub fn write(thunk: Thunk, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {23pub fn write(thunk: Thunk, macho_file: *MachO, bw: *Writer) !void {
24 for (thunk.symbols.keys(), 0..) |ref, i| {24 for (thunk.symbols.keys(), 0..) |ref, i| {
25 const sym = ref.getSymbol(macho_file).?;25 const sym = ref.getSymbol(macho_file).?;
26 const saddr = thunk.getAddress(macho_file) + i * trampoline_size;26 const saddr = thunk.getAddress(macho_file) + i * trampoline_size;
...@@ -61,7 +61,7 @@ pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {...@@ -61,7 +61,7 @@ pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {
61 }61 }
62}62}
6363
64pub fn format(thunk: Thunk, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {64pub fn format(thunk: Thunk, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
65 _ = thunk;65 _ = thunk;
66 _ = bw;66 _ = bw;
67 _ = unused_fmt_string;67 _ = unused_fmt_string;
...@@ -80,7 +80,7 @@ const FormatContext = struct {...@@ -80,7 +80,7 @@ const FormatContext = struct {
80 macho_file: *MachO,80 macho_file: *MachO,
81};81};
8282
83fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {83fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
84 _ = unused_fmt_string;84 _ = unused_fmt_string;
85 const thunk = ctx.thunk;85 const thunk = ctx.thunk;
86 const macho_file = ctx.macho_file;86 const macho_file = ctx.macho_file;
...@@ -103,6 +103,7 @@ const math = std.math;...@@ -103,6 +103,7 @@ const math = std.math;
103const mem = std.mem;103const mem = std.mem;
104const std = @import("std");104const std = @import("std");
105const trace = @import("../../tracy.zig").trace;105const trace = @import("../../tracy.zig").trace;
106const Writer = std.io.Writer;
106107
107const Allocator = mem.Allocator;108const Allocator = mem.Allocator;
108const Atom = @import("Atom.zig");109const Atom = @import("Atom.zig");
src/link/MachO/UnwindInfo.zig+7-6
...@@ -289,7 +289,7 @@ pub fn calcSize(info: UnwindInfo) usize {...@@ -289,7 +289,7 @@ pub fn calcSize(info: UnwindInfo) usize {
289 return total_size;289 return total_size;
290}290}
291291
292pub fn write(info: UnwindInfo, macho_file: *MachO, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {292pub fn write(info: UnwindInfo, macho_file: *MachO, bw: *Writer) Writer.Error!void {
293 const seg = macho_file.getTextSegment();293 const seg = macho_file.getTextSegment();
294 const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?];294 const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?];
295295
...@@ -449,7 +449,7 @@ pub const Encoding = extern struct {...@@ -449,7 +449,7 @@ pub const Encoding = extern struct {
449 return enc.enc == other.enc;449 return enc.enc == other.enc;
450 }450 }
451451
452 pub fn format(enc: Encoding, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {452 pub fn format(enc: Encoding, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
453 _ = unused_fmt_string;453 _ = unused_fmt_string;
454 try bw.print("0x{x:0>8}", .{enc.enc});454 try bw.print("0x{x:0>8}", .{enc.enc});
455 }455 }
...@@ -505,7 +505,7 @@ pub const Record = struct {...@@ -505,7 +505,7 @@ pub const Record = struct {
505 return lsda.getAddress(macho_file) + rec.lsda_offset;505 return lsda.getAddress(macho_file) + rec.lsda_offset;
506 }506 }
507507
508 pub fn format(rec: Record, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {508 pub fn format(rec: Record, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
509 _ = rec;509 _ = rec;
510 _ = bw;510 _ = bw;
511 _ = unused_fmt_string;511 _ = unused_fmt_string;
...@@ -524,7 +524,7 @@ pub const Record = struct {...@@ -524,7 +524,7 @@ pub const Record = struct {
524 macho_file: *MachO,524 macho_file: *MachO,
525 };525 };
526526
527 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {527 fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
528 _ = unused_fmt_string;528 _ = unused_fmt_string;
529 const rec = ctx.rec;529 const rec = ctx.rec;
530 const macho_file = ctx.macho_file;530 const macho_file = ctx.macho_file;
...@@ -589,7 +589,7 @@ const Page = struct {...@@ -589,7 +589,7 @@ const Page = struct {
589 return null;589 return null;
590 }590 }
591591
592 fn format(page: *const Page, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {592 fn format(page: *const Page, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
593 _ = page;593 _ = page;
594 _ = bw;594 _ = bw;
595 _ = unused_format_string;595 _ = unused_format_string;
...@@ -601,7 +601,7 @@ const Page = struct {...@@ -601,7 +601,7 @@ const Page = struct {
601 info: UnwindInfo,601 info: UnwindInfo,
602 };602 };
603603
604 fn format2(ctx: FormatPageContext, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {604 fn format2(ctx: FormatPageContext, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
605 _ = unused_format_string;605 _ = unused_format_string;
606 try bw.writeAll("Page:\n");606 try bw.writeAll("Page:\n");
607 try bw.print(" kind: {s}\n", .{@tagName(ctx.page.kind)});607 try bw.print(" kind: {s}\n", .{@tagName(ctx.page.kind)});
...@@ -684,6 +684,7 @@ const macho = std.macho;...@@ -684,6 +684,7 @@ const macho = std.macho;
684const math = std.math;684const math = std.math;
685const mem = std.mem;685const mem = std.mem;
686const trace = @import("../../tracy.zig").trace;686const trace = @import("../../tracy.zig").trace;
687const Writer = std.io.Writer;
687688
688const Allocator = mem.Allocator;689const Allocator = mem.Allocator;
689const Atom = @import("Atom.zig");690const Atom = @import("Atom.zig");
src/link/MachO/ZigObject.zig+4-3
...@@ -317,7 +317,7 @@ pub fn updateArSize(self: *ZigObject) void {...@@ -317,7 +317,7 @@ pub fn updateArSize(self: *ZigObject) void {
317 self.output_ar_state.size = self.data.items.len;317 self.output_ar_state.size = self.data.items.len;
318}318}
319319
320pub fn writeAr(self: ZigObject, bw: *std.io.BufferedWriter, ar_format: Archive.Format) std.io.Writer.Error!void {320pub fn writeAr(self: ZigObject, bw: *Writer, ar_format: Archive.Format) Writer.Error!void {
321 // Header321 // Header
322 const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow;322 const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow;
323 try Archive.writeHeader(bw, self.basename, size, ar_format);323 try Archive.writeHeader(bw, self.basename, size, ar_format);
...@@ -1688,7 +1688,7 @@ const FormatContext = struct {...@@ -1688,7 +1688,7 @@ const FormatContext = struct {
1688 macho_file: *MachO,1688 macho_file: *MachO,
1689};1689};
16901690
1691fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1691fn formatSymtab(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1692 _ = unused_fmt_string;1692 _ = unused_fmt_string;
1693 try bw.writeAll(" symbols\n");1693 try bw.writeAll(" symbols\n");
1694 const self = ctx.self;1694 const self = ctx.self;
...@@ -1711,7 +1711,7 @@ pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatAt...@@ -1711,7 +1711,7 @@ pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatAt
1711 } };1711 } };
1712}1712}
17131713
1714fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {1714fn formatAtoms(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
1715 _ = unused_fmt_string;1715 _ = unused_fmt_string;
1716 const self = ctx.self;1716 const self = ctx.self;
1717 const macho_file = ctx.macho_file;1717 const macho_file = ctx.macho_file;
...@@ -1783,6 +1783,7 @@ const mem = std.mem;...@@ -1783,6 +1783,7 @@ const mem = std.mem;
1783const target_util = @import("../../target.zig");1783const target_util = @import("../../target.zig");
1784const trace = @import("../../tracy.zig").trace;1784const trace = @import("../../tracy.zig").trace;
1785const std = @import("std");1785const std = @import("std");
1786const Writer = std.io.Writer;
17861787
1787const Allocator = std.mem.Allocator;1788const Allocator = std.mem.Allocator;
1788const Archive = @import("Archive.zig");1789const Archive = @import("Archive.zig");
src/link/MachO/dead_strip.zig+2-1
...@@ -196,7 +196,7 @@ const Level = struct {...@@ -196,7 +196,7 @@ const Level = struct {
196 self.value += 1;196 self.value += 1;
197 }197 }
198198
199 pub fn format(self: *const @This(), bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {199 pub fn format(self: *const @This(), bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
200 _ = unused_fmt_string;200 _ = unused_fmt_string;
201 try bw.splatByteAll(' ', self.value);201 try bw.splatByteAll(' ', self.value);
202 }202 }
...@@ -213,6 +213,7 @@ const mem = std.mem;...@@ -213,6 +213,7 @@ const mem = std.mem;
213const trace = @import("../../tracy.zig").trace;213const trace = @import("../../tracy.zig").trace;
214const track_live_log = std.log.scoped(.dead_strip_track_live);214const track_live_log = std.log.scoped(.dead_strip_track_live);
215const std = @import("std");215const std = @import("std");
216const Writer = std.io.Writer;
216217
217const Allocator = mem.Allocator;218const Allocator = mem.Allocator;
218const Atom = @import("Atom.zig");219const Atom = @import("Atom.zig");
src/link/MachO/dyld_info/Rebase.zig+12-11
...@@ -133,7 +133,7 @@ fn finalize(rebase: *Rebase, gpa: Allocator) !void {...@@ -133,7 +133,7 @@ fn finalize(rebase: *Rebase, gpa: Allocator) !void {
133 try done(bw);133 try done(bw);
134}134}
135135
136fn finalizeSegment(entries: []const Entry, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {136fn finalizeSegment(entries: []const Entry, bw: *Writer) Writer.Error!void {
137 if (entries.len == 0) return;137 if (entries.len == 0) return;
138138
139 const segment_id = entries[0].segment_id;139 const segment_id = entries[0].segment_id;
...@@ -220,24 +220,24 @@ fn finalizeSegment(entries: []const Entry, bw: *std.io.BufferedWriter) std.io.Wr...@@ -220,24 +220,24 @@ fn finalizeSegment(entries: []const Entry, bw: *std.io.BufferedWriter) std.io.Wr
220 }220 }
221}221}
222222
223fn setTypePointer(bw: *std.io.BufferedWriter) std.io.Writer.Error!void {223fn setTypePointer(bw: *Writer) Writer.Error!void {
224 log.debug(">>> set type: {d}", .{macho.REBASE_TYPE_POINTER});224 log.debug(">>> set type: {d}", .{macho.REBASE_TYPE_POINTER});
225 try bw.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.REBASE_TYPE_POINTER)));225 try bw.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.REBASE_TYPE_POINTER)));
226}226}
227227
228fn setSegmentOffset(segment_id: u4, offset: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {228fn setSegmentOffset(segment_id: u4, offset: u64, bw: *Writer) Writer.Error!void {
229 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });229 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });
230 try bw.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));230 try bw.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));
231 try bw.writeLeb128(offset);231 try bw.writeLeb128(offset);
232}232}
233233
234fn rebaseAddAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {234fn rebaseAddAddr(addr: u64, bw: *Writer) Writer.Error!void {
235 log.debug(">>> rebase with add: {x}", .{addr});235 log.debug(">>> rebase with add: {x}", .{addr});
236 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);236 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);
237 try bw.writeLeb128(addr);237 try bw.writeLeb128(addr);
238}238}
239239
240fn rebaseTimes(count: usize, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {240fn rebaseTimes(count: usize, bw: *Writer) Writer.Error!void {
241 log.debug(">>> rebase with count: {d}", .{count});241 log.debug(">>> rebase with count: {d}", .{count});
242 if (count <= 0xf) {242 if (count <= 0xf) {
243 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @as(u4, @truncate(count)));243 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @as(u4, @truncate(count)));
...@@ -247,14 +247,14 @@ fn rebaseTimes(count: usize, bw: *std.io.BufferedWriter) std.io.Writer.Error!voi...@@ -247,14 +247,14 @@ fn rebaseTimes(count: usize, bw: *std.io.BufferedWriter) std.io.Writer.Error!voi
247 }247 }
248}248}
249249
250fn rebaseTimesSkip(count: usize, skip: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {250fn rebaseTimesSkip(count: usize, skip: u64, bw: *Writer) Writer.Error!void {
251 log.debug(">>> rebase with count: {d} and skip: {x}", .{ count, skip });251 log.debug(">>> rebase with count: {d} and skip: {x}", .{ count, skip });
252 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);252 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);
253 try bw.writeLeb128(count);253 try bw.writeLeb128(count);
254 try bw.writeLeb128(skip);254 try bw.writeLeb128(skip);
255}255}
256256
257fn addAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {257fn addAddr(addr: u64, bw: *Writer) Writer.Error!void {
258 log.debug(">>> add: {x}", .{addr});258 log.debug(">>> add: {x}", .{addr});
259 if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {259 if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {
260 if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(260 if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(
...@@ -265,12 +265,12 @@ fn addAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {...@@ -265,12 +265,12 @@ fn addAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {
265 try bw.writeLeb128(addr);265 try bw.writeLeb128(addr);
266}266}
267267
268fn done(bw: *std.io.BufferedWriter) std.io.Writer.Error!void {268fn done(bw: *Writer) Writer.Error!void {
269 log.debug(">>> done", .{});269 log.debug(">>> done", .{});
270 try bw.writeByte(macho.REBASE_OPCODE_DONE);270 try bw.writeByte(macho.REBASE_OPCODE_DONE);
271}271}
272272
273pub fn write(rebase: Rebase, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {273pub fn write(rebase: Rebase, bw: *Writer) Writer.Error!void {
274 try bw.writeAll(rebase.buffer.items);274 try bw.writeAll(rebase.buffer.items);
275}275}
276276
...@@ -654,9 +654,10 @@ const log = std.log.scoped(.link_dyld_info);...@@ -654,9 +654,10 @@ const log = std.log.scoped(.link_dyld_info);
654const macho = std.macho;654const macho = std.macho;
655const mem = std.mem;655const mem = std.mem;
656const testing = std.testing;656const testing = std.testing;
657const trace = @import("../../../tracy.zig").trace;
658
659const Allocator = mem.Allocator;657const Allocator = mem.Allocator;
658const Writer = std.io.Writer;
659
660const trace = @import("../../../tracy.zig").trace;
660const File = @import("../file.zig").File;661const File = @import("../file.zig").File;
661const MachO = @import("../../MachO.zig");662const MachO = @import("../../MachO.zig");
662const Rebase = @This();663const Rebase = @This();
src/link/MachO/dyld_info/Trie.zig+6-6
...@@ -166,8 +166,7 @@ fn finalize(self: *Trie, allocator: Allocator) !void {...@@ -166,8 +166,7 @@ fn finalize(self: *Trie, allocator: Allocator) !void {
166166
167 assert(self.buffer.len == 0);167 assert(self.buffer.len == 0);
168 self.buffer = try allocator.alloc(u8, size);168 self.buffer = try allocator.alloc(u8, size);
169 var bw: std.io.BufferedWriter = undefined;169 var bw: Writer = .fixed(self.buffer);
170 bw.initFixed(self.buffer);
171 for (ordered_nodes.items) |node_index| {170 for (ordered_nodes.items) |node_index| {
172 try self.writeNode(node_index, &bw);171 try self.writeNode(node_index, &bw);
173 }172 }
...@@ -185,7 +184,7 @@ const FinalizeNodeResult = struct {...@@ -185,7 +184,7 @@ const FinalizeNodeResult = struct {
185/// Updates offset of this node in the output byte stream.184/// Updates offset of this node in the output byte stream.
186fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {185fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {
187 var buf: [1024]u8 = undefined;186 var buf: [1024]u8 = undefined;
188 var bw = std.io.Writer.null.buffered(&buf);187 var bw = Writer.null.buffered(&buf);
189 const slice = self.nodes.slice();188 const slice = self.nodes.slice();
190189
191 var node_size: u32 = 0;190 var node_size: u32 = 0;
...@@ -229,7 +228,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void {...@@ -229,7 +228,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void {
229 allocator.free(self.buffer);228 allocator.free(self.buffer);
230}229}
231230
232pub fn write(self: Trie, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {231pub fn write(self: Trie, bw: *Writer) Writer.Error!void {
233 try bw.writeAll(self.buffer);232 try bw.writeAll(self.buffer);
234}233}
235234
...@@ -239,7 +238,7 @@ pub fn write(self: Trie, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {...@@ -239,7 +238,7 @@ pub fn write(self: Trie, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {
239/// iterate over `Trie.ordered_nodes` and call this method on each node.238/// iterate over `Trie.ordered_nodes` and call this method on each node.
240/// This is one of the requirements of the MachO.239/// This is one of the requirements of the MachO.
241/// Panics if `finalize` was not called before calling this method.240/// Panics if `finalize` was not called before calling this method.
242fn writeNode(self: *Trie, node_index: Node.Index, bw: *std.io.BufferedWriter) !void {241fn writeNode(self: *Trie, node_index: Node.Index, bw: *Writer) !void {
243 const slice = self.nodes.slice();242 const slice = self.nodes.slice();
244 const edges = slice.items(.edges)[node_index];243 const edges = slice.items(.edges)[node_index];
245 const is_terminal = slice.items(.is_terminal)[node_index];244 const is_terminal = slice.items(.is_terminal)[node_index];
...@@ -408,9 +407,10 @@ const macho = std.macho;...@@ -408,9 +407,10 @@ const macho = std.macho;
408const mem = std.mem;407const mem = std.mem;
409const std = @import("std");408const std = @import("std");
410const testing = std.testing;409const testing = std.testing;
410const Writer = std.io.Writer;
411
411const trace = @import("../../../tracy.zig").trace;412const trace = @import("../../../tracy.zig").trace;
412const DeprecatedLinearFifo = @import("../../../deprecated.zig").LinearFifo;413const DeprecatedLinearFifo = @import("../../../deprecated.zig").LinearFifo;
413
414const Allocator = mem.Allocator;414const Allocator = mem.Allocator;
415const MachO = @import("../../MachO.zig");415const MachO = @import("../../MachO.zig");
416const Trie = @This();416const Trie = @This();
src/link/MachO/dyld_info/bind.zig+19-18
...@@ -139,7 +139,7 @@ pub const Bind = struct {...@@ -139,7 +139,7 @@ pub const Bind = struct {
139 try done(bw);139 try done(bw);
140 }140 }
141141
142 fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {142 fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *Writer) Writer.Error!void {
143 if (entries.len == 0) return;143 if (entries.len == 0) return;
144144
145 const seg_id = entries[0].segment_id;145 const seg_id = entries[0].segment_id;
...@@ -251,7 +251,7 @@ pub const Bind = struct {...@@ -251,7 +251,7 @@ pub const Bind = struct {
251 }251 }
252 }252 }
253253
254 pub fn write(bind: Bind, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {254 pub fn write(bind: Bind, bw: *Writer) Writer.Error!void {
255 try bw.writeAll(bind.buffer.items);255 try bw.writeAll(bind.buffer.items);
256 }256 }
257};257};
...@@ -380,7 +380,7 @@ pub const WeakBind = struct {...@@ -380,7 +380,7 @@ pub const WeakBind = struct {
380 try done(bw);380 try done(bw);
381 }381 }
382382
383 fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {383 fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *Writer) Writer.Error!void {
384 if (entries.len == 0) return;384 if (entries.len == 0) return;
385385
386 const seg_id = entries[0].segment_id;386 const seg_id = entries[0].segment_id;
...@@ -481,7 +481,7 @@ pub const WeakBind = struct {...@@ -481,7 +481,7 @@ pub const WeakBind = struct {
481 }481 }
482 }482 }
483483
484 pub fn write(bind: WeakBind, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {484 pub fn write(bind: WeakBind, bw: *Writer) Writer.Error!void {
485 try bw.writeAll(bind.buffer.items);485 try bw.writeAll(bind.buffer.items);
486 }486 }
487};487};
...@@ -565,30 +565,30 @@ pub const LazyBind = struct {...@@ -565,30 +565,30 @@ pub const LazyBind = struct {
565 }565 }
566 }566 }
567567
568 pub fn write(bind: LazyBind, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {568 pub fn write(bind: LazyBind, bw: *Writer) Writer.Error!void {
569 try bw.writeAll(bind.buffer.items);569 try bw.writeAll(bind.buffer.items);
570 }570 }
571};571};
572572
573fn setSegmentOffset(segment_id: u4, offset: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {573fn setSegmentOffset(segment_id: u4, offset: u64, bw: *Writer) Writer.Error!void {
574 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });574 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });
575 try bw.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segment_id);575 try bw.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segment_id);
576 try bw.writeLeb128(offset);576 try bw.writeLeb128(offset);
577}577}
578578
579fn setSymbol(name: []const u8, flags: u4, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {579fn setSymbol(name: []const u8, flags: u4, bw: *Writer) Writer.Error!void {
580 log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags });580 log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags });
581 try bw.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);581 try bw.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);
582 try bw.writeAll(name);582 try bw.writeAll(name);
583 try bw.writeByte(0);583 try bw.writeByte(0);
584}584}
585585
586fn setTypePointer(bw: *std.io.BufferedWriter) std.io.Writer.Error!void {586fn setTypePointer(bw: *Writer) Writer.Error!void {
587 log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER});587 log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER});
588 try bw.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.BIND_TYPE_POINTER)));588 try bw.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.BIND_TYPE_POINTER)));
589}589}
590590
591fn setDylibOrdinal(ordinal: i16, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {591fn setDylibOrdinal(ordinal: i16, bw: *Writer) Writer.Error!void {
592 switch (ordinal) {592 switch (ordinal) {
593 else => unreachable, // Invalid dylib special binding593 else => unreachable, // Invalid dylib special binding
594 macho.BIND_SPECIAL_DYLIB_SELF,594 macho.BIND_SPECIAL_DYLIB_SELF,
...@@ -610,18 +610,18 @@ fn setDylibOrdinal(ordinal: i16, bw: *std.io.BufferedWriter) std.io.Writer.Error...@@ -610,18 +610,18 @@ fn setDylibOrdinal(ordinal: i16, bw: *std.io.BufferedWriter) std.io.Writer.Error
610 }610 }
611}611}
612612
613fn setAddend(addend: i64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {613fn setAddend(addend: i64, bw: *Writer) Writer.Error!void {
614 log.debug(">>> set addend: {x}", .{addend});614 log.debug(">>> set addend: {x}", .{addend});
615 try bw.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);615 try bw.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);
616 try bw.writeLeb128(addend);616 try bw.writeLeb128(addend);
617}617}
618618
619fn doBind(bw: *std.io.BufferedWriter) std.io.Writer.Error!void {619fn doBind(bw: *Writer) Writer.Error!void {
620 log.debug(">>> bind", .{});620 log.debug(">>> bind", .{});
621 try bw.writeByte(macho.BIND_OPCODE_DO_BIND);621 try bw.writeByte(macho.BIND_OPCODE_DO_BIND);
622}622}
623623
624fn doBindAddAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {624fn doBindAddAddr(addr: u64, bw: *Writer) Writer.Error!void {
625 log.debug(">>> bind with add: {x}", .{addr});625 log.debug(">>> bind with add: {x}", .{addr});
626 if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {626 if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {
627 if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(627 if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(
...@@ -632,34 +632,35 @@ fn doBindAddAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void...@@ -632,34 +632,35 @@ fn doBindAddAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void
632 try bw.writeLeb128(addr);632 try bw.writeLeb128(addr);
633}633}
634634
635fn doBindTimesSkip(count: usize, skip: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {635fn doBindTimesSkip(count: usize, skip: u64, bw: *Writer) Writer.Error!void {
636 log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip });636 log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip });
637 try bw.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);637 try bw.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
638 try bw.writeLeb128(count);638 try bw.writeLeb128(count);
639 try bw.writeLeb128(skip);639 try bw.writeLeb128(skip);
640}640}
641641
642fn addAddr(addr: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {642fn addAddr(addr: u64, bw: *Writer) Writer.Error!void {
643 log.debug(">>> add: {x}", .{addr});643 log.debug(">>> add: {x}", .{addr});
644 try bw.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);644 try bw.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);
645 try bw.writeLeb128(addr);645 try bw.writeLeb128(addr);
646}646}
647647
648fn done(bw: *std.io.BufferedWriter) std.io.Writer.Error!void {648fn done(bw: *Writer) Writer.Error!void {
649 log.debug(">>> done", .{});649 log.debug(">>> done", .{});
650 try bw.writeByte(macho.BIND_OPCODE_DONE);650 try bw.writeByte(macho.BIND_OPCODE_DONE);
651}651}
652652
653const std = @import("std");
653const assert = std.debug.assert;654const assert = std.debug.assert;
654const leb = std.leb;655const leb = std.leb;
655const log = std.log.scoped(.link_dyld_info);656const log = std.log.scoped(.link_dyld_info);
656const macho = std.macho;657const macho = std.macho;
657const mem = std.mem;658const mem = std.mem;
658const testing = std.testing;659const testing = std.testing;
659const trace = @import("../../../tracy.zig").trace;660const Allocator = std.mem.Allocator;
660const std = @import("std");661const Writer = std.io.Writer;
661662
662const Allocator = mem.Allocator;663const trace = @import("../../../tracy.zig").trace;
663const File = @import("../file.zig").File;664const File = @import("../file.zig").File;
664const MachO = @import("../../MachO.zig");665const MachO = @import("../../MachO.zig");
665const Symbol = @import("../Symbol.zig");666const Symbol = @import("../Symbol.zig");
src/link/MachO/eh_frame.zig+4-4
...@@ -103,7 +103,7 @@ pub const Cie = struct {...@@ -103,7 +103,7 @@ pub const Cie = struct {
103 macho_file: *MachO,103 macho_file: *MachO,
104 };104 };
105105
106 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {106 fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
107 _ = unused_fmt_string;107 _ = unused_fmt_string;
108 const cie = ctx.cie;108 const cie = ctx.cie;
109 try bw.print("@{x} : size({x})", .{109 try bw.print("@{x} : size({x})", .{
...@@ -142,8 +142,7 @@ pub const Fde = struct {...@@ -142,8 +142,7 @@ pub const Fde = struct {
142 const object = fde.getObject(macho_file);142 const object = fde.getObject(macho_file);
143 const sect = object.sections.items(.header)[object.eh_frame_sect_index.?];143 const sect = object.sections.items(.header)[object.eh_frame_sect_index.?];
144144
145 var br: std.io.Reader = undefined;145 var br: std.io.Reader = .fixed(fde.getData(macho_file));
146 br.initFixed(fde.getData(macho_file));
147146
148 try br.discard(4);147 try br.discard(4);
149 const cie_ptr = try br.takeInt(u32, .little);148 const cie_ptr = try br.takeInt(u32, .little);
...@@ -249,7 +248,7 @@ pub const Fde = struct {...@@ -249,7 +248,7 @@ pub const Fde = struct {
249 macho_file: *MachO,248 macho_file: *MachO,
250 };249 };
251250
252 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {251 fn format2(ctx: FormatContext, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
253 _ = unused_fmt_string;252 _ = unused_fmt_string;
254 const fde = ctx.fde;253 const fde = ctx.fde;
255 const macho_file = ctx.macho_file;254 const macho_file = ctx.macho_file;
...@@ -528,6 +527,7 @@ const math = std.math;...@@ -528,6 +527,7 @@ const math = std.math;
528const mem = std.mem;527const mem = std.mem;
529const std = @import("std");528const std = @import("std");
530const trace = @import("../../tracy.zig").trace;529const trace = @import("../../tracy.zig").trace;
530const Writer = std.io.Writer;
531531
532const Allocator = std.mem.Allocator;532const Allocator = std.mem.Allocator;
533const Atom = @import("Atom.zig");533const Atom = @import("Atom.zig");
src/link/MachO/file.zig+3-2
...@@ -14,7 +14,7 @@ pub const File = union(enum) {...@@ -14,7 +14,7 @@ pub const File = union(enum) {
14 return .{ .data = file };14 return .{ .data = file };
15 }15 }
1616
17 fn formatPath(file: File, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) std.io.Writer.Error!void {17 fn formatPath(file: File, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void {
18 _ = unused_fmt_string;18 _ = unused_fmt_string;
19 switch (file) {19 switch (file) {
20 .zig_object => |zo| try bw.writeAll(zo.basename),20 .zig_object => |zo| try bw.writeAll(zo.basename),
...@@ -322,7 +322,7 @@ pub const File = union(enum) {...@@ -322,7 +322,7 @@ pub const File = union(enum) {
322 };322 };
323 }323 }
324324
325 pub fn writeAr(file: File, bw: *std.io.BufferedWriter, ar_format: Archive.Format, macho_file: *MachO) std.io.Writer.Error!void {325 pub fn writeAr(file: File, bw: *Writer, ar_format: Archive.Format, macho_file: *MachO) Writer.Error!void {
326 return switch (file) {326 return switch (file) {
327 .dylib, .internal => unreachable,327 .dylib, .internal => unreachable,
328 .zig_object => |x| x.writeAr(bw, ar_format),328 .zig_object => |x| x.writeAr(bw, ar_format),
...@@ -365,6 +365,7 @@ const log = std.log.scoped(.link);...@@ -365,6 +365,7 @@ const log = std.log.scoped(.link);
365const macho = std.macho;365const macho = std.macho;
366const Allocator = std.mem.Allocator;366const Allocator = std.mem.Allocator;
367const Path = std.Build.Cache.Path;367const Path = std.Build.Cache.Path;
368const Writer = std.io.Writer;
368369
369const trace = @import("../../tracy.zig").trace;370const trace = @import("../../tracy.zig").trace;
370const Archive = @import("Archive.zig");371const Archive = @import("Archive.zig");
src/link/MachO/load_commands.zig+6-5
...@@ -3,6 +3,7 @@ const assert = std.debug.assert;...@@ -3,6 +3,7 @@ const assert = std.debug.assert;
3const log = std.log.scoped(.link);3const log = std.log.scoped(.link);
4const macho = std.macho;4const macho = std.macho;
5const mem = std.mem;5const mem = std.mem;
6const Writer = std.io.Writer;
67
7const Allocator = mem.Allocator;8const Allocator = mem.Allocator;
8const DebugSymbols = @import("DebugSymbols.zig");9const DebugSymbols = @import("DebugSymbols.zig");
...@@ -180,7 +181,7 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {...@@ -180,7 +181,7 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {
180 return offset;181 return offset;
181}182}
182183
183pub fn writeDylinkerLC(bw: *std.io.BufferedWriter) std.io.Writer.Error!void {184pub fn writeDylinkerLC(bw: *Writer) Writer.Error!void {
184 const name_len = mem.sliceTo(default_dyld_path, 0).len;185 const name_len = mem.sliceTo(default_dyld_path, 0).len;
185 const cmdsize = @as(u32, @intCast(mem.alignForward(186 const cmdsize = @as(u32, @intCast(mem.alignForward(
186 u64,187 u64,
...@@ -204,7 +205,7 @@ const WriteDylibLCCtx = struct {...@@ -204,7 +205,7 @@ const WriteDylibLCCtx = struct {
204 compatibility_version: u32 = 0x10000,205 compatibility_version: u32 = 0x10000,
205};206};
206207
207pub fn writeDylibLC(ctx: WriteDylibLCCtx, bw: *std.io.BufferedWriter) !void {208pub fn writeDylibLC(ctx: WriteDylibLCCtx, bw: *Writer) !void {
208 const name_len = ctx.name.len + 1;209 const name_len = ctx.name.len + 1;
209 const cmdsize: u32 = @intCast(mem.alignForward(210 const cmdsize: u32 = @intCast(mem.alignForward(
210 u64,211 u64,
...@@ -252,7 +253,7 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {...@@ -252,7 +253,7 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {
252 }, writer);253 }, writer);
253}254}
254255
255pub fn writeRpathLC(bw: *std.io.BufferedWriter, rpath: []const u8) !void {256pub fn writeRpathLC(bw: *Writer, rpath: []const u8) !void {
256 const rpath_len = rpath.len + 1;257 const rpath_len = rpath.len + 1;
257 const cmdsize = @as(u32, @intCast(mem.alignForward(258 const cmdsize = @as(u32, @intCast(mem.alignForward(
258 u64,259 u64,
...@@ -268,7 +269,7 @@ pub fn writeRpathLC(bw: *std.io.BufferedWriter, rpath: []const u8) !void {...@@ -268,7 +269,7 @@ pub fn writeRpathLC(bw: *std.io.BufferedWriter, rpath: []const u8) !void {
268 try bw.splatByteAll(0, cmdsize - @sizeOf(macho.rpath_command) - rpath_len);269 try bw.splatByteAll(0, cmdsize - @sizeOf(macho.rpath_command) - rpath_len);
269}270}
270271
271pub fn writeVersionMinLC(bw: *std.io.BufferedWriter, platform: MachO.Platform, sdk_version: ?std.SemanticVersion) std.io.Writer.Error!void {272pub fn writeVersionMinLC(bw: *Writer, platform: MachO.Platform, sdk_version: ?std.SemanticVersion) Writer.Error!void {
272 const cmd: macho.LC = switch (platform.os_tag) {273 const cmd: macho.LC = switch (platform.os_tag) {
273 .macos => .VERSION_MIN_MACOSX,274 .macos => .VERSION_MIN_MACOSX,
274 .ios => .VERSION_MIN_IPHONEOS,275 .ios => .VERSION_MIN_IPHONEOS,
...@@ -286,7 +287,7 @@ pub fn writeVersionMinLC(bw: *std.io.BufferedWriter, platform: MachO.Platform, s...@@ -286,7 +287,7 @@ pub fn writeVersionMinLC(bw: *std.io.BufferedWriter, platform: MachO.Platform, s
286 }));287 }));
287}288}
288289
289pub fn writeBuildVersionLC(bw: *std.io.BufferedWriter, platform: MachO.Platform, sdk_version: ?std.SemanticVersion) std.io.Writer.Error!void {290pub fn writeBuildVersionLC(bw: *Writer, platform: MachO.Platform, sdk_version: ?std.SemanticVersion) Writer.Error!void {
290 const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);291 const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
291 try bw.writeStruct(macho.build_version_command{292 try bw.writeStruct(macho.build_version_command{
292 .cmdsize = cmdsize,293 .cmdsize = cmdsize,
src/link/MachO/relocatable.zig+3-4
...@@ -205,8 +205,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -205,8 +205,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
205 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});205 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});
206 }206 }
207207
208 var bw: std.io.BufferedWriter = undefined;208 var bw: Writer = .fixed(try gpa.alloc(u8, total_size));
209 bw.initFixed(try gpa.alloc(u8, total_size));
210 defer gpa.free(bw.buffer);209 defer gpa.free(bw.buffer);
211210
212 // Write magic211 // Write magic
...@@ -683,8 +682,7 @@ fn writeSectionsToFile(macho_file: *MachO) !void {...@@ -683,8 +682,7 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
683682
684fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struct { usize, usize } {683fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struct { usize, usize } {
685 const gpa = macho_file.base.comp.gpa;684 const gpa = macho_file.base.comp.gpa;
686 var bw: std.io.BufferedWriter = undefined;685 var bw: Writer = .fixed(try gpa.alloc(u8, load_commands.calcLoadCommandsSizeObject(macho_file)));
687 bw.initFixed(try gpa.alloc(u8, load_commands.calcLoadCommandsSizeObject(macho_file)));
688 defer gpa.free(bw.buffer);686 defer gpa.free(bw.buffer);
689687
690 var ncmds: usize = 0;688 var ncmds: usize = 0;
...@@ -759,6 +757,7 @@ const macho = std.macho;...@@ -759,6 +757,7 @@ const macho = std.macho;
759const math = std.math;757const math = std.math;
760const mem = std.mem;758const mem = std.mem;
761const state_log = std.log.scoped(.link_state);759const state_log = std.log.scoped(.link_state);
760const Writer = std.io.Writer;
762761
763const Archive = @import("Archive.zig");762const Archive = @import("Archive.zig");
764const Atom = @import("Atom.zig");763const Atom = @import("Atom.zig");
src/link/MachO/synthetic.zig+17-16
...@@ -27,7 +27,7 @@ pub const GotSection = struct {...@@ -27,7 +27,7 @@ pub const GotSection = struct {
27 return got.symbols.items.len * @sizeOf(u64);27 return got.symbols.items.len * @sizeOf(u64);
28 }28 }
2929
30 pub fn write(got: GotSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {30 pub fn write(got: GotSection, macho_file: *MachO, bw: *Writer) !void {
31 const tracy = trace(@src());31 const tracy = trace(@src());
32 defer tracy.end();32 defer tracy.end();
33 for (got.symbols.items) |ref| {33 for (got.symbols.items) |ref| {
...@@ -48,7 +48,7 @@ pub const GotSection = struct {...@@ -48,7 +48,7 @@ pub const GotSection = struct {
4848
49 pub fn format2(49 pub fn format2(
50 ctx: FormatCtx,50 ctx: FormatCtx,
51 bw: *std.io.BufferedWriter,51 bw: *Writer,
52 comptime unused_fmt_string: []const u8,52 comptime unused_fmt_string: []const u8,
53 ) !void {53 ) !void {
54 _ = unused_fmt_string;54 _ = unused_fmt_string;
...@@ -94,7 +94,7 @@ pub const StubsSection = struct {...@@ -94,7 +94,7 @@ pub const StubsSection = struct {
94 return stubs.symbols.items.len * header.reserved2;94 return stubs.symbols.items.len * header.reserved2;
95 }95 }
9696
97 pub fn write(stubs: StubsSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {97 pub fn write(stubs: StubsSection, macho_file: *MachO, bw: *Writer) !void {
98 const tracy = trace(@src());98 const tracy = trace(@src());
99 defer tracy.end();99 defer tracy.end();
100 const cpu_arch = macho_file.getTarget().cpu.arch;100 const cpu_arch = macho_file.getTarget().cpu.arch;
...@@ -137,7 +137,7 @@ pub const StubsSection = struct {...@@ -137,7 +137,7 @@ pub const StubsSection = struct {
137137
138 pub fn format2(138 pub fn format2(
139 ctx: FormatCtx,139 ctx: FormatCtx,
140 bw: *std.io.BufferedWriter,140 bw: *Writer,
141 comptime unused_fmt_string: []const u8,141 comptime unused_fmt_string: []const u8,
142 ) !void {142 ) !void {
143 _ = unused_fmt_string;143 _ = unused_fmt_string;
...@@ -185,7 +185,7 @@ pub const StubsHelperSection = struct {...@@ -185,7 +185,7 @@ pub const StubsHelperSection = struct {
185 return s;185 return s;
186 }186 }
187187
188 pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {188 pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *Writer) !void {
189 const tracy = trace(@src());189 const tracy = trace(@src());
190 defer tracy.end();190 defer tracy.end();
191191
...@@ -230,7 +230,7 @@ pub const StubsHelperSection = struct {...@@ -230,7 +230,7 @@ pub const StubsHelperSection = struct {
230 }230 }
231 }231 }
232232
233 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {233 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *Writer) !void {
234 _ = stubs_helper;234 _ = stubs_helper;
235 const obj = macho_file.getInternalObject().?;235 const obj = macho_file.getInternalObject().?;
236 const cpu_arch = macho_file.getTarget().cpu.arch;236 const cpu_arch = macho_file.getTarget().cpu.arch;
...@@ -289,7 +289,7 @@ pub const LaSymbolPtrSection = struct {...@@ -289,7 +289,7 @@ pub const LaSymbolPtrSection = struct {
289 return macho_file.stubs.symbols.items.len * @sizeOf(u64);289 return macho_file.stubs.symbols.items.len * @sizeOf(u64);
290 }290 }
291291
292 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {292 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, bw: *Writer) !void {
293 const tracy = trace(@src());293 const tracy = trace(@src());
294 defer tracy.end();294 defer tracy.end();
295 _ = laptr;295 _ = laptr;
...@@ -339,7 +339,7 @@ pub const TlvPtrSection = struct {...@@ -339,7 +339,7 @@ pub const TlvPtrSection = struct {
339 return tlv.symbols.items.len * @sizeOf(u64);339 return tlv.symbols.items.len * @sizeOf(u64);
340 }340 }
341341
342 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {342 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, bw: *Writer) !void {
343 const tracy = trace(@src());343 const tracy = trace(@src());
344 defer tracy.end();344 defer tracy.end();
345345
...@@ -364,7 +364,7 @@ pub const TlvPtrSection = struct {...@@ -364,7 +364,7 @@ pub const TlvPtrSection = struct {
364364
365 pub fn format2(365 pub fn format2(
366 ctx: FormatCtx,366 ctx: FormatCtx,
367 bw: *std.io.BufferedWriter,367 bw: *Writer,
368 comptime unused_fmt_string: []const u8,368 comptime unused_fmt_string: []const u8,
369 ) !void {369 ) !void {
370 _ = unused_fmt_string;370 _ = unused_fmt_string;
...@@ -415,7 +415,7 @@ pub const ObjcStubsSection = struct {...@@ -415,7 +415,7 @@ pub const ObjcStubsSection = struct {
415 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);415 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);
416 }416 }
417417
418 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {418 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, bw: *Writer) !void {
419 const tracy = trace(@src());419 const tracy = trace(@src());
420 defer tracy.end();420 defer tracy.end();
421421
...@@ -487,7 +487,7 @@ pub const ObjcStubsSection = struct {...@@ -487,7 +487,7 @@ pub const ObjcStubsSection = struct {
487487
488 pub fn format2(488 pub fn format2(
489 ctx: FormatCtx,489 ctx: FormatCtx,
490 bw: *std.io.BufferedWriter,490 bw: *Writer,
491 comptime unused_fmt_string: []const u8,491 comptime unused_fmt_string: []const u8,
492 ) !void {492 ) !void {
493 _ = unused_fmt_string;493 _ = unused_fmt_string;
...@@ -516,7 +516,7 @@ pub const Indsymtab = struct {...@@ -516,7 +516,7 @@ pub const Indsymtab = struct {
516 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);516 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);
517 }517 }
518518
519 pub fn write(ind: Indsymtab, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {519 pub fn write(ind: Indsymtab, macho_file: *MachO, bw: *Writer) !void {
520 const tracy = trace(@src());520 const tracy = trace(@src());
521 defer tracy.end();521 defer tracy.end();
522522
...@@ -593,7 +593,7 @@ pub const DataInCode = struct {...@@ -593,7 +593,7 @@ pub const DataInCode = struct {
593 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;593 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;
594 }594 }
595595
596 pub fn write(dice: DataInCode, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {596 pub fn write(dice: DataInCode, macho_file: *MachO, bw: *Writer) !void {
597 const base_address = if (!macho_file.base.isRelocatable())597 const base_address = if (!macho_file.base.isRelocatable())
598 macho_file.getTextSegment().vmaddr598 macho_file.getTextSegment().vmaddr
599 else599 else
...@@ -617,13 +617,14 @@ pub const DataInCode = struct {...@@ -617,13 +617,14 @@ pub const DataInCode = struct {
617 };617 };
618};618};
619619
620const std = @import("std");
620const aarch64 = @import("../aarch64.zig");621const aarch64 = @import("../aarch64.zig");
621const assert = std.debug.assert;622const assert = std.debug.assert;
622const macho = std.macho;623const macho = std.macho;
623const math = std.math;624const math = std.math;
624const std = @import("std");
625const trace = @import("../../tracy.zig").trace;
626
627const Allocator = std.mem.Allocator;625const Allocator = std.mem.Allocator;
626const Writer = std.io.Writer;
627
628const trace = @import("../../tracy.zig").trace;
628const MachO = @import("../MachO.zig");629const MachO = @import("../MachO.zig");
629const Symbol = @import("Symbol.zig");630const Symbol = @import("Symbol.zig");
src/link/Plan9.zig+27-27
...@@ -23,6 +23,7 @@ const Allocator = std.mem.Allocator;...@@ -23,6 +23,7 @@ const Allocator = std.mem.Allocator;
23const log = std.log.scoped(.link);23const log = std.log.scoped(.link);
24const assert = std.debug.assert;24const assert = std.debug.assert;
25const Path = std.Build.Cache.Path;25const Path = std.Build.Cache.Path;
26const Writer = std.io.Writer;
2627
27base: link.File,28base: link.File,
28sixtyfour_bit: bool,29sixtyfour_bit: bool,
...@@ -336,25 +337,24 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void...@@ -336,25 +337,24 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void
336 };337 };
337 try fn_map_res.value_ptr.functions.put(gpa, nav_index, out);338 try fn_map_res.value_ptr.functions.put(gpa, nav_index, out);
338339
339 var aw: std.io.AllocatingWriter = undefined;340 var aw: std.io.AllocatingWriter = .init(arena);
340 aw.init(arena);
341 defer aw.deinit();341 defer aw.deinit();
342 const bw = &aw.buffered_writer;342 const w = &aw.interface;
343343
344 // every 'z' starts with 0344 // every 'z' starts with 0
345 try bw.writeByte(0);345 try w.writeByte(0);
346 // path component value of '/'346 // path component value of '/'
347 try bw.writeInt(u16, 1, .big);347 try w.writeInt(u16, 1, .big);
348348
349 // getting the full file path349 // getting the full file path
350 {350 {
351 const full_path = try file.path.toAbsolute(comp.dirs, gpa);351 const full_path = try file.path.toAbsolute(comp.dirs, gpa);
352 defer gpa.free(full_path);352 defer gpa.free(full_path);
353 try self.addPathComponents(full_path, bw);353 try self.addPathComponents(full_path, w);
354 }354 }
355355
356 // null terminate356 // null terminate
357 try bw.writeByte(0);357 try w.writeByte(0);
358 const final = try aw.toOwnedSlice();358 const final = try aw.toOwnedSlice();
359 self.syms.items[fn_map_res.value_ptr.sym_index - 1] = .{359 self.syms.items[fn_map_res.value_ptr.sym_index - 1] = .{
360 .type = .z,360 .type = .z,
...@@ -370,17 +370,17 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void...@@ -370,17 +370,17 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void
370 }370 }
371}371}
372372
373fn addPathComponents(self: *Plan9, path: []const u8, bw: *std.io.BufferedWriter) !void {373fn addPathComponents(self: *Plan9, path: []const u8, w: *Writer) !void {
374 const gpa = self.base.comp.gpa;374 const gpa = self.base.comp.gpa;
375 const sep = std.fs.path.sep;375 const sep = std.fs.path.sep;
376 var it = std.mem.tokenizeScalar(u8, path, sep);376 var it = std.mem.tokenizeScalar(u8, path, sep);
377 while (it.next()) |component| {377 while (it.next()) |component| {
378 if (self.file_segments.get(component)) |num| {378 if (self.file_segments.get(component)) |num| {
379 try bw.writeInt(u16, num, .big);379 try w.writeInt(u16, num, .big);
380 } else {380 } else {
381 self.file_segments_i += 1;381 self.file_segments_i += 1;
382 try self.file_segments.put(gpa, component, self.file_segments_i);382 try self.file_segments.put(gpa, component, self.file_segments_i);
383 try bw.writeInt(u16, self.file_segments_i, .big);383 try w.writeInt(u16, self.file_segments_i, .big);
384 }384 }
385 }385 }
386}386}
...@@ -527,14 +527,14 @@ fn allocateGotIndex(self: *Plan9) usize {...@@ -527,14 +527,14 @@ fn allocateGotIndex(self: *Plan9) usize {
527 }527 }
528}528}
529529
530pub fn changeLine(bw: *std.io.Writer, delta_line: i32) !void {530pub fn changeLine(w: *std.io.Writer, delta_line: i32) !void {
531 if (delta_line > 0 and delta_line < 65) {531 if (delta_line > 0 and delta_line < 65) {
532 try bw.writeByte(@intCast(delta_line));532 try w.writeByte(@intCast(delta_line));
533 } else if (delta_line < 0 and delta_line > -65) {533 } else if (delta_line < 0 and delta_line > -65) {
534 try bw.writeByte(@intCast(-delta_line + 64));534 try w.writeByte(@intCast(-delta_line + 64));
535 } else if (delta_line != 0) {535 } else if (delta_line != 0) {
536 try bw.writeByte(0);536 try w.writeByte(0);
537 try bw.writeInt(i32, delta_line, .big);537 try w.writeInt(i32, delta_line, .big);
538 }538 }
539}539}
540540
...@@ -1205,16 +1205,16 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {...@@ -1205,16 +1205,16 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {
1205 try w.writeByte(0);1205 try w.writeByte(0);
1206}1206}
12071207
1208pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {1208pub fn writeSyms(self: *Plan9, w: *Writer) !void {
1209 const zcu = self.base.comp.zcu.?;1209 const zcu = self.base.comp.zcu.?;
1210 const ip = &zcu.intern_pool;1210 const ip = &zcu.intern_pool;
1211 // write __GOT1211 // write __GOT
1212 try self.writeSym(bw, self.syms.items[0]);1212 try self.writeSym(w, self.syms.items[0]);
1213 // write the f symbols1213 // write the f symbols
1214 {1214 {
1215 var it = self.file_segments.iterator();1215 var it = self.file_segments.iterator();
1216 while (it.next()) |entry| {1216 while (it.next()) |entry| {
1217 try self.writeSym(bw, .{1217 try self.writeSym(w, .{
1218 .type = .f,1218 .type = .f,
1219 .value = entry.value_ptr.*,1219 .value = entry.value_ptr.*,
1220 .name = entry.key_ptr.*,1220 .name = entry.key_ptr.*,
...@@ -1230,12 +1230,12 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1230,12 +1230,12 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1230 const nav_metadata = self.navs.get(nav_index).?;1230 const nav_metadata = self.navs.get(nav_index).?;
1231 const atom = self.getAtom(nav_metadata.index);1231 const atom = self.getAtom(nav_metadata.index);
1232 const sym = self.syms.items[atom.sym_index.?];1232 const sym = self.syms.items[atom.sym_index.?];
1233 try self.writeSym(bw, sym);1233 try self.writeSym(w, sym);
1234 if (self.nav_exports.get(nav_index)) |export_indices| {1234 if (self.nav_exports.get(nav_index)) |export_indices| {
1235 for (export_indices) |export_idx| {1235 for (export_indices) |export_idx| {
1236 const exp = export_idx.ptr(zcu);1236 const exp = export_idx.ptr(zcu);
1237 if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {1237 if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {
1238 try self.writeSym(bw, self.syms.items[exp_i]);1238 try self.writeSym(w, self.syms.items[exp_i]);
1239 }1239 }
1240 }1240 }
1241 }1241 }
...@@ -1248,7 +1248,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1248,7 +1248,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1248 const meta = kv.value_ptr;1248 const meta = kv.value_ptr;
1249 const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;1249 const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;
1250 const sym = self.syms.items[data_atom.sym_index.?];1250 const sym = self.syms.items[data_atom.sym_index.?];
1251 try self.writeSym(bw, sym);1251 try self.writeSym(w, sym);
1252 }1252 }
1253 }1253 }
1254 // text symbols are the hardest:1254 // text symbols are the hardest:
...@@ -1259,8 +1259,8 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1259,8 +1259,8 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1259 while (it_file.next()) |fentry| {1259 while (it_file.next()) |fentry| {
1260 var symidx_and_submap = fentry.value_ptr;1260 var symidx_and_submap = fentry.value_ptr;
1261 // write the z symbols1261 // write the z symbols
1262 try self.writeSym(bw, self.syms.items[symidx_and_submap.sym_index - 1]);1262 try self.writeSym(w, self.syms.items[symidx_and_submap.sym_index - 1]);
1263 try self.writeSym(bw, self.syms.items[symidx_and_submap.sym_index]);1263 try self.writeSym(w, self.syms.items[symidx_and_submap.sym_index]);
12641264
1265 // write all the decls come from the file of the z symbol1265 // write all the decls come from the file of the z symbol
1266 var submap_it = symidx_and_submap.functions.iterator();1266 var submap_it = symidx_and_submap.functions.iterator();
...@@ -1269,7 +1269,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1269,7 +1269,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1269 const nav_metadata = self.navs.get(nav_index).?;1269 const nav_metadata = self.navs.get(nav_index).?;
1270 const atom = self.getAtom(nav_metadata.index);1270 const atom = self.getAtom(nav_metadata.index);
1271 const sym = self.syms.items[atom.sym_index.?];1271 const sym = self.syms.items[atom.sym_index.?];
1272 try self.writeSym(bw, sym);1272 try self.writeSym(w, sym);
1273 if (self.nav_exports.get(nav_index)) |export_indices| {1273 if (self.nav_exports.get(nav_index)) |export_indices| {
1274 for (export_indices) |export_idx| {1274 for (export_indices) |export_idx| {
1275 const exp = export_idx.ptr(zcu);1275 const exp = export_idx.ptr(zcu);
...@@ -1277,7 +1277,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1277,7 +1277,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1277 const s = self.syms.items[exp_i];1277 const s = self.syms.items[exp_i];
1278 if (mem.eql(u8, s.name, "_start"))1278 if (mem.eql(u8, s.name, "_start"))
1279 self.entry_val = s.value;1279 self.entry_val = s.value;
1280 try self.writeSym(bw, s);1280 try self.writeSym(w, s);
1281 }1281 }
1282 }1282 }
1283 }1283 }
...@@ -1290,7 +1290,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1290,7 +1290,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1290 const meta = kv.value_ptr;1290 const meta = kv.value_ptr;
1291 const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;1291 const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;
1292 const sym = self.syms.items[text_atom.sym_index.?];1292 const sym = self.syms.items[text_atom.sym_index.?];
1293 try self.writeSym(bw, sym);1293 try self.writeSym(w, sym);
1294 }1294 }
1295 }1295 }
1296 }1296 }
...@@ -1299,7 +1299,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {...@@ -1299,7 +1299,7 @@ pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1299 if (idx) |atom_idx| {1299 if (idx) |atom_idx| {
1300 const atom = self.getAtom(atom_idx);1300 const atom = self.getAtom(atom_idx);
1301 const sym = self.syms.items[atom.sym_index.?];1301 const sym = self.syms.items[atom.sym_index.?];
1302 try self.writeSym(bw, sym);1302 try self.writeSym(w, sym);
1303 }1303 }
1304 }1304 }
1305}1305}
src/link/Wasm.zig+5-5
...@@ -28,6 +28,7 @@ const fs = std.fs;...@@ -28,6 +28,7 @@ const fs = std.fs;
28const leb = std.leb;28const leb = std.leb;
29const log = std.log.scoped(.link);29const log = std.log.scoped(.link);
30const mem = std.mem;30const mem = std.mem;
31const Writer = std.io.Writer;
3132
32const Mir = @import("../arch/wasm/Mir.zig");33const Mir = @import("../arch/wasm/Mir.zig");
33const CodeGen = @import("../arch/wasm/CodeGen.zig");34const CodeGen = @import("../arch/wasm/CodeGen.zig");
...@@ -2124,8 +2125,8 @@ pub const FunctionType = extern struct {...@@ -2124,8 +2125,8 @@ pub const FunctionType = extern struct {
2124 wasm: *const Wasm,2125 wasm: *const Wasm,
2125 ft: FunctionType,2126 ft: FunctionType,
21262127
2127 pub fn format(self: Formatter, bw: *std.io.BufferedWriter, comptime format_string: []const u8) std.io.Writer.Error!void {2128 pub fn format(self: Formatter, bw: *Writer, comptime format_string: []const u8) Writer.Error!void {
2128 if (format_string.len != 0) std.fmt.invalidFmtError(format_string, self);2129 comptime assert(format_string.len == 0);
2129 const params = self.ft.params.slice(self.wasm);2130 const params = self.ft.params.slice(self.wasm);
2130 const returns = self.ft.returns.slice(self.wasm);2131 const returns = self.ft.returns.slice(self.wasm);
21312132
...@@ -2904,7 +2905,7 @@ pub const Feature = packed struct(u8) {...@@ -2904,7 +2905,7 @@ pub const Feature = packed struct(u8) {
2904 @"=",2905 @"=",
2905 };2906 };
29062907
2907 pub fn format(feature: Feature, bw: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {2908 pub fn format(feature: Feature, bw: *Writer, comptime fmt: []const u8) Writer.Error!void {
2908 _ = fmt;2909 _ = fmt;
2909 try bw.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) });2910 try bw.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) });
2910 }2911 }
...@@ -3037,8 +3038,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {...@@ -3037,8 +3038,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
3037 const stat = try obj.file.stat();3038 const stat = try obj.file.stat();
3038 const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;3039 const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;
30393040
3040 var br: std.io.Reader = undefined;3041 var br: std.io.Reader = .fixed(try gpa.alloc(u8, size));
3041 br.initFixed(try gpa.alloc(u8, size));
3042 defer gpa.free(br.storageBuffer());3042 defer gpa.free(br.storageBuffer());
30433043
3044 const n = try obj.file.preadAll(br.storageBuffer(), 0);3044 const n = try obj.file.preadAll(br.storageBuffer(), 0);
src/link/Wasm/Flush.zig+355-354
...@@ -18,6 +18,7 @@ const Allocator = std.mem.Allocator;...@@ -18,6 +18,7 @@ const Allocator = std.mem.Allocator;
18const mem = std.mem;18const mem = std.mem;
19const log = std.log.scoped(.link);19const log = std.log.scoped(.link);
20const assert = std.debug.assert;20const assert = std.debug.assert;
21const Writer = std.io.Writer;
2122
22/// Ordered list of data segments that will appear in the final binary.23/// Ordered list of data segments that will appear in the final binary.
23/// When sorted, to-be-merged segments will be made adjacent.24/// When sorted, to-be-merged segments will be made adjacent.
...@@ -557,11 +558,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -557,11 +558,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
557 var data_section_index: ?u32 = null;558 var data_section_index: ?u32 = null;
558559
559 assert(f.binary_bytes.items.len == 0);560 assert(f.binary_bytes.items.len == 0);
560 var aw: std.io.AllocatingWriter = undefined;561 var aw: std.io.AllocatingWriter = .fromArrayList(gpa, &f.binary_bytes);
561 const bw = aw.fromArrayList(gpa, &f.binary_bytes);
562 defer f.binary_bytes = aw.toArrayList();562 defer f.binary_bytes = aw.toArrayList();
563 const w = &aw.interface;
563564
564 try bw.writeAll(&std.wasm.magic ++ &std.wasm.version);565 try w.writeAll(&std.wasm.magic ++ &std.wasm.version);
565566
566 // Type section.567 // Type section.
567 for (f.function_imports.values()) |id| {568 for (f.function_imports.values()) |id| {
...@@ -571,16 +572,16 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -571,16 +572,16 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
571 try f.func_types.put(gpa, function.typeIndex(wasm), {});572 try f.func_types.put(gpa, function.typeIndex(wasm), {});
572 }573 }
573 if (f.func_types.entries.len != 0) {574 if (f.func_types.entries.len != 0) {
574 const header_offset = try reserveVecSectionHeader(bw);575 const header_offset = try reserveVecSectionHeader(w);
575 for (f.func_types.keys()) |func_type_index| {576 for (f.func_types.keys()) |func_type_index| {
576 const func_type = func_type_index.ptr(wasm);577 const func_type = func_type_index.ptr(wasm);
577 try bw.writeLeb128(std.wasm.function_type);578 try w.writeLeb128(std.wasm.function_type);
578 const params = func_type.params.slice(wasm);579 const params = func_type.params.slice(wasm);
579 try bw.writeLeb128(params.len);580 try w.writeLeb128(params.len);
580 for (params) |param_ty| try bw.writeLeb128(@intFromEnum(param_ty));581 for (params) |param_ty| try w.writeLeb128(@intFromEnum(param_ty));
581 const returns = func_type.returns.slice(wasm);582 const returns = func_type.returns.slice(wasm);
582 try bw.writeLeb128(returns.len);583 try w.writeLeb128(returns.len);
583 for (returns) |ret_ty| try bw.writeLeb128(@intFromEnum(ret_ty));584 for (returns) |ret_ty| try w.writeLeb128(@intFromEnum(ret_ty));
584 }585 }
585 replaceVecSectionHeader(&aw, header_offset, .type, @intCast(f.func_types.entries.len));586 replaceVecSectionHeader(&aw, header_offset, .type, @intCast(f.func_types.entries.len));
586 section_index += 1;587 section_index += 1;
...@@ -595,42 +596,42 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -595,42 +596,42 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
595 // Import section596 // Import section
596 {597 {
597 var total_imports: usize = 0;598 var total_imports: usize = 0;
598 const header_offset = try reserveVecSectionHeader(bw);599 const header_offset = try reserveVecSectionHeader(w);
599600
600 for (f.function_imports.values()) |id| {601 for (f.function_imports.values()) |id| {
601 const module_name = id.moduleName(wasm).slice(wasm).?;602 const module_name = id.moduleName(wasm).slice(wasm).?;
602 try bw.writeLeb128(module_name.len);603 try w.writeLeb128(module_name.len);
603 try bw.writeAll(module_name);604 try w.writeAll(module_name);
604605
605 const name = id.importName(wasm).slice(wasm);606 const name = id.importName(wasm).slice(wasm);
606 try bw.writeLeb128(name.len);607 try w.writeLeb128(name.len);
607 try bw.writeAll(name);608 try w.writeAll(name);
608609
609 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.function));610 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.function));
610 const type_index: FuncTypeIndex = .fromTypeIndex(id.functionType(wasm), f);611 const type_index: FuncTypeIndex = .fromTypeIndex(id.functionType(wasm), f);
611 try bw.writeLeb128(@intFromEnum(type_index));612 try w.writeLeb128(@intFromEnum(type_index));
612 }613 }
613 total_imports += f.function_imports.entries.len;614 total_imports += f.function_imports.entries.len;
614615
615 for (wasm.table_imports.values()) |id| {616 for (wasm.table_imports.values()) |id| {
616 const table_import = id.value(wasm);617 const table_import = id.value(wasm);
617 const module_name = table_import.module_name.slice(wasm);618 const module_name = table_import.module_name.slice(wasm);
618 try bw.writeLeb128(module_name.len);619 try w.writeLeb128(module_name.len);
619 try bw.writeAll(module_name);620 try w.writeAll(module_name);
620621
621 const name = table_import.name.slice(wasm);622 const name = table_import.name.slice(wasm);
622 try bw.writeLeb128(name.len);623 try w.writeLeb128(name.len);
623 try bw.writeAll(name);624 try w.writeAll(name);
624625
625 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.table));626 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.table));
626 try bw.writeLeb128(@intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to())));627 try w.writeLeb128(@intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to())));
627 try emitLimits(bw, table_import.limits());628 try emitLimits(w, table_import.limits());
628 }629 }
629 total_imports += wasm.table_imports.entries.len;630 total_imports += wasm.table_imports.entries.len;
630631
631 if (import_memory) {632 if (import_memory) {
632 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;633 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;
633 try emitMemoryImport(wasm, bw, name, &.{634 try emitMemoryImport(wasm, w, name, &.{
634 // TODO the import_memory option needs to specify from which module635 // TODO the import_memory option needs to specify from which module
635 .module_name = wasm.object_host_name.unwrap().?,636 .module_name = wasm.object_host_name.unwrap().?,
636 .limits_min = wasm.memories.limits.min,637 .limits_min = wasm.memories.limits.min,
...@@ -644,17 +645,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -644,17 +645,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
644645
645 for (f.global_imports.values()) |id| {646 for (f.global_imports.values()) |id| {
646 const module_name = id.moduleName(wasm).slice(wasm).?;647 const module_name = id.moduleName(wasm).slice(wasm).?;
647 try bw.writeLeb128(module_name.len);648 try w.writeLeb128(module_name.len);
648 try bw.writeAll(module_name);649 try w.writeAll(module_name);
649650
650 const name = id.importName(wasm).slice(wasm);651 const name = id.importName(wasm).slice(wasm);
651 try bw.writeLeb128(name.len);652 try w.writeLeb128(name.len);
652 try bw.writeAll(name);653 try w.writeAll(name);
653654
654 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.global));655 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.global));
655 const global_type = id.globalType(wasm);656 const global_type = id.globalType(wasm);
656 try bw.writeLeb128(@intFromEnum(global_type.valtype));657 try w.writeLeb128(@intFromEnum(global_type.valtype));
657 try bw.writeByte(@intFromBool(global_type.mutable));658 try w.writeByte(@intFromBool(global_type.mutable));
658 }659 }
659 total_imports += f.global_imports.entries.len;660 total_imports += f.global_imports.entries.len;
660661
...@@ -668,10 +669,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -668,10 +669,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
668669
669 // Function section670 // Function section
670 if (wasm.functions.count() != 0) {671 if (wasm.functions.count() != 0) {
671 const header_offset = try reserveVecSectionHeader(bw);672 const header_offset = try reserveVecSectionHeader(w);
672 for (wasm.functions.keys()) |function| {673 for (wasm.functions.keys()) |function| {
673 const index: FuncTypeIndex = .fromTypeIndex(function.typeIndex(wasm), f);674 const index: FuncTypeIndex = .fromTypeIndex(function.typeIndex(wasm), f);
674 try bw.writeLeb128(@intFromEnum(index));675 try w.writeLeb128(@intFromEnum(index));
675 }676 }
676677
677 replaceVecSectionHeader(&aw, header_offset, .function, @intCast(wasm.functions.count()));678 replaceVecSectionHeader(&aw, header_offset, .function, @intCast(wasm.functions.count()));
...@@ -680,11 +681,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -680,11 +681,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
680681
681 // Table section682 // Table section
682 if (wasm.tables.entries.len > 0) {683 if (wasm.tables.entries.len > 0) {
683 const header_offset = try reserveVecSectionHeader(bw);684 const header_offset = try reserveVecSectionHeader(w);
684685
685 for (wasm.tables.keys()) |table| {686 for (wasm.tables.keys()) |table| {
686 try bw.writeLeb128(@intFromEnum(table.refType(wasm)));687 try w.writeLeb128(@intFromEnum(table.refType(wasm)));
687 try emitLimits(bw, table.limits(wasm));688 try emitLimits(w, table.limits(wasm));
688 }689 }
689690
690 replaceVecSectionHeader(&aw, header_offset, .table, @intCast(wasm.tables.entries.len));691 replaceVecSectionHeader(&aw, header_offset, .table, @intCast(wasm.tables.entries.len));
...@@ -693,8 +694,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -693,8 +694,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
693694
694 // Memory section. wasm currently only supports 1 linear memory segment.695 // Memory section. wasm currently only supports 1 linear memory segment.
695 if (!import_memory) {696 if (!import_memory) {
696 const header_offset = try reserveVecSectionHeader(bw);697 const header_offset = try reserveVecSectionHeader(w);
697 try emitLimits(bw, wasm.memories.limits);698 try emitLimits(w, wasm.memories.limits);
698 replaceVecSectionHeader(&aw, header_offset, .memory, 1);699 replaceVecSectionHeader(&aw, header_offset, .memory, 1);
699 section_index += 1;700 section_index += 1;
700 }701 }
...@@ -702,24 +703,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -702,24 +703,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
702 // Global section.703 // Global section.
703 const globals_len: u32 = @intCast(wasm.globals.entries.len);704 const globals_len: u32 = @intCast(wasm.globals.entries.len);
704 if (globals_len > 0) {705 if (globals_len > 0) {
705 const header_offset = try reserveVecSectionHeader(bw);706 const header_offset = try reserveVecSectionHeader(w);
706707
707 for (wasm.globals.keys()) |global_resolution| {708 for (wasm.globals.keys()) |global_resolution| {
708 switch (global_resolution.unpack(wasm)) {709 switch (global_resolution.unpack(wasm)) {
709 .unresolved => unreachable,710 .unresolved => unreachable,
710 .__heap_base => try appendGlobal(bw, false, virtual_addrs.heap_base),711 .__heap_base => try appendGlobal(w, false, virtual_addrs.heap_base),
711 .__heap_end => try appendGlobal(bw, false, virtual_addrs.heap_end),712 .__heap_end => try appendGlobal(w, false, virtual_addrs.heap_end),
712 .__stack_pointer => try appendGlobal(bw, true, virtual_addrs.stack_pointer),713 .__stack_pointer => try appendGlobal(w, true, virtual_addrs.stack_pointer),
713 .__tls_align => try appendGlobal(bw, false, @intCast(virtual_addrs.tls_align.toByteUnits().?)),714 .__tls_align => try appendGlobal(w, false, @intCast(virtual_addrs.tls_align.toByteUnits().?)),
714 .__tls_base => try appendGlobal(bw, true, virtual_addrs.tls_base.?),715 .__tls_base => try appendGlobal(w, true, virtual_addrs.tls_base.?),
715 .__tls_size => try appendGlobal(bw, false, virtual_addrs.tls_size.?),716 .__tls_size => try appendGlobal(w, false, virtual_addrs.tls_size.?),
716 .object_global => |i| {717 .object_global => |i| {
717 const global = i.ptr(wasm);718 const global = i.ptr(wasm);
718 try bw.writeAll(&.{719 try w.writeAll(&.{
719 @intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())),720 @intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())),
720 @intFromBool(global.flags.global_type.mutable),721 @intFromBool(global.flags.global_type.mutable),
721 });722 });
722 try emitExpr(wasm, bw, global.expr);723 try emitExpr(wasm, w, global.expr);
723 },724 },
724 .nav_exe => unreachable, // Zig source code currently cannot represent this.725 .nav_exe => unreachable, // Zig source code currently cannot represent this.
725 .nav_obj => unreachable, // Zig source code currently cannot represent this.726 .nav_obj => unreachable, // Zig source code currently cannot represent this.
...@@ -732,44 +733,44 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -732,44 +733,44 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
732733
733 // Export section734 // Export section
734 {735 {
735 const header_offset = try reserveVecSectionHeader(bw);736 const header_offset = try reserveVecSectionHeader(w);
736 var exports_len: usize = 0;737 var exports_len: usize = 0;
737738
738 for (wasm.function_exports.keys(), wasm.function_exports.values()) |exp_name, function_index| {739 for (wasm.function_exports.keys(), wasm.function_exports.values()) |exp_name, function_index| {
739 const name = exp_name.slice(wasm);740 const name = exp_name.slice(wasm);
740 try bw.writeLeb128(name.len);741 try w.writeLeb128(name.len);
741 try bw.writeAll(name);742 try w.writeAll(name);
742 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.function));743 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.function));
743 const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, function_index);744 const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, function_index);
744 try bw.writeLeb128(@intFromEnum(func_index));745 try w.writeLeb128(@intFromEnum(func_index));
745 }746 }
746 exports_len += wasm.function_exports.entries.len;747 exports_len += wasm.function_exports.entries.len;
747748
748 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {749 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {
749 const name = "__indirect_function_table";750 const name = "__indirect_function_table";
750 const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);751 const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);
751 try bw.writeLeb128(name.len);752 try w.writeLeb128(name.len);
752 try bw.writeAll(name);753 try w.writeAll(name);
753 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.table));754 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.table));
754 try bw.writeLeb128(index);755 try w.writeLeb128(index);
755 exports_len += 1;756 exports_len += 1;
756 }757 }
757758
758 if (export_memory) {759 if (export_memory) {
759 const name = "memory";760 const name = "memory";
760 try bw.writeLeb128(name.len);761 try w.writeLeb128(name.len);
761 try bw.writeAll(name);762 try w.writeAll(name);
762 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));763 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));
763 try bw.writeUleb128(0);764 try w.writeUleb128(0);
764 exports_len += 1;765 exports_len += 1;
765 }766 }
766767
767 for (wasm.global_exports.items) |exp| {768 for (wasm.global_exports.items) |exp| {
768 const name = exp.name.slice(wasm);769 const name = exp.name.slice(wasm);
769 try bw.writeLeb128(name.len);770 try w.writeLeb128(name.len);
770 try bw.writeAll(name);771 try w.writeAll(name);
771 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.global));772 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.global));
772 try bw.writeLeb128(@intFromEnum(exp.global_index));773 try w.writeLeb128(@intFromEnum(exp.global_index));
773 }774 }
774 exports_len += wasm.global_exports.items.len;775 exports_len += wasm.global_exports.items.len;
775776
...@@ -790,19 +791,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -790,19 +791,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
790791
791 // element section792 // element section
792 if (f.indirect_function_table.entries.len > 0) {793 if (f.indirect_function_table.entries.len > 0) {
793 const header_offset = try reserveVecSectionHeader(bw);794 const header_offset = try reserveVecSectionHeader(w);
794795
795 // indirect function table elements796 // indirect function table elements
796 const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);797 const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);
797 // passive with implicit 0-index table or set table index manually798 // passive with implicit 0-index table or set table index manually
798 const flags: u32 = if (table_index == 0) 0x0 else 0x02;799 const flags: u32 = if (table_index == 0) 0x0 else 0x02;
799 try bw.writeLeb128(flags);800 try w.writeLeb128(flags);
800 if (flags == 0x02) try bw.writeLeb128(table_index);801 if (flags == 0x02) try w.writeLeb128(table_index);
801 // We start at index 1, so unresolved function pointers are invalid802 // We start at index 1, so unresolved function pointers are invalid
802 try emitInit(bw, .{ .i32_const = 1 });803 try emitInit(w, .{ .i32_const = 1 });
803 if (flags == 0x02) try bw.writeUleb128(0); // represents funcref804 if (flags == 0x02) try w.writeUleb128(0); // represents funcref
804 try bw.writeLeb128(f.indirect_function_table.entries.len);805 try w.writeLeb128(f.indirect_function_table.entries.len);
805 for (f.indirect_function_table.keys()) |func_index| try bw.writeLeb128(@intFromEnum(func_index));806 for (f.indirect_function_table.keys()) |func_index| try w.writeLeb128(@intFromEnum(func_index));
806807
807 replaceVecSectionHeader(&aw, header_offset, .element, 1);808 replaceVecSectionHeader(&aw, header_offset, .element, 1);
808 section_index += 1;809 section_index += 1;
...@@ -810,42 +811,42 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -810,42 +811,42 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
810811
811 // When the shared-memory option is enabled, we *must* emit the 'data count' section.812 // When the shared-memory option is enabled, we *must* emit the 'data count' section.
812 if (f.data_segment_groups.items.len > 0) {813 if (f.data_segment_groups.items.len > 0) {
813 const header_offset = try reserveVecSectionHeader(bw);814 const header_offset = try reserveVecSectionHeader(w);
814 replaceVecSectionHeader(&aw, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));815 replaceVecSectionHeader(&aw, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));
815 }816 }
816817
817 // Code section.818 // Code section.
818 if (wasm.functions.count() != 0) {819 if (wasm.functions.count() != 0) {
819 const header_offset = try reserveVecSectionHeader(bw);820 const header_offset = try reserveVecSectionHeader(w);
820821
821 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {822 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {
822 .unresolved => unreachable,823 .unresolved => unreachable,
823 .__wasm_apply_global_tls_relocs => @panic("TODO lower __wasm_apply_global_tls_relocs"),824 .__wasm_apply_global_tls_relocs => @panic("TODO lower __wasm_apply_global_tls_relocs"),
824 .__wasm_call_ctors => {825 .__wasm_call_ctors => {
825 const code_start = try reserveSizeHeader(bw);826 const code_start = try reserveSizeHeader(w);
826 defer replaceSizeHeader(&aw, code_start);827 defer replaceSizeHeader(&aw, code_start);
827 try emitCallCtorsFunction(wasm, bw);828 try emitCallCtorsFunction(wasm, w);
828 },829 },
829 .__wasm_init_memory => {830 .__wasm_init_memory => {
830 const code_start = try reserveSizeHeader(bw);831 const code_start = try reserveSizeHeader(w);
831 defer replaceSizeHeader(&aw, code_start);832 defer replaceSizeHeader(&aw, code_start);
832 try emitInitMemoryFunction(wasm, bw, &virtual_addrs);833 try emitInitMemoryFunction(wasm, w, &virtual_addrs);
833 },834 },
834 .__wasm_init_tls => {835 .__wasm_init_tls => {
835 const code_start = try reserveSizeHeader(bw);836 const code_start = try reserveSizeHeader(w);
836 defer replaceSizeHeader(&aw, code_start);837 defer replaceSizeHeader(&aw, code_start);
837 try emitInitTlsFunction(wasm, bw);838 try emitInitTlsFunction(wasm, w);
838 },839 },
839 .object_function => |i| {840 .object_function => |i| {
840 const ptr = i.ptr(wasm);841 const ptr = i.ptr(wasm);
841 const code = ptr.code.slice(wasm);842 const code = ptr.code.slice(wasm);
842 try bw.writeLeb128(code.len);843 try w.writeLeb128(code.len);
843 const code_start = bw.count;844 const code_start = w.count;
844 try bw.writeAll(code);845 try w.writeAll(code);
845 if (!is_obj) applyRelocs(aw.getWritten()[code_start..], ptr.offset, ptr.relocations(wasm), wasm);846 if (!is_obj) applyRelocs(aw.getWritten()[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
846 },847 },
847 .zcu_func => |i| {848 .zcu_func => |i| {
848 const code_start = try reserveSizeHeader(bw);849 const code_start = try reserveSizeHeader(w);
849 defer replaceSizeHeader(&aw, code_start);850 defer replaceSizeHeader(&aw, code_start);
850851
851 log.debug("lowering function code for '{s}'", .{resolution.name(wasm).?});852 log.debug("lowering function code for '{s}'", .{resolution.name(wasm).?});
...@@ -855,7 +856,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -855,7 +856,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
855 const ip_index = i.key(wasm).*;856 const ip_index = i.key(wasm).*;
856 switch (ip.indexToKey(ip_index)) {857 switch (ip.indexToKey(ip_index)) {
857 .enum_type => {858 .enum_type => {
858 try emitTagNameFunction(wasm, bw, f.data_segments.get(.__zig_tag_name_table).?, i.value(wasm).tag_name.table_index, ip_index);859 try emitTagNameFunction(wasm, w, f.data_segments.get(.__zig_tag_name_table).?, i.value(wasm).tag_name.table_index, ip_index);
859 },860 },
860 else => {861 else => {
861 const func = i.value(wasm).function;862 const func = i.value(wasm).function;
...@@ -870,7 +871,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -870,7 +871,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
870 .func_tys = undefined,871 .func_tys = undefined,
871 .error_name_table_ref_count = undefined,872 .error_name_table_ref_count = undefined,
872 };873 };
873 try mir.lower(wasm, bw);874 try mir.lower(wasm, w);
874 },875 },
875 }876 }
876 },877 },
...@@ -912,7 +913,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -912,7 +913,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
912913
913 // Data section.914 // Data section.
914 if (f.data_segment_groups.items.len != 0) {915 if (f.data_segment_groups.items.len != 0) {
915 const header_offset = try reserveVecSectionHeader(bw);916 const header_offset = try reserveVecSectionHeader(w);
916917
917 var group_index: u32 = 0;918 var group_index: u32 = 0;
918 var segment_offset: u32 = 0;919 var segment_offset: u32 = 0;
...@@ -920,7 +921,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -920,7 +921,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
920 var group_end_addr = f.data_segment_groups.items[group_index].end_addr;921 var group_end_addr = f.data_segment_groups.items[group_index].end_addr;
921 for (segment_ids, segment_vaddrs) |segment_id, segment_vaddr| {922 for (segment_ids, segment_vaddrs) |segment_id, segment_vaddr| {
922 if (segment_vaddr >= group_end_addr) {923 if (segment_vaddr >= group_end_addr) {
923 try bw.splatByteAll(0, group_end_addr - group_start_addr - segment_offset);924 try w.splatByteAll(0, group_end_addr - group_start_addr - segment_offset);
924 group_index += 1;925 group_index += 1;
925 if (group_index >= f.data_segment_groups.items.len) {926 if (group_index >= f.data_segment_groups.items.len) {
926 // All remaining segments are zero.927 // All remaining segments are zero.
...@@ -934,10 +935,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -934,10 +935,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
934 const group_size = group_end_addr - group_start_addr;935 const group_size = group_end_addr - group_start_addr;
935 log.debug("emit data section group, {d} bytes", .{group_size});936 log.debug("emit data section group, {d} bytes", .{group_size});
936 const flags: Object.DataSegmentFlags = if (segment_id.isPassive(wasm)) .passive else .active;937 const flags: Object.DataSegmentFlags = if (segment_id.isPassive(wasm)) .passive else .active;
937 try bw.writeLeb128(@intFromEnum(flags));938 try w.writeLeb128(@intFromEnum(flags));
938 // Passive segments are initialized at runtime.939 // Passive segments are initialized at runtime.
939 if (flags != .passive) try emitInit(bw, .{ .i32_const = @as(i32, @bitCast(group_start_addr)) });940 if (flags != .passive) try emitInit(w, .{ .i32_const = @as(i32, @bitCast(group_start_addr)) });
940 try bw.writeLeb128(group_size);941 try w.writeLeb128(group_size);
941 }942 }
942 if (segment_id.isEmpty(wasm)) {943 if (segment_id.isEmpty(wasm)) {
943 // It counted for virtual memory but it does not go into the binary.944 // It counted for virtual memory but it does not go into the binary.
...@@ -946,59 +947,59 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -946,59 +947,59 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
946947
947 // Padding for alignment.948 // Padding for alignment.
948 const needed_offset = segment_vaddr - group_start_addr;949 const needed_offset = segment_vaddr - group_start_addr;
949 try bw.splatByteAll(0, needed_offset - segment_offset);950 try w.splatByteAll(0, needed_offset - segment_offset);
950 segment_offset = needed_offset;951 segment_offset = needed_offset;
951952
952 const code_start = bw.count;953 const code_start = w.count;
953 append: {954 append: {
954 const code = switch (segment_id.unpack(wasm)) {955 const code = switch (segment_id.unpack(wasm)) {
955 .__heap_base => {956 .__heap_base => {
956 try bw.writeInt(u32, virtual_addrs.heap_base, .little);957 try w.writeInt(u32, virtual_addrs.heap_base, .little);
957 break :append;958 break :append;
958 },959 },
959 .__heap_end => {960 .__heap_end => {
960 try bw.writeInt(u32, virtual_addrs.heap_end, .little);961 try w.writeInt(u32, virtual_addrs.heap_end, .little);
961 break :append;962 break :append;
962 },963 },
963 .__zig_error_names => {964 .__zig_error_names => {
964 try bw.writeAll(wasm.error_name_bytes.items);965 try w.writeAll(wasm.error_name_bytes.items);
965 break :append;966 break :append;
966 },967 },
967 .__zig_error_name_table => {968 .__zig_error_name_table => {
968 if (is_obj) @panic("TODO error name table reloc");969 if (is_obj) @panic("TODO error name table reloc");
969 const base = f.data_segments.get(.__zig_error_names).?;970 const base = f.data_segments.get(.__zig_error_names).?;
970 if (!is64) {971 if (!is64) {
971 try emitTagNameTable(bw, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);972 try emitTagNameTable(w, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);
972 } else {973 } else {
973 try emitTagNameTable(bw, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64);974 try emitTagNameTable(w, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64);
974 }975 }
975 break :append;976 break :append;
976 },977 },
977 .__zig_tag_names => {978 .__zig_tag_names => {
978 try bw.writeAll(wasm.tag_name_bytes.items);979 try w.writeAll(wasm.tag_name_bytes.items);
979 break :append;980 break :append;
980 },981 },
981 .__zig_tag_name_table => {982 .__zig_tag_name_table => {
982 if (is_obj) @panic("TODO tag name table reloc");983 if (is_obj) @panic("TODO tag name table reloc");
983 const base = f.data_segments.get(.__zig_tag_names).?;984 const base = f.data_segments.get(.__zig_tag_names).?;
984 if (!is64) {985 if (!is64) {
985 try emitTagNameTable(bw, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32);986 try emitTagNameTable(w, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32);
986 } else {987 } else {
987 try emitTagNameTable(bw, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64);988 try emitTagNameTable(w, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64);
988 }989 }
989 break :append;990 break :append;
990 },991 },
991 .object => |i| {992 .object => |i| {
992 const ptr = i.ptr(wasm);993 const ptr = i.ptr(wasm);
993 try bw.writeAll(ptr.payload.slice(wasm));994 try w.writeAll(ptr.payload.slice(wasm));
994 if (!is_obj) applyRelocs(aw.getWritten()[code_start..], ptr.offset, ptr.relocations(wasm), wasm);995 if (!is_obj) applyRelocs(aw.getWritten()[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
995 break :append;996 break :append;
996 },997 },
997 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code,998 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code,
998 };999 };
999 try bw.writeAll(code.slice(wasm));1000 try w.writeAll(code.slice(wasm));
1000 }1001 }
1001 segment_offset += @intCast(bw.count - code_start);1002 segment_offset += @intCast(w.count - code_start);
1002 }1003 }
10031004
1004 replaceVecSectionHeader(&aw, header_offset, .data, @intCast(f.data_segment_groups.items.len));1005 replaceVecSectionHeader(&aw, header_offset, .data, @intCast(f.data_segment_groups.items.len));
...@@ -1019,7 +1020,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1019,7 +1020,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1019 .none => {},1020 .none => {},
1020 .fast => {1021 .fast => {
1021 var id: [16]u8 = undefined;1022 var id: [16]u8 = undefined;
1022 std.crypto.hash.sha3.TurboShake128(null).hash(bw.getWritten(), &id, .{});1023 std.crypto.hash.sha3.TurboShake128(null).hash(w.getWritten(), &id, .{});
1023 var uuid: [36]u8 = undefined;1024 var uuid: [36]u8 = undefined;
1024 _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{1025 _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{
1025 id[0..4], id[4..6], id[6..8], id[8..10], id[10..],1026 id[0..4], id[4..6], id[6..8], id[8..10], id[10..],
...@@ -1067,62 +1068,62 @@ fn emitNameSection(...@@ -1067,62 +1068,62 @@ fn emitNameSection(
1067 data_segment_groups: []const DataSegmentGroup,1068 data_segment_groups: []const DataSegmentGroup,
1068) !void {1069) !void {
1069 const f = &wasm.flush_buffer;1070 const f = &wasm.flush_buffer;
1070 const bw = &aw.buffered_writer;1071 const w = &aw.interface;
1071 const header_offset = try reserveSectionHeader(bw);1072 const header_offset = try reserveSectionHeader(w);
1072 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));1073 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
10731074
1074 const section_name = "name";1075 const section_name = "name";
1075 try bw.writeLeb128(section_name.len);1076 try w.writeLeb128(section_name.len);
1076 try bw.writeAll(section_name);1077 try w.writeAll(section_name);
10771078
1078 {1079 {
1079 const sub_header_offset = try reserveSectionHeader(bw);1080 const sub_header_offset = try reserveSectionHeader(w);
1080 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.function));1081 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.function));
10811082
1082 try bw.writeLeb128(f.function_imports.entries.len + wasm.functions.entries.len);1083 try w.writeLeb128(f.function_imports.entries.len + wasm.functions.entries.len);
1083 for (f.function_imports.keys(), 0..) |name_index, function_index| {1084 for (f.function_imports.keys(), 0..) |name_index, function_index| {
1084 const name = name_index.slice(wasm);1085 const name = name_index.slice(wasm);
1085 try bw.writeLeb128(function_index);1086 try w.writeLeb128(function_index);
1086 try bw.writeLeb128(name.len);1087 try w.writeLeb128(name.len);
1087 try bw.writeAll(name);1088 try w.writeAll(name);
1088 }1089 }
1089 for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| {1090 for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| {
1090 const name = resolution.name(wasm).?;1091 const name = resolution.name(wasm).?;
1091 try bw.writeLeb128(function_index);1092 try w.writeLeb128(function_index);
1092 try bw.writeLeb128(name.len);1093 try w.writeLeb128(name.len);
1093 try bw.writeAll(name);1094 try w.writeAll(name);
1094 }1095 }
1095 }1096 }
10961097
1097 {1098 {
1098 const sub_header_offset = try reserveSectionHeader(bw);1099 const sub_header_offset = try reserveSectionHeader(w);
1099 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.global));1100 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.global));
11001101
1101 try bw.writeLeb128(f.global_imports.entries.len + wasm.globals.entries.len);1102 try w.writeLeb128(f.global_imports.entries.len + wasm.globals.entries.len);
1102 for (f.global_imports.keys(), 0..) |name_index, global_index| {1103 for (f.global_imports.keys(), 0..) |name_index, global_index| {
1103 const name = name_index.slice(wasm);1104 const name = name_index.slice(wasm);
1104 try bw.writeLeb128(global_index);1105 try w.writeLeb128(global_index);
1105 try bw.writeLeb128(name.len);1106 try w.writeLeb128(name.len);
1106 try bw.writeAll(name);1107 try w.writeAll(name);
1107 }1108 }
1108 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {1109 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {
1109 const name = resolution.name(wasm).?;1110 const name = resolution.name(wasm).?;
1110 try bw.writeLeb128(global_index);1111 try w.writeLeb128(global_index);
1111 try bw.writeLeb128(name.len);1112 try w.writeLeb128(name.len);
1112 try bw.writeAll(name);1113 try w.writeAll(name);
1113 }1114 }
1114 }1115 }
11151116
1116 {1117 {
1117 const sub_header_offset = try reserveSectionHeader(bw);1118 const sub_header_offset = try reserveSectionHeader(w);
1118 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.data_segment));1119 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.data_segment));
11191120
1120 try bw.writeLeb128(data_segment_groups.len);1121 try w.writeLeb128(data_segment_groups.len);
1121 for (data_segment_groups, 0..) |group, group_index| {1122 for (data_segment_groups, 0..) |group, group_index| {
1122 const name, _ = splitSegmentName(group.first_segment.name(wasm));1123 const name, _ = splitSegmentName(group.first_segment.name(wasm));
1123 try bw.writeLeb128(group_index);1124 try w.writeLeb128(group_index);
1124 try bw.writeLeb128(name.len);1125 try w.writeLeb128(name.len);
1125 try bw.writeAll(name);1126 try w.writeAll(name);
1126 }1127 }
1127 }1128 }
1128}1129}
...@@ -1131,87 +1132,87 @@ fn emitFeaturesSection(aw: *std.io.AllocatingWriter, target: *const std.Target)...@@ -1131,87 +1132,87 @@ fn emitFeaturesSection(aw: *std.io.AllocatingWriter, target: *const std.Target)
1131 const feature_count = target.cpu.features.count();1132 const feature_count = target.cpu.features.count();
1132 if (feature_count == 0) return;1133 if (feature_count == 0) return;
11331134
1134 const bw = &aw.buffered_writer;1135 const w = &aw.interface;
1135 const header_offset = try reserveSectionHeader(bw);1136 const header_offset = try reserveSectionHeader(w);
1136 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));1137 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
11371138
1138 const section_name = "target_features";1139 const section_name = "target_features";
1139 try bw.writeLeb128(section_name.len);1140 try w.writeLeb128(section_name.len);
1140 try bw.writeAll(section_name);1141 try w.writeAll(section_name);
11411142
1142 try bw.writeLeb128(feature_count);1143 try w.writeLeb128(feature_count);
1143 var safety_count = feature_count;1144 var safety_count = feature_count;
1144 for (target.cpu.arch.allFeaturesList(), 0..) |*feature, i| {1145 for (target.cpu.arch.allFeaturesList(), 0..) |*feature, i| {
1145 if (!target.cpu.has(.wasm, @as(std.Target.wasm.Feature, @enumFromInt(i)))) continue;1146 if (!target.cpu.has(.wasm, @as(std.Target.wasm.Feature, @enumFromInt(i)))) continue;
1146 safety_count -= 1;1147 safety_count -= 1;
11471148
1148 try bw.writeUleb128('+');1149 try w.writeUleb128('+');
1149 // Depends on llvm_name for the hyphenated version that matches wasm tooling conventions.1150 // Depends on llvm_name for the hyphenated version that matches wasm tooling conventions.
1150 const name = feature.llvm_name.?;1151 const name = feature.llvm_name.?;
1151 try bw.writeLeb128(name.len);1152 try w.writeLeb128(name.len);
1152 try bw.writeAll(name);1153 try w.writeAll(name);
1153 }1154 }
1154 assert(safety_count == 0);1155 assert(safety_count == 0);
1155}1156}
11561157
1157fn emitBuildIdSection(aw: *std.io.AllocatingWriter, build_id: []const u8) !void {1158fn emitBuildIdSection(aw: *std.io.AllocatingWriter, build_id: []const u8) !void {
1158 const bw = &aw.buffered_writer;1159 const w = &aw.interface;
1159 const header_offset = try reserveSectionHeader(bw);1160 const header_offset = try reserveSectionHeader(w);
1160 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));1161 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
11611162
1162 const section_name = "build_id";1163 const section_name = "build_id";
1163 try bw.writeLeb128(section_name.len);1164 try w.writeLeb128(section_name.len);
1164 try bw.writeAll(section_name);1165 try w.writeAll(section_name);
11651166
1166 try bw.writeUleb128(1);1167 try w.writeUleb128(1);
1167 try bw.writeLeb128(build_id.len);1168 try w.writeLeb128(build_id.len);
1168 try bw.writeAll(build_id);1169 try w.writeAll(build_id);
1169}1170}
11701171
1171fn emitProducerSection(aw: *std.io.AllocatingWriter) !void {1172fn emitProducerSection(aw: *std.io.AllocatingWriter) !void {
1172 const bw = &aw.buffered_writer;1173 const w = &aw.interface;
1173 const header_offset = try reserveSectionHeader(bw);1174 const header_offset = try reserveSectionHeader(w);
1174 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));1175 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
11751176
1176 const section_name = "producers";1177 const section_name = "producers";
1177 try bw.writeLeb128(section_name.len);1178 try w.writeLeb128(section_name.len);
1178 try bw.writeAll(section_name);1179 try w.writeAll(section_name);
11791180
1180 try bw.writeUleb128(2); // 2 fields: language + processed-by1181 try w.writeUleb128(2); // 2 fields: language + processed-by
1181 {1182 {
1182 const field_name = "language";1183 const field_name = "language";
1183 try bw.writeLeb128(field_name.len);1184 try w.writeLeb128(field_name.len);
1184 try bw.writeAll(field_name);1185 try w.writeAll(field_name);
11851186
1186 // field_value_count (TODO: Parse object files for producer sections to detect their language)1187 // field_value_count (TODO: Parse object files for producer sections to detect their language)
1187 try bw.writeUleb128(1);1188 try w.writeUleb128(1);
11881189
1189 // versioned name1190 // versioned name
1190 {1191 {
1191 const field_value = "Zig";1192 const field_value = "Zig";
1192 try bw.writeLeb128(field_value.len);1193 try w.writeLeb128(field_value.len);
1193 try bw.writeAll(field_value);1194 try w.writeAll(field_value);
11941195
1195 try bw.writeLeb128(build_options.version.len);1196 try w.writeLeb128(build_options.version.len);
1196 try bw.writeAll(build_options.version);1197 try w.writeAll(build_options.version);
1197 }1198 }
1198 }1199 }
1199 {1200 {
1200 const field_name = "processed-by";1201 const field_name = "processed-by";
1201 try bw.writeLeb128(field_name.len);1202 try w.writeLeb128(field_name.len);
1202 try bw.writeAll(field_name);1203 try w.writeAll(field_name);
12031204
1204 // field_value_count (TODO: Parse object files for producer sections to detect other used tools)1205 // field_value_count (TODO: Parse object files for producer sections to detect other used tools)
1205 try bw.writeUleb128(1);1206 try w.writeUleb128(1);
12061207
1207 // versioned name1208 // versioned name
1208 {1209 {
1209 const field_value = "Zig";1210 const field_value = "Zig";
1210 try bw.writeLeb128(field_value.len);1211 try w.writeLeb128(field_value.len);
1211 try bw.writeAll(field_value);1212 try w.writeAll(field_value);
12121213
1213 try bw.writeLeb128(build_options.version.len);1214 try w.writeLeb128(build_options.version.len);
1214 try bw.writeAll(build_options.version);1215 try w.writeAll(build_options.version);
1215 }1216 }
1216 }1217 }
1217}1218}
...@@ -1251,9 +1252,9 @@ fn wantSegmentMerge(...@@ -1251,9 +1252,9 @@ fn wantSegmentMerge(
1251/// section id + fixed leb contents size + fixed leb vector length1252/// section id + fixed leb contents size + fixed leb vector length
1252const vec_section_header_size = section_header_size + size_header_size;1253const vec_section_header_size = section_header_size + size_header_size;
12531254
1254fn reserveVecSectionHeader(bw: *std.io.BufferedWriter) std.io.Writer.Error!u32 {1255fn reserveVecSectionHeader(w: *Writer) Writer.Error!u32 {
1255 const offset = bw.count;1256 const offset = w.count;
1256 _ = try bw.writableSlice(vec_section_header_size);1257 _ = try w.writableSlice(vec_section_header_size);
1257 return @intCast(offset);1258 return @intCast(offset);
1258}1259}
12591260
...@@ -1265,68 +1266,68 @@ fn replaceVecSectionHeader(...@@ -1265,68 +1266,68 @@ fn replaceVecSectionHeader(
1265) void {1266) void {
1266 const header = aw.getWritten()[offset..][0..vec_section_header_size];1267 const header = aw.getWritten()[offset..][0..vec_section_header_size];
1267 header[0] = @intFromEnum(section);1268 header[0] = @intFromEnum(section);
1268 std.leb.writeUnsignedFixed(5, header[1..6], @intCast(aw.buffered_writer.count - offset - section_header_size));1269 std.leb.writeUnsignedFixed(5, header[1..6], @intCast(aw.interface.count - offset - section_header_size));
1269 std.leb.writeUnsignedFixed(5, header[6..], n_items);1270 std.leb.writeUnsignedFixed(5, header[6..], n_items);
1270}1271}
12711272
1272const section_header_size = 1 + size_header_size;1273const section_header_size = 1 + size_header_size;
12731274
1274fn reserveSectionHeader(bw: *std.io.BufferedWriter) std.io.Writer.Error!u32 {1275fn reserveSectionHeader(w: *Writer) Writer.Error!u32 {
1275 const offset = bw.count;1276 const offset = w.count;
1276 _ = try bw.writableSlice(section_header_size);1277 _ = try w.writableSlice(section_header_size);
1277 return @intCast(offset);1278 return @intCast(offset);
1278}1279}
12791280
1280fn replaceSectionHeader(aw: *std.io.AllocatingWriter, offset: u32, section: u8) void {1281fn replaceSectionHeader(aw: *std.io.AllocatingWriter, offset: u32, section: u8) void {
1281 const header = aw.getWritten()[offset..][0..section_header_size];1282 const header = aw.getWritten()[offset..][0..section_header_size];
1282 header[0] = section;1283 header[0] = section;
1283 std.leb.writeUnsignedFixed(5, header[1..6], @intCast(aw.buffered_writer.count - offset - section_header_size));1284 std.leb.writeUnsignedFixed(5, header[1..6], @intCast(aw.interface.count - offset - section_header_size));
1284}1285}
12851286
1286const size_header_size = 5;1287const size_header_size = 5;
12871288
1288fn reserveSizeHeader(bw: *std.io.BufferedWriter) std.io.Writer.Error!u32 {1289fn reserveSizeHeader(w: *Writer) Writer.Error!u32 {
1289 const offset = bw.count;1290 const offset = w.count;
1290 _ = try bw.writableSlice(size_header_size);1291 _ = try w.writableSlice(size_header_size);
1291 return @intCast(offset);1292 return @intCast(offset);
1292}1293}
12931294
1294fn replaceSizeHeader(aw: *std.io.AllocatingWriter, offset: u32) void {1295fn replaceSizeHeader(aw: *std.io.AllocatingWriter, offset: u32) void {
1295 const header = aw.getWritten()[offset..][0..size_header_size];1296 const header = aw.getWritten()[offset..][0..size_header_size];
1296 std.leb.writeUnsignedFixed(5, header[0..5], @intCast(aw.buffered_writer.count - offset - size_header_size));1297 std.leb.writeUnsignedFixed(5, header[0..5], @intCast(aw.interface.count - offset - size_header_size));
1297}1298}
12981299
1299fn emitLimits(bw: *std.io.BufferedWriter, limits: std.wasm.Limits) std.io.Writer.Error!void {1300fn emitLimits(w: *Writer, limits: std.wasm.Limits) Writer.Error!void {
1300 try bw.writeByte(@bitCast(limits.flags));1301 try w.writeByte(@bitCast(limits.flags));
1301 try bw.writeLeb128(limits.min);1302 try w.writeLeb128(limits.min);
1302 if (limits.flags.has_max) try bw.writeLeb128(limits.max);1303 if (limits.flags.has_max) try w.writeLeb128(limits.max);
1303}1304}
13041305
1305fn emitMemoryImport(1306fn emitMemoryImport(
1306 wasm: *Wasm,1307 wasm: *Wasm,
1307 bw: *std.io.BufferedWriter,1308 w: *Writer,
1308 name_index: String,1309 name_index: String,
1309 memory_import: *const Wasm.MemoryImport,1310 memory_import: *const Wasm.MemoryImport,
1310) std.io.Writer.Error!void {1311) Writer.Error!void {
1311 const module_name = memory_import.module_name.slice(wasm);1312 const module_name = memory_import.module_name.slice(wasm);
1312 try bw.writeLeb128(module_name.len);1313 try w.writeLeb128(module_name.len);
1313 try bw.writeAll(module_name);1314 try w.writeAll(module_name);
13141315
1315 const name = name_index.slice(wasm);1316 const name = name_index.slice(wasm);
1316 try bw.writeLeb128(name.len);1317 try w.writeLeb128(name.len);
1317 try bw.writeAll(name);1318 try w.writeAll(name);
13181319
1319 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));1320 try w.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));
1320 try emitLimits(bw, memory_import.limits());1321 try emitLimits(w, memory_import.limits());
1321}1322}
13221323
1323pub fn emitInit(bw: *std.io.BufferedWriter, init_expr: std.wasm.InitExpression) std.io.Writer.Error!void {1324pub fn emitInit(w: *Writer, init_expr: std.wasm.InitExpression) Writer.Error!void {
1324 switch (init_expr) {1325 switch (init_expr) {
1325 inline else => |val, tag| {1326 inline else => |val, tag| {
1326 try bw.writeByte(@intFromEnum(@field(std.wasm.Opcode, @tagName(tag))));1327 try w.writeByte(@intFromEnum(@field(std.wasm.Opcode, @tagName(tag))));
1327 switch (@typeInfo(@TypeOf(val))) {1328 switch (@typeInfo(@TypeOf(val))) {
1328 .int => try bw.writeLeb128(val),1329 .int => try w.writeLeb128(val),
1329 .float => |float| try bw.writeInt(1330 .float => |float| try w.writeInt(
1330 @Type(.{ .int = .{ .signedness = .unsigned, .bits = float.bits } }),1331 @Type(.{ .int = .{ .signedness = .unsigned, .bits = float.bits } }),
1331 @bitCast(val),1332 @bitCast(val),
1332 .little,1333 .little,
...@@ -1335,44 +1336,44 @@ pub fn emitInit(bw: *std.io.BufferedWriter, init_expr: std.wasm.InitExpression)...@@ -1335,44 +1336,44 @@ pub fn emitInit(bw: *std.io.BufferedWriter, init_expr: std.wasm.InitExpression)
1335 }1336 }
1336 },1337 },
1337 }1338 }
1338 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1339 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1339}1340}
13401341
1341pub fn emitExpr(wasm: *const Wasm, bw: *std.io.BufferedWriter, expr: Wasm.Expr) std.io.Writer.Error!void {1342pub fn emitExpr(wasm: *const Wasm, w: *Writer, expr: Wasm.Expr) Writer.Error!void {
1342 const slice = expr.slice(wasm);1343 const slice = expr.slice(wasm);
1343 try bw.writeAll(slice[0 .. slice.len + 1]); // +1 to include end opcode1344 try w.writeAll(slice[0 .. slice.len + 1]); // +1 to include end opcode
1344}1345}
13451346
1346fn emitSegmentInfo(wasm: *Wasm, aw: *std.io.BufferedWriter) std.io.Writer.Error!void {1347fn emitSegmentInfo(wasm: *Wasm, aw: *Writer) Writer.Error!void {
1347 const bw = &aw.buffered_writer;1348 const w = &aw.interface;
1348 const header_offset = try reserveSectionHeader(bw);1349 const header_offset = try reserveSectionHeader(w);
1349 defer replaceSectionHeader(aw, header_offset, @intFromEnum(Wasm.SubsectionType.segment_info));1350 defer replaceSectionHeader(aw, header_offset, @intFromEnum(Wasm.SubsectionType.segment_info));
13501351
1351 try bw.writeLeb128(wasm.segment_info.count());1352 try w.writeLeb128(wasm.segment_info.count());
1352 for (wasm.segment_info.values()) |segment_info| {1353 for (wasm.segment_info.values()) |segment_info| {
1353 log.debug("Emit segment: {s} align({d}) flags({b})", .{1354 log.debug("Emit segment: {s} align({d}) flags({b})", .{
1354 segment_info.name,1355 segment_info.name,
1355 segment_info.alignment,1356 segment_info.alignment,
1356 segment_info.flags,1357 segment_info.flags,
1357 });1358 });
1358 try bw.writeLeb128(segment_info.name.len);1359 try w.writeLeb128(segment_info.name.len);
1359 try bw.writeAll(segment_info.name);1360 try w.writeAll(segment_info.name);
1360 try bw.writeLeb128(segment_info.alignment.toLog2Units());1361 try w.writeLeb128(segment_info.alignment.toLog2Units());
1361 try bw.writeLeb128(segment_info.flags);1362 try w.writeLeb128(segment_info.flags);
1362 }1363 }
1363}1364}
13641365
1365fn emitTagNameTable(1366fn emitTagNameTable(
1366 bw: *std.io.BufferedWriter,1367 w: *Writer,
1367 tag_name_offs: []const u32,1368 tag_name_offs: []const u32,
1368 tag_name_bytes: []const u8,1369 tag_name_bytes: []const u8,
1369 base: u32,1370 base: u32,
1370 comptime Int: type,1371 comptime Int: type,
1371) std.io.Writer.Error!void {1372) Writer.Error!void {
1372 for (tag_name_offs) |off| {1373 for (tag_name_offs) |off| {
1373 const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);1374 const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);
1374 try bw.writeInt(Int, base + off, .little);1375 try w.writeInt(Int, base + off, .little);
1375 try bw.writeInt(Int, name_len, .little);1376 try w.writeInt(Int, name_len, .little);
1376 }1377 }
1377}1378}
13781379
...@@ -1536,8 +1537,8 @@ fn reloc_leb_type(code: []u8, index: FuncTypeIndex) void {...@@ -1536,8 +1537,8 @@ fn reloc_leb_type(code: []u8, index: FuncTypeIndex) void {
1536 std.leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));1537 std.leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));
1537}1538}
15381539
1539fn emitCallCtorsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1540fn emitCallCtorsFunction(wasm: *const Wasm, w: *Writer) Writer.Error!void {
1540 try bw.writeUleb128(0); // no locals1541 try w.writeUleb128(0); // no locals
1541 for (wasm.object_init_funcs.items) |init_func| {1542 for (wasm.object_init_funcs.items) |init_func| {
1542 const func = init_func.function_index.ptr(wasm);1543 const func = init_func.function_index.ptr(wasm);
1543 if (!func.object_index.ptr(wasm).is_included) continue;1544 if (!func.object_index.ptr(wasm).is_included) continue;
...@@ -1546,16 +1547,16 @@ fn emitCallCtorsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.W...@@ -1546,16 +1547,16 @@ fn emitCallCtorsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.W
15461547
1547 // Call function by its function index1548 // Call function by its function index
1548 const call_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);1549 const call_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);
1549 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));1550 try w.writeByte(@intFromEnum(std.wasm.Opcode.call));
1550 try bw.writeLeb128(@intFromEnum(call_index));1551 try w.writeLeb128(@intFromEnum(call_index));
15511552
1552 // drop all returned values from the stack as __wasm_call_ctors has no return value1553 // drop all returned values from the stack as __wasm_call_ctors has no return value
1553 try bw.splatByteAll(@intFromEnum(std.wasm.Opcode.drop), n_returns);1554 try w.splatByteAll(@intFromEnum(std.wasm.Opcode.drop), n_returns);
1554 }1555 }
1555 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end function body1556 try w.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end function body
1556}1557}
15571558
1558fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual_addrs: *const VirtualAddrs) std.io.Writer.Error!void {1559fn emitInitMemoryFunction(wasm: *const Wasm, w: *Writer, virtual_addrs: *const VirtualAddrs) Writer.Error!void {
1559 const comp = wasm.base.comp;1560 const comp = wasm.base.comp;
1560 const shared_memory = comp.config.shared_memory;1561 const shared_memory = comp.config.shared_memory;
15611562
...@@ -1566,13 +1567,13 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual...@@ -1566,13 +1567,13 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual
1566 // function.1567 // function.
1567 assert(wasm.any_passive_inits);1568 assert(wasm.any_passive_inits);
15681569
1569 try bw.writeUleb128(0); // no locals1570 try w.writeUleb128(0); // no locals
15701571
1571 if (virtual_addrs.init_memory_flag) |flag_address| {1572 if (virtual_addrs.init_memory_flag) |flag_address| {
1572 assert(shared_memory);1573 assert(shared_memory);
1573 // destination blocks1574 // destination blocks
1574 // based on values we jump to corresponding label1575 // based on values we jump to corresponding label
1575 try bw.writeAll(&.{1576 try w.writeAll(&.{
1576 @intFromEnum(std.wasm.Opcode.block), // $drop1577 @intFromEnum(std.wasm.Opcode.block), // $drop
1577 @intFromEnum(std.wasm.BlockType.empty),1578 @intFromEnum(std.wasm.BlockType.empty),
1578 @intFromEnum(std.wasm.Opcode.block), // $wait1579 @intFromEnum(std.wasm.Opcode.block), // $wait
...@@ -1582,24 +1583,24 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual...@@ -1582,24 +1583,24 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual
1582 });1583 });
15831584
1584 // atomically check1585 // atomically check
1585 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1586 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1586 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));1587 try w.writeLeb128(@as(i32, @bitCast(flag_address)));
1587 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1588 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1588 try bw.writeSleb128(0);1589 try w.writeSleb128(0);
1589 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1590 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1590 try bw.writeSleb128(1);1591 try w.writeSleb128(1);
1591 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));1592 try w.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1592 try bw.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_rmw_cmpxchg));1593 try w.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_rmw_cmpxchg));
1593 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1594 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1594 try bw.writeUleb128(0); // offset1595 try w.writeUleb128(0); // offset
15951596
1596 // based on the value from the atomic check, jump to the label.1597 // based on the value from the atomic check, jump to the label.
1597 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br_table));1598 try w.writeByte(@intFromEnum(std.wasm.Opcode.br_table));
1598 try bw.writeUleb128(3 - 1); // length of the table (we have 3 blocks but because of the mandatory default the length is 2).1599 try w.writeUleb128(3 - 1); // length of the table (we have 3 blocks but because of the mandatory default the length is 2).
1599 try bw.writeUleb128(0); // $init1600 try w.writeUleb128(0); // $init
1600 try bw.writeUleb128(1); // $wait1601 try w.writeUleb128(1); // $wait
1601 try bw.writeUleb128(2); // $drop1602 try w.writeUleb128(2); // $drop
1602 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1603 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1603 }1604 }
16041605
1605 const segment_groups = wasm.flush_buffer.data_segment_groups.items;1606 const segment_groups = wasm.flush_buffer.data_segment_groups.items;
...@@ -1615,79 +1616,79 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual...@@ -1615,79 +1616,79 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual
1615 // For passive BSS segments we can simply issue a memory.fill(0). For1616 // For passive BSS segments we can simply issue a memory.fill(0). For
1616 // non-BSS segments we do a memory.init. Both instructions take as1617 // non-BSS segments we do a memory.init. Both instructions take as
1617 // their first argument the destination address.1618 // their first argument the destination address.
1618 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1619 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1619 try bw.writeLeb128(@as(i32, @bitCast(start_addr)));1620 try w.writeLeb128(@as(i32, @bitCast(start_addr)));
16201621
1621 if (shared_memory and segment.isTls(wasm)) {1622 if (shared_memory and segment.isTls(wasm)) {
1622 // When we initialize the TLS segment we also set the `__tls_base`1623 // When we initialize the TLS segment we also set the `__tls_base`
1623 // global. This allows the runtime to use this static copy of the1624 // global. This allows the runtime to use this static copy of the
1624 // TLS data for the first/main thread.1625 // TLS data for the first/main thread.
1625 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1626 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1626 try bw.writeLeb128(@as(i32, @bitCast(start_addr)));1627 try w.writeLeb128(@as(i32, @bitCast(start_addr)));
1627 try bw.writeByte(@intFromEnum(std.wasm.Opcode.global_set));1628 try w.writeByte(@intFromEnum(std.wasm.Opcode.global_set));
1628 try bw.writeLeb128(virtual_addrs.tls_base.?);1629 try w.writeLeb128(virtual_addrs.tls_base.?);
1629 }1630 }
16301631
1631 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1632 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1632 try bw.writeSleb128(0);1633 try w.writeSleb128(0);
1633 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1634 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1634 try bw.writeLeb128(@as(i32, @bitCast(segment_size)));1635 try w.writeLeb128(@as(i32, @bitCast(segment_size)));
1635 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));1636 try w.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
1636 if (segment.isBss(wasm)) {1637 if (segment.isBss(wasm)) {
1637 // fill bss segment with zeroes1638 // fill bss segment with zeroes
1638 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_fill));1639 try w.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_fill));
1639 } else {1640 } else {
1640 // initialize the segment1641 // initialize the segment
1641 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_init));1642 try w.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_init));
1642 try bw.writeLeb128(segment_index);1643 try w.writeLeb128(segment_index);
1643 }1644 }
1644 try bw.writeByte(0); // memory index immediate1645 try w.writeByte(0); // memory index immediate
1645 }1646 }
16461647
1647 if (virtual_addrs.init_memory_flag) |flag_address| {1648 if (virtual_addrs.init_memory_flag) |flag_address| {
1648 assert(shared_memory);1649 assert(shared_memory);
16491650
1650 // we set the init memory flag to value '2'1651 // we set the init memory flag to value '2'
1651 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1652 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1652 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));1653 try w.writeLeb128(@as(i32, @bitCast(flag_address)));
1653 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1654 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1654 try bw.writeSleb128(2);1655 try w.writeSleb128(2);
1655 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));1656 try w.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1656 try bw.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_store));1657 try w.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_store));
1657 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1658 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1658 try bw.writeUleb128(0); // offset1659 try w.writeUleb128(0); // offset
16591660
1660 // notify any waiters for segment initialization completion1661 // notify any waiters for segment initialization completion
1661 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1662 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1662 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));1663 try w.writeLeb128(@as(i32, @bitCast(flag_address)));
1663 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1664 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1664 try bw.writeSleb128(-1); // number of waiters1665 try w.writeSleb128(-1); // number of waiters
16651666
1666 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));1667 try w.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1667 try bw.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_notify));1668 try w.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_notify));
1668 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1669 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1669 try bw.writeUleb128(0); // offset1670 try w.writeUleb128(0); // offset
1670 try bw.writeByte(@intFromEnum(std.wasm.Opcode.drop));1671 try w.writeByte(@intFromEnum(std.wasm.Opcode.drop));
16711672
1672 // branch and drop segments1673 // branch and drop segments
1673 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br));1674 try w.writeByte(@intFromEnum(std.wasm.Opcode.br));
1674 try bw.writeUleb128(1);1675 try w.writeUleb128(1);
16751676
1676 // wait for thread to initialize memory segments1677 // wait for thread to initialize memory segments
1677 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end $wait1678 try w.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end $wait
1678 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1679 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1679 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));1680 try w.writeLeb128(@as(i32, @bitCast(flag_address)));
1680 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1681 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1681 try bw.writeSleb128(1); // expected flag value1682 try w.writeSleb128(1); // expected flag value
1682 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));1683 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));
1683 try bw.writeSleb128(-1); // timeout1684 try w.writeSleb128(-1); // timeout
1684 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));1685 try w.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1685 try bw.writeByte(@intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_wait32));1686 try w.writeByte(@intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_wait32));
1686 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1687 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1687 try bw.writeUleb128(0); // offset1688 try w.writeUleb128(0); // offset
1688 try bw.writeByte(@intFromEnum(std.wasm.Opcode.drop));1689 try w.writeByte(@intFromEnum(std.wasm.Opcode.drop));
16891690
1690 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end $drop1691 try w.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end $drop
1691 }1692 }
16921693
1693 for (segment_groups, 0..) |group, segment_index| {1694 for (segment_groups, 0..) |group, segment_index| {
...@@ -1698,20 +1699,20 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual...@@ -1698,20 +1699,20 @@ fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual
1698 // during the initialization of each thread (__wasm_init_tls).1699 // during the initialization of each thread (__wasm_init_tls).
1699 if (shared_memory and segment.isTls(wasm)) continue;1700 if (shared_memory and segment.isTls(wasm)) continue;
17001701
1701 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));1702 try w.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
1702 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.data_drop));1703 try w.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.data_drop));
1703 try bw.writeLeb128(segment_index);1704 try w.writeLeb128(segment_index);
1704 }1705 }
17051706
1706 // End of the function body1707 // End of the function body
1707 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1708 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1708}1709}
17091710
1710fn emitInitTlsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1711fn emitInitTlsFunction(wasm: *const Wasm, w: *Writer) Writer.Error!void {
1711 const comp = wasm.base.comp;1712 const comp = wasm.base.comp;
1712 assert(comp.config.shared_memory);1713 assert(comp.config.shared_memory);
17131714
1714 try bw.writeUleb128(0); // no locals1715 try w.writeUleb128(0); // no locals
17151716
1716 // If there's a TLS segment, initialize it during runtime using the bulk-memory feature1717 // If there's a TLS segment, initialize it during runtime using the bulk-memory feature
1717 // TLS segment is always the first one due to how we sort the data segments.1718 // TLS segment is always the first one due to how we sort the data segments.
...@@ -1724,31 +1725,31 @@ fn emitInitTlsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.Wri...@@ -1724,31 +1725,31 @@ fn emitInitTlsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.Wri
17241725
1725 const param_local: u32 = 0;1726 const param_local: u32 = 0;
17261727
1727 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));1728 try w.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1728 try bw.writeLeb128(param_local);1729 try w.writeLeb128(param_local);
17291730
1730 const tls_base_global_index: Wasm.GlobalIndex = @enumFromInt(wasm.globals.getIndex(.__tls_base).?);1731 const tls_base_global_index: Wasm.GlobalIndex = @enumFromInt(wasm.globals.getIndex(.__tls_base).?);
1731 try bw.writeByte(@intFromEnum(std.wasm.Opcode.global_set));1732 try w.writeByte(@intFromEnum(std.wasm.Opcode.global_set));
1732 try bw.writeLeb128(@intFromEnum(tls_base_global_index));1733 try w.writeLeb128(@intFromEnum(tls_base_global_index));
17331734
1734 // load stack values for the bulk-memory operation1735 // load stack values for the bulk-memory operation
1735 {1736 {
1736 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));1737 try w.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1737 try bw.writeLeb128(param_local);1738 try w.writeLeb128(param_local);
17381739
1739 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1740 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1740 try bw.writeSleb128(0); // segment offset1741 try w.writeSleb128(0); // segment offset
17411742
1742 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1743 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1743 try bw.writeLeb128(@as(i32, @bitCast(group_size))); // segment offset1744 try w.writeLeb128(@as(i32, @bitCast(group_size))); // segment offset
1744 }1745 }
17451746
1746 // perform the bulk-memory operation to initialize the data segment1747 // perform the bulk-memory operation to initialize the data segment
1747 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));1748 try w.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
1748 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_init));1749 try w.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_init));
1749 // segment immediate1750 // segment immediate
1750 try bw.writeLeb128(data_segment_index);1751 try w.writeLeb128(data_segment_index);
1751 try bw.writeByte(0); // memory index immediate1752 try w.writeByte(0); // memory index immediate
1752 }1753 }
17531754
1754 // If we have to perform any TLS relocations, call the corresponding function1755 // If we have to perform any TLS relocations, call the corresponding function
...@@ -1756,21 +1757,21 @@ fn emitInitTlsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.Wri...@@ -1756,21 +1757,21 @@ fn emitInitTlsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) std.io.Wri
1756 // generated by the linker.1757 // generated by the linker.
1757 if (wasm.functions.getIndex(.__wasm_apply_global_tls_relocs)) |function_index| {1758 if (wasm.functions.getIndex(.__wasm_apply_global_tls_relocs)) |function_index| {
1758 const output_function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex(wasm, @enumFromInt(function_index));1759 const output_function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex(wasm, @enumFromInt(function_index));
1759 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));1760 try w.writeByte(@intFromEnum(std.wasm.Opcode.call));
1760 try bw.writeLeb128(@intFromEnum(output_function_index));1761 try w.writeLeb128(@intFromEnum(output_function_index));
1761 }1762 }
17621763
1763 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1764 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1764}1765}
17651766
1766fn emitStartSection(aw: *std.io.AllocatingWriter, i: Wasm.OutputFunctionIndex) !void {1767fn emitStartSection(aw: *std.io.AllocatingWriter, i: Wasm.OutputFunctionIndex) !void {
1767 const header_offset = try reserveVecSectionHeader(&aw.buffered_writer);1768 const header_offset = try reserveVecSectionHeader(&aw.interface);
1768 defer replaceVecSectionHeader(aw, header_offset, .start, @intFromEnum(i));1769 defer replaceVecSectionHeader(aw, header_offset, .start, @intFromEnum(i));
1769}1770}
17701771
1771fn emitTagNameFunction(1772fn emitTagNameFunction(
1772 wasm: *Wasm,1773 wasm: *Wasm,
1773 bw: *std.io.BufferedWriter,1774 w: *Writer,
1774 table_base_addr: u32,1775 table_base_addr: u32,
1775 table_index: u32,1776 table_index: u32,
1776 enum_type_ip: InternPool.Index,1777 enum_type_ip: InternPool.Index,
...@@ -1782,33 +1783,33 @@ fn emitTagNameFunction(...@@ -1782,33 +1783,33 @@ fn emitTagNameFunction(
1782 const enum_type = ip.loadEnumType(enum_type_ip);1783 const enum_type = ip.loadEnumType(enum_type_ip);
1783 const tag_values = enum_type.values.get(ip);1784 const tag_values = enum_type.values.get(ip);
17841785
1785 try bw.writeUleb128(0); // no locals1786 try w.writeUleb128(0); // no locals
17861787
1787 const slice_abi_size: u32 = 8;1788 const slice_abi_size: u32 = 8;
1788 if (tag_values.len == 0) {1789 if (tag_values.len == 0) {
1789 // Then it's auto-numbered and therefore a direct table lookup.1790 // Then it's auto-numbered and therefore a direct table lookup.
1790 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));1791 try w.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1791 try bw.writeUleb128(0);1792 try w.writeUleb128(0);
17921793
1793 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));1794 try w.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1794 try bw.writeUleb128(1);1795 try w.writeUleb128(1);
17951796
1796 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1797 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1797 if (std.math.isPowerOfTwo(slice_abi_size)) {1798 if (std.math.isPowerOfTwo(slice_abi_size)) {
1798 try bw.writeLeb128(@as(i32, @bitCast(@as(u32, std.math.log2_int(u32, slice_abi_size)))));1799 try w.writeLeb128(@as(i32, @bitCast(@as(u32, std.math.log2_int(u32, slice_abi_size)))));
1799 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_shl));1800 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_shl));
1800 } else {1801 } else {
1801 try bw.writeLeb128(@as(i32, @bitCast(slice_abi_size)));1802 try w.writeLeb128(@as(i32, @bitCast(slice_abi_size)));
1802 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_mul));1803 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_mul));
1803 }1804 }
18041805
1805 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_load));1806 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_load));
1806 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1807 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1807 try bw.writeLeb128(table_base_addr + slice_abi_size * table_index);1808 try w.writeLeb128(table_base_addr + slice_abi_size * table_index);
18081809
1809 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_store));1810 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_store));
1810 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1811 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1811 try bw.writeUleb128(0);1812 try w.writeUleb128(0);
1812 } else {1813 } else {
1813 const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu);1814 const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu);
1814 const outer_block_type: std.wasm.BlockType = switch (int_info.bits) {1815 const outer_block_type: std.wasm.BlockType = switch (int_info.bits) {
...@@ -1817,80 +1818,80 @@ fn emitTagNameFunction(...@@ -1817,80 +1818,80 @@ fn emitTagNameFunction(
1817 else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}),1818 else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}),
1818 };1819 };
18191820
1820 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));1821 try w.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1821 try bw.writeUleb128(0);1822 try w.writeUleb128(0);
18221823
1823 // Outer block that computes table offset.1824 // Outer block that computes table offset.
1824 try bw.writeByte(@intFromEnum(std.wasm.Opcode.block));1825 try w.writeByte(@intFromEnum(std.wasm.Opcode.block));
1825 try bw.writeByte(@intFromEnum(outer_block_type));1826 try w.writeByte(@intFromEnum(outer_block_type));
18261827
1827 for (tag_values, 0..) |tag_value, tag_index| {1828 for (tag_values, 0..) |tag_value, tag_index| {
1828 // block for this if case1829 // block for this if case
1829 try bw.writeByte(@intFromEnum(std.wasm.Opcode.block));1830 try w.writeByte(@intFromEnum(std.wasm.Opcode.block));
1830 try bw.writeByte(@intFromEnum(std.wasm.BlockType.empty));1831 try w.writeByte(@intFromEnum(std.wasm.BlockType.empty));
18311832
1832 // Tag value whose name should be returned.1833 // Tag value whose name should be returned.
1833 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));1834 try w.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1834 try bw.writeUleb128(1);1835 try w.writeUleb128(1);
18351836
1836 const val: Zcu.Value = .fromInterned(tag_value);1837 const val: Zcu.Value = .fromInterned(tag_value);
1837 switch (outer_block_type) {1838 switch (outer_block_type) {
1838 .i32 => {1839 .i32 => {
1839 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1840 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1840 try bw.writeLeb128(@as(i32, switch (int_info.signedness) {1841 try w.writeLeb128(@as(i32, switch (int_info.signedness) {
1841 .signed => @intCast(val.toSignedInt(zcu)),1842 .signed => @intCast(val.toSignedInt(zcu)),
1842 .unsigned => @bitCast(@as(u32, @intCast(val.toUnsignedInt(zcu)))),1843 .unsigned => @bitCast(@as(u32, @intCast(val.toUnsignedInt(zcu)))),
1843 }));1844 }));
1844 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_ne));1845 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_ne));
1845 },1846 },
1846 .i64 => {1847 .i64 => {
1847 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));1848 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));
1848 try bw.writeLeb128(@as(i64, switch (int_info.signedness) {1849 try w.writeLeb128(@as(i64, switch (int_info.signedness) {
1849 .signed => val.toSignedInt(zcu),1850 .signed => val.toSignedInt(zcu),
1850 .unsigned => @bitCast(val.toUnsignedInt(zcu)),1851 .unsigned => @bitCast(val.toUnsignedInt(zcu)),
1851 }));1852 }));
1852 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_ne));1853 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_ne));
1853 },1854 },
1854 else => unreachable,1855 else => unreachable,
1855 }1856 }
18561857
1857 // if they're not equal, break out of current branch1858 // if they're not equal, break out of current branch
1858 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br_if));1859 try w.writeByte(@intFromEnum(std.wasm.Opcode.br_if));
1859 try bw.writeUleb128(0);1860 try w.writeUleb128(0);
18601861
1861 // Put the table offset of the result on the stack.1862 // Put the table offset of the result on the stack.
1862 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1863 try w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1863 try bw.writeLeb128(@as(i32, @bitCast(@as(u32, @intCast(slice_abi_size * tag_index)))));1864 try w.writeLeb128(@as(i32, @bitCast(@as(u32, @intCast(slice_abi_size * tag_index)))));
18641865
1865 // break outside blocks1866 // break outside blocks
1866 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br));1867 try w.writeByte(@intFromEnum(std.wasm.Opcode.br));
1867 try bw.writeUleb128(1);1868 try w.writeUleb128(1);
18681869
1869 // end the block for this case1870 // end the block for this case
1870 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1871 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1871 }1872 }
1872 try bw.writeByte(@intFromEnum(std.wasm.Opcode.@"unreachable"));1873 try w.writeByte(@intFromEnum(std.wasm.Opcode.@"unreachable"));
1873 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1874 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
18741875
1875 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_load));1876 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_load));
1876 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1877 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1877 try bw.writeLeb128(table_base_addr + slice_abi_size * table_index);1878 try w.writeLeb128(table_base_addr + slice_abi_size * table_index);
18781879
1879 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_store));1880 try w.writeByte(@intFromEnum(std.wasm.Opcode.i64_store));
1880 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());1881 try w.writeLeb128(comptime Alignment.@"4".toLog2Units());
1881 try bw.writeUleb128(0);1882 try w.writeUleb128(0);
1882 }1883 }
18831884
1884 // End of the function body1885 // End of the function body
1885 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1886 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1886}1887}
18871888
1888fn appendGlobal(bw: *std.io.BufferedWriter, mutable: bool, val: u32) std.io.Writer.Error!void {1889fn appendGlobal(w: *Writer, mutable: bool, val: u32) Writer.Error!void {
1889 try bw.writeAll(&.{1890 try w.writeAll(&.{
1890 @intFromEnum(std.wasm.Valtype.i32),1891 @intFromEnum(std.wasm.Valtype.i32),
1891 @intFromBool(mutable),1892 @intFromBool(mutable),
1892 @intFromEnum(std.wasm.Opcode.i32_const),1893 @intFromEnum(std.wasm.Opcode.i32_const),
1893 });1894 });
1894 try bw.writeLeb128(val);1895 try w.writeLeb128(val);
1895 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));1896 try w.writeByte(@intFromEnum(std.wasm.Opcode.end));
1896}1897}
src/link/riscv.zig+7-6
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *Writer) Writer.Error!void {
2 const mask: u8 = 0b11_000000;2 const mask: u8 = 0b11_000000;
3 const actual: i8 = @truncate(addend);3 const actual: i8 = @truncate(addend);
4 const old_value = (try bw.writableArray(1))[0];4 const old_value = (try bw.writableArray(1))[0];
...@@ -9,7 +9,7 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *std.io...@@ -9,7 +9,7 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *std.io
9 try bw.writeByte(new_value);9 try bw.writeByte(new_value);
10}10}
1111
12pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {12pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *Writer) Writer.Error!void {
13 switch (op) {13 switch (op) {
14 .set => try overwriteUleb(@intCast(addend), bw),14 .set => try overwriteUleb(@intCast(addend), bw),
15 .sub => {15 .sub => {
...@@ -20,7 +20,7 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io....@@ -20,7 +20,7 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.
20 }20 }
21}21}
2222
23fn overwriteUleb(new_value: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {23fn overwriteUleb(new_value: u64, bw: *Writer) Writer.Error!void {
24 var value: u64 = new_value;24 var value: u64 = new_value;
25 while (true) {25 while (true) {
26 const byte = (try bw.writableArray(1))[0];26 const byte = (try bw.writableArray(1))[0];
...@@ -34,8 +34,8 @@ pub fn writeAddend(...@@ -34,8 +34,8 @@ pub fn writeAddend(
34 comptime Int: type,34 comptime Int: type,
35 comptime op: enum { add, sub },35 comptime op: enum { add, sub },
36 value: anytype,36 value: anytype,
37 bw: *std.io.BufferedWriter,37 bw: *Writer,
38) std.io.Writer.Error!void {38) Writer.Error!void {
39 const n = @divExact(@bitSizeOf(Int), 8);39 const n = @divExact(@bitSizeOf(Int), 8);
40 var V: Int = mem.readInt(Int, (try bw.writableSliceGreedy(n))[0..n], .little);40 var V: Int = mem.readInt(Int, (try bw.writableSliceGreedy(n))[0..n], .little);
41 const addend: Int = @truncate(value);41 const addend: Int = @truncate(value);
...@@ -108,8 +108,9 @@ pub const Eflags = packed struct(u32) {...@@ -108,8 +108,9 @@ pub const Eflags = packed struct(u32) {
108 };108 };
109};109};
110110
111const mem = std.mem;
112const std = @import("std");111const std = @import("std");
112const mem = std.mem;
113const Writer = std.io.Writer;
113114
114const encoding = @import("../arch/riscv64/encoding.zig");115const encoding = @import("../arch/riscv64/encoding.zig");
115const Instruction = encoding.Instruction;116const Instruction = encoding.Instruction;
src/link/table_section.zig+2-1
...@@ -39,7 +39,7 @@ pub fn TableSection(comptime Entry: type) type {...@@ -39,7 +39,7 @@ pub fn TableSection(comptime Entry: type) type {
39 return self.entries.items.len;39 return self.entries.items.len;
40 }40 }
4141
42 pub fn format(self: Self, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) std.io.Writer.Error!void {42 pub fn format(self: Self, bw: *Writer, comptime unused_format_string: []const u8) Writer.Error!void {
43 comptime assert(unused_format_string.len == 0);43 comptime assert(unused_format_string.len == 0);
44 try bw.writeAll("TableSection:\n");44 try bw.writeAll("TableSection:\n");
45 for (self.entries.items, 0..) |entry, i| {45 for (self.entries.items, 0..) |entry, i| {
...@@ -57,3 +57,4 @@ const assert = std.debug.assert;...@@ -57,3 +57,4 @@ const assert = std.debug.assert;
57const log = std.log.scoped(.link);57const log = std.log.scoped(.link);
5858
59const Allocator = std.mem.Allocator;59const Allocator = std.mem.Allocator;
60const Writer = std.io.Writer;
src/print_env.zig+5-4
...@@ -22,8 +22,9 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void {...@@ -22,8 +22,9 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void {
22 const triple = try host.zigTriple(arena);22 const triple = try host.zigTriple(arena);
2323
24 var buffer: [1024]u8 = undefined;24 var buffer: [1024]u8 = undefined;
25 var bw: std.io.BufferedWriter = std.fs.File.stdout().writer().buffered(&buffer);25 var stdout_writer = std.fs.File.stdout().writer(&buffer);
26 var jws: std.json.Stringify = .{ .writer = &bw, .options = .{ .whitespace = .indent_1 } };26 const w = &stdout_writer.interface();
27 var jws: std.json.Stringify = .{ .writer = w, .options = .{ .whitespace = .indent_1 } };
2728
28 try jws.beginObject();29 try jws.beginObject();
2930
...@@ -54,7 +55,7 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void {...@@ -54,7 +55,7 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void {
54 try jws.endObject();55 try jws.endObject();
5556
56 try jws.endObject();57 try jws.endObject();
57 try bw.writeByte('\n');58 try w.writeByte('\n');
5859
59 try bw.flush();60 try w.flush();
60}61}
src/print_targets.zig+2-1
...@@ -10,6 +10,7 @@ const target = @import("target.zig");...@@ -10,6 +10,7 @@ const target = @import("target.zig");
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const glibc = @import("libs/glibc.zig");11const glibc = @import("libs/glibc.zig");
12const introspect = @import("introspect.zig");12const introspect = @import("introspect.zig");
13const Writer = std.io.Writer;
1314
14pub fn cmdTargets(arena: Allocator, args: []const []const u8) !void {15pub fn cmdTargets(arena: Allocator, args: []const []const u8) !void {
15 _ = args;16 _ = args;
...@@ -20,7 +21,7 @@ pub fn cmdTargets(arena: Allocator, args: []const []const u8) !void {...@@ -20,7 +21,7 @@ pub fn cmdTargets(arena: Allocator, args: []const []const u8) !void {
20 try bw.flush();21 try bw.flush();
21}22}
2223
23fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target) std.io.Writer.Error!void {24fn print(arena: Allocator, output: *Writer, host: *const Target) Writer.Error!void {
24 var zig_lib_directory = introspect.findZigLibDir(arena) catch |err| {25 var zig_lib_directory = introspect.findZigLibDir(arena) catch |err| {
25 fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});26 fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});
26 };27 };
src/print_value.zig+7-6
...@@ -9,6 +9,7 @@ const Sema = @import("Sema.zig");...@@ -9,6 +9,7 @@ const Sema = @import("Sema.zig");
9const InternPool = @import("InternPool.zig");9const InternPool = @import("InternPool.zig");
10const Allocator = std.mem.Allocator;10const Allocator = std.mem.Allocator;
11const Target = std.Target;11const Target = std.Target;
12const Writer = std.io.Writer;
1213
13const max_aggregate_items = 100;14const max_aggregate_items = 100;
14const max_string_len = 256;15const max_string_len = 256;
...@@ -20,7 +21,7 @@ pub const FormatContext = struct {...@@ -20,7 +21,7 @@ pub const FormatContext = struct {
20 depth: u8,21 depth: u8,
21};22};
2223
23pub fn formatSema(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {24pub fn formatSema(ctx: FormatContext, bw: *Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
24 const sema = ctx.opt_sema.?;25 const sema = ctx.opt_sema.?;
25 comptime std.debug.assert(fmt.len == 0);26 comptime std.debug.assert(fmt.len == 0);
26 return print(ctx.val, bw, ctx.depth, ctx.pt, sema) catch |err| switch (err) {27 return print(ctx.val, bw, ctx.depth, ctx.pt, sema) catch |err| switch (err) {
...@@ -31,7 +32,7 @@ pub fn formatSema(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt:...@@ -31,7 +32,7 @@ pub fn formatSema(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt:
31 };32 };
32}33}
3334
34pub fn format(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt: []const u8) std.io.Writer.Error!void {35pub fn format(ctx: FormatContext, bw: *Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
35 std.debug.assert(ctx.opt_sema == null);36 std.debug.assert(ctx.opt_sema == null);
36 comptime std.debug.assert(fmt.len == 0);37 comptime std.debug.assert(fmt.len == 0);
37 return print(ctx.val, bw, ctx.depth, ctx.pt, null) catch |err| switch (err) {38 return print(ctx.val, bw, ctx.depth, ctx.pt, null) catch |err| switch (err) {
...@@ -43,7 +44,7 @@ pub fn format(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt: []co...@@ -43,7 +44,7 @@ pub fn format(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt: []co
4344
44pub fn print(45pub fn print(
45 val: Value,46 val: Value,
46 bw: *std.io.BufferedWriter,47 bw: *Writer,
47 level: u8,48 level: u8,
48 pt: Zcu.PerThread,49 pt: Zcu.PerThread,
49 opt_sema: ?*Sema,50 opt_sema: ?*Sema,
...@@ -186,7 +187,7 @@ fn printAggregate(...@@ -186,7 +187,7 @@ fn printAggregate(
186 val: Value,187 val: Value,
187 aggregate: InternPool.Key.Aggregate,188 aggregate: InternPool.Key.Aggregate,
188 is_ref: bool,189 is_ref: bool,
189 bw: *std.io.BufferedWriter,190 bw: *Writer,
190 level: u8,191 level: u8,
191 pt: Zcu.PerThread,192 pt: Zcu.PerThread,
192 opt_sema: ?*Sema,193 opt_sema: ?*Sema,
...@@ -272,7 +273,7 @@ fn printPtr(...@@ -272,7 +273,7 @@ fn printPtr(
272 ptr_val: Value,273 ptr_val: Value,
273 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.274 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
274 want_kind: ?PrintPtrKind,275 want_kind: ?PrintPtrKind,
275 bw: *std.io.BufferedWriter,276 bw: *Writer,
276 level: u8,277 level: u8,
277 pt: Zcu.PerThread,278 pt: Zcu.PerThread,
278 opt_sema: ?*Sema,279 opt_sema: ?*Sema,
...@@ -318,7 +319,7 @@ const PrintPtrKind = enum { lvalue, rvalue };...@@ -318,7 +319,7 @@ const PrintPtrKind = enum { lvalue, rvalue };
318/// Returns the root derivation, which may be ignored.319/// Returns the root derivation, which may be ignored.
319pub fn printPtrDerivation(320pub fn printPtrDerivation(
320 derivation: Value.PointerDeriveStep,321 derivation: Value.PointerDeriveStep,
321 bw: *std.io.BufferedWriter,322 bw: *Writer,
322 pt: Zcu.PerThread,323 pt: Zcu.PerThread,
323 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.324 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
324 /// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as325 /// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as
src/print_zir.zig+107-107
...@@ -10,7 +10,7 @@ const Zcu = @import("Zcu.zig");...@@ -10,7 +10,7 @@ const Zcu = @import("Zcu.zig");
10const LazySrcLoc = Zcu.LazySrcLoc;10const LazySrcLoc = Zcu.LazySrcLoc;
1111
12/// Write human-readable, debug formatted ZIR code.12/// Write human-readable, debug formatted ZIR code.
13pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.BufferedWriter) !void {13pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.Writer) !void {
14 var arena = std.heap.ArenaAllocator.init(gpa);14 var arena = std.heap.ArenaAllocator.init(gpa);
15 defer arena.deinit();15 defer arena.deinit();
1616
...@@ -57,7 +57,7 @@ pub fn renderInstructionContext(...@@ -57,7 +57,7 @@ pub fn renderInstructionContext(
57 scope_file: *Zcu.File,57 scope_file: *Zcu.File,
58 parent_decl_node: Ast.Node.Index,58 parent_decl_node: Ast.Node.Index,
59 indent: u32,59 indent: u32,
60 bw: *std.io.BufferedWriter,60 bw: *std.io.Writer,
61) !void {61) !void {
62 var arena = std.heap.ArenaAllocator.init(gpa);62 var arena = std.heap.ArenaAllocator.init(gpa);
63 defer arena.deinit();63 defer arena.deinit();
...@@ -89,7 +89,7 @@ pub fn renderSingleInstruction(...@@ -89,7 +89,7 @@ pub fn renderSingleInstruction(
89 scope_file: *Zcu.File,89 scope_file: *Zcu.File,
90 parent_decl_node: Ast.Node.Index,90 parent_decl_node: Ast.Node.Index,
91 indent: u32,91 indent: u32,
92 bw: *std.io.BufferedWriter,92 bw: *std.io.Writer,
93) !void {93) !void {
94 var arena = std.heap.ArenaAllocator.init(gpa);94 var arena = std.heap.ArenaAllocator.init(gpa);
95 defer arena.deinit();95 defer arena.deinit();
...@@ -176,11 +176,11 @@ const Writer = struct {...@@ -176,11 +176,11 @@ const Writer = struct {
176 }176 }
177 } = .{},177 } = .{},
178178
179 const Error = std.io.Writer.Error || std.mem.Allocator.Error;179 const Error = std.io.Writer.Error || Allocator.Error;
180180
181 fn writeInstToStream(181 fn writeInstToStream(
182 self: *Writer,182 self: *Writer,
183 stream: *std.io.BufferedWriter,183 stream: *std.io.Writer,
184 inst: Zir.Inst.Index,184 inst: Zir.Inst.Index,
185 ) Error!void {185 ) Error!void {
186 const tags = self.code.instructions.items(.tag);186 const tags = self.code.instructions.items(.tag);
...@@ -510,7 +510,7 @@ const Writer = struct {...@@ -510,7 +510,7 @@ const Writer = struct {
510 }510 }
511 }511 }
512512
513 fn writeExtended(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {513 fn writeExtended(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
514 const extended = self.code.instructions.items(.data)[@intFromEnum(inst)].extended;514 const extended = self.code.instructions.items(.data)[@intFromEnum(inst)].extended;
515 try stream.print("{s}(", .{@tagName(extended.opcode)});515 try stream.print("{s}(", .{@tagName(extended.opcode)});
516 switch (extended.opcode) {516 switch (extended.opcode) {
...@@ -619,13 +619,13 @@ const Writer = struct {...@@ -619,13 +619,13 @@ const Writer = struct {
619 }619 }
620 }620 }
621621
622 fn writeExtNode(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {622 fn writeExtNode(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
623 try stream.writeAll(")) ");623 try stream.writeAll(")) ");
624 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));624 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
625 try self.writeSrcNode(stream, src_node);625 try self.writeSrcNode(stream, src_node);
626 }626 }
627627
628 fn writeArrayInitElemType(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {628 fn writeArrayInitElemType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
629 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;629 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;
630 try self.writeInstRef(stream, inst_data.lhs);630 try self.writeInstRef(stream, inst_data.lhs);
631 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});631 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});
...@@ -633,7 +633,7 @@ const Writer = struct {...@@ -633,7 +633,7 @@ const Writer = struct {
633633
634 fn writeUnNode(634 fn writeUnNode(
635 self: *Writer,635 self: *Writer,
636 stream: *std.io.BufferedWriter,636 stream: *std.io.Writer,
637 inst: Zir.Inst.Index,637 inst: Zir.Inst.Index,
638 ) Error!void {638 ) Error!void {
639 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node;639 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
...@@ -644,7 +644,7 @@ const Writer = struct {...@@ -644,7 +644,7 @@ const Writer = struct {
644644
645 fn writeUnTok(645 fn writeUnTok(
646 self: *Writer,646 self: *Writer,
647 stream: *std.io.BufferedWriter,647 stream: *std.io.Writer,
648 inst: Zir.Inst.Index,648 inst: Zir.Inst.Index,
649 ) Error!void {649 ) Error!void {
650 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok;650 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok;
...@@ -655,7 +655,7 @@ const Writer = struct {...@@ -655,7 +655,7 @@ const Writer = struct {
655655
656 fn writeValidateDestructure(656 fn writeValidateDestructure(
657 self: *Writer,657 self: *Writer,
658 stream: *std.io.BufferedWriter,658 stream: *std.io.Writer,
659 inst: Zir.Inst.Index,659 inst: Zir.Inst.Index,
660 ) Error!void {660 ) Error!void {
661 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;661 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
...@@ -669,7 +669,7 @@ const Writer = struct {...@@ -669,7 +669,7 @@ const Writer = struct {
669669
670 fn writeValidateArrayInitTy(670 fn writeValidateArrayInitTy(
671 self: *Writer,671 self: *Writer,
672 stream: *std.io.BufferedWriter,672 stream: *std.io.Writer,
673 inst: Zir.Inst.Index,673 inst: Zir.Inst.Index,
674 ) Error!void {674 ) Error!void {
675 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;675 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
...@@ -681,7 +681,7 @@ const Writer = struct {...@@ -681,7 +681,7 @@ const Writer = struct {
681681
682 fn writeArrayTypeSentinel(682 fn writeArrayTypeSentinel(
683 self: *Writer,683 self: *Writer,
684 stream: *std.io.BufferedWriter,684 stream: *std.io.Writer,
685 inst: Zir.Inst.Index,685 inst: Zir.Inst.Index,
686 ) Error!void {686 ) Error!void {
687 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;687 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
...@@ -697,7 +697,7 @@ const Writer = struct {...@@ -697,7 +697,7 @@ const Writer = struct {
697697
698 fn writePtrType(698 fn writePtrType(
699 self: *Writer,699 self: *Writer,
700 stream: *std.io.BufferedWriter,700 stream: *std.io.Writer,
701 inst: Zir.Inst.Index,701 inst: Zir.Inst.Index,
702 ) Error!void {702 ) Error!void {
703 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;703 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;
...@@ -740,12 +740,12 @@ const Writer = struct {...@@ -740,12 +740,12 @@ const Writer = struct {
740 try self.writeSrcNode(stream, extra.data.src_node);740 try self.writeSrcNode(stream, extra.data.src_node);
741 }741 }
742742
743 fn writeInt(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {743 fn writeInt(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
744 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int;744 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int;
745 try stream.print("{d})", .{inst_data});745 try stream.print("{d})", .{inst_data});
746 }746 }
747747
748 fn writeIntBig(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {748 fn writeIntBig(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
749 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;749 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
750 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);750 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);
751 const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count];751 const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count];
...@@ -764,12 +764,12 @@ const Writer = struct {...@@ -764,12 +764,12 @@ const Writer = struct {
764 try stream.print("{s})", .{as_string});764 try stream.print("{s})", .{as_string});
765 }765 }
766766
767 fn writeFloat(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {767 fn writeFloat(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
768 const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float;768 const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float;
769 try stream.print("{d})", .{number});769 try stream.print("{d})", .{number});
770 }770 }
771771
772 fn writeFloat128(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {772 fn writeFloat128(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
773 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;773 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
774 const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;774 const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
775 const number = extra.get();775 const number = extra.get();
...@@ -780,7 +780,7 @@ const Writer = struct {...@@ -780,7 +780,7 @@ const Writer = struct {
780780
781 fn writeStr(781 fn writeStr(
782 self: *Writer,782 self: *Writer,
783 stream: *std.io.BufferedWriter,783 stream: *std.io.Writer,
784 inst: Zir.Inst.Index,784 inst: Zir.Inst.Index,
785 ) Error!void {785 ) Error!void {
786 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;786 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
...@@ -788,7 +788,7 @@ const Writer = struct {...@@ -788,7 +788,7 @@ const Writer = struct {
788 try stream.print("\"{f}\")", .{std.zig.fmtEscapes(str)});788 try stream.print("\"{f}\")", .{std.zig.fmtEscapes(str)});
789 }789 }
790790
791 fn writeSliceStart(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {791 fn writeSliceStart(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
792 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;792 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
793 const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;793 const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;
794 try self.writeInstRef(stream, extra.lhs);794 try self.writeInstRef(stream, extra.lhs);
...@@ -798,7 +798,7 @@ const Writer = struct {...@@ -798,7 +798,7 @@ const Writer = struct {
798 try self.writeSrcNode(stream, inst_data.src_node);798 try self.writeSrcNode(stream, inst_data.src_node);
799 }799 }
800800
801 fn writeSliceEnd(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {801 fn writeSliceEnd(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
802 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;802 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
803 const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;803 const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;
804 try self.writeInstRef(stream, extra.lhs);804 try self.writeInstRef(stream, extra.lhs);
...@@ -810,7 +810,7 @@ const Writer = struct {...@@ -810,7 +810,7 @@ const Writer = struct {
810 try self.writeSrcNode(stream, inst_data.src_node);810 try self.writeSrcNode(stream, inst_data.src_node);
811 }811 }
812812
813 fn writeSliceSentinel(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {813 fn writeSliceSentinel(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
814 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;814 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
815 const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;815 const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;
816 try self.writeInstRef(stream, extra.lhs);816 try self.writeInstRef(stream, extra.lhs);
...@@ -824,7 +824,7 @@ const Writer = struct {...@@ -824,7 +824,7 @@ const Writer = struct {
824 try self.writeSrcNode(stream, inst_data.src_node);824 try self.writeSrcNode(stream, inst_data.src_node);
825 }825 }
826826
827 fn writeSliceLength(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {827 fn writeSliceLength(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
828 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;828 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
829 const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;829 const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;
830 try self.writeInstRef(stream, extra.lhs);830 try self.writeInstRef(stream, extra.lhs);
...@@ -840,7 +840,7 @@ const Writer = struct {...@@ -840,7 +840,7 @@ const Writer = struct {
840 try self.writeSrcNode(stream, inst_data.src_node);840 try self.writeSrcNode(stream, inst_data.src_node);
841 }841 }
842842
843 fn writeUnionInit(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {843 fn writeUnionInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
844 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;844 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
845 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;845 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
846 try self.writeInstRef(stream, extra.union_type);846 try self.writeInstRef(stream, extra.union_type);
...@@ -852,7 +852,7 @@ const Writer = struct {...@@ -852,7 +852,7 @@ const Writer = struct {
852 try self.writeSrcNode(stream, inst_data.src_node);852 try self.writeSrcNode(stream, inst_data.src_node);
853 }853 }
854854
855 fn writeShuffle(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {855 fn writeShuffle(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
856 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;856 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
857 const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;857 const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;
858 try self.writeInstRef(stream, extra.elem_type);858 try self.writeInstRef(stream, extra.elem_type);
...@@ -866,7 +866,7 @@ const Writer = struct {...@@ -866,7 +866,7 @@ const Writer = struct {
866 try self.writeSrcNode(stream, inst_data.src_node);866 try self.writeSrcNode(stream, inst_data.src_node);
867 }867 }
868868
869 fn writeSelect(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {869 fn writeSelect(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
870 const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data;870 const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data;
871 try self.writeInstRef(stream, extra.elem_type);871 try self.writeInstRef(stream, extra.elem_type);
872 try stream.writeAll(", ");872 try stream.writeAll(", ");
...@@ -879,7 +879,7 @@ const Writer = struct {...@@ -879,7 +879,7 @@ const Writer = struct {
879 try self.writeSrcNode(stream, extra.node);879 try self.writeSrcNode(stream, extra.node);
880 }880 }
881881
882 fn writeMulAdd(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {882 fn writeMulAdd(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
883 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;883 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
884 const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data;884 const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data;
885 try self.writeInstRef(stream, extra.mulend1);885 try self.writeInstRef(stream, extra.mulend1);
...@@ -891,7 +891,7 @@ const Writer = struct {...@@ -891,7 +891,7 @@ const Writer = struct {
891 try self.writeSrcNode(stream, inst_data.src_node);891 try self.writeSrcNode(stream, inst_data.src_node);
892 }892 }
893893
894 fn writeBuiltinCall(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {894 fn writeBuiltinCall(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
895 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;895 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
896 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;896 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
897897
...@@ -907,7 +907,7 @@ const Writer = struct {...@@ -907,7 +907,7 @@ const Writer = struct {
907 try self.writeSrcNode(stream, inst_data.src_node);907 try self.writeSrcNode(stream, inst_data.src_node);
908 }908 }
909909
910 fn writeFieldParentPtr(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {910 fn writeFieldParentPtr(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
911 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;911 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
912 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;912 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
913 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));913 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
...@@ -924,7 +924,7 @@ const Writer = struct {...@@ -924,7 +924,7 @@ const Writer = struct {
924 try self.writeSrcNode(stream, extra.src_node);924 try self.writeSrcNode(stream, extra.src_node);
925 }925 }
926926
927 fn writeBuiltinAsyncCall(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {927 fn writeBuiltinAsyncCall(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
928 const extra = self.code.extraData(Zir.Inst.AsyncCall, extended.operand).data;928 const extra = self.code.extraData(Zir.Inst.AsyncCall, extended.operand).data;
929 try self.writeInstRef(stream, extra.frame_buffer);929 try self.writeInstRef(stream, extra.frame_buffer);
930 try stream.writeAll(", ");930 try stream.writeAll(", ");
...@@ -937,7 +937,7 @@ const Writer = struct {...@@ -937,7 +937,7 @@ const Writer = struct {
937 try self.writeSrcNode(stream, extra.node);937 try self.writeSrcNode(stream, extra.node);
938 }938 }
939939
940 fn writeParam(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {940 fn writeParam(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
941 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;941 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
942 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);942 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
943 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);943 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
...@@ -952,7 +952,7 @@ const Writer = struct {...@@ -952,7 +952,7 @@ const Writer = struct {
952 try self.writeSrcTok(stream, inst_data.src_tok);952 try self.writeSrcTok(stream, inst_data.src_tok);
953 }953 }
954954
955 fn writePlNodeBin(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {955 fn writePlNodeBin(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
956 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;956 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
957 const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;957 const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
958 try self.writeInstRef(stream, extra.lhs);958 try self.writeInstRef(stream, extra.lhs);
...@@ -962,7 +962,7 @@ const Writer = struct {...@@ -962,7 +962,7 @@ const Writer = struct {
962 try self.writeSrcNode(stream, inst_data.src_node);962 try self.writeSrcNode(stream, inst_data.src_node);
963 }963 }
964964
965 fn writePlNodeMultiOp(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {965 fn writePlNodeMultiOp(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
966 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;966 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
967 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);967 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
968 const args = self.code.refSlice(extra.end, extra.data.operands_len);968 const args = self.code.refSlice(extra.end, extra.data.operands_len);
...@@ -975,7 +975,7 @@ const Writer = struct {...@@ -975,7 +975,7 @@ const Writer = struct {
975 try self.writeSrcNode(stream, inst_data.src_node);975 try self.writeSrcNode(stream, inst_data.src_node);
976 }976 }
977977
978 fn writeArrayMul(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {978 fn writeArrayMul(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
979 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;979 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
980 const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;980 const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;
981 try self.writeInstRef(stream, extra.res_ty);981 try self.writeInstRef(stream, extra.res_ty);
...@@ -987,13 +987,13 @@ const Writer = struct {...@@ -987,13 +987,13 @@ const Writer = struct {
987 try self.writeSrcNode(stream, inst_data.src_node);987 try self.writeSrcNode(stream, inst_data.src_node);
988 }988 }
989989
990 fn writeElemValImm(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {990 fn writeElemValImm(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
991 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;991 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;
992 try self.writeInstRef(stream, inst_data.operand);992 try self.writeInstRef(stream, inst_data.operand);
993 try stream.print(", {d})", .{inst_data.idx});993 try stream.print(", {d})", .{inst_data.idx});
994 }994 }
995995
996 fn writeArrayInitElemPtr(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {996 fn writeArrayInitElemPtr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
997 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;997 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
998 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;998 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
999999
...@@ -1002,7 +1002,7 @@ const Writer = struct {...@@ -1002,7 +1002,7 @@ const Writer = struct {
1002 try self.writeSrcNode(stream, inst_data.src_node);1002 try self.writeSrcNode(stream, inst_data.src_node);
1003 }1003 }
10041004
1005 fn writePlNodeExport(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1005 fn writePlNodeExport(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1006 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1006 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1007 const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;1007 const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
10081008
...@@ -1013,7 +1013,7 @@ const Writer = struct {...@@ -1013,7 +1013,7 @@ const Writer = struct {
1013 try self.writeSrcNode(stream, inst_data.src_node);1013 try self.writeSrcNode(stream, inst_data.src_node);
1014 }1014 }
10151015
1016 fn writeValidateArrayInitRefTy(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1016 fn writeValidateArrayInitRefTy(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1017 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1017 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1018 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;1018 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;
10191019
...@@ -1023,7 +1023,7 @@ const Writer = struct {...@@ -1023,7 +1023,7 @@ const Writer = struct {
1023 try self.writeSrcNode(stream, inst_data.src_node);1023 try self.writeSrcNode(stream, inst_data.src_node);
1024 }1024 }
10251025
1026 fn writeStructInit(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1026 fn writeStructInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1027 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1027 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1028 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);1028 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
1029 var field_i: u32 = 0;1029 var field_i: u32 = 0;
...@@ -1047,7 +1047,7 @@ const Writer = struct {...@@ -1047,7 +1047,7 @@ const Writer = struct {
1047 try self.writeSrcNode(stream, inst_data.src_node);1047 try self.writeSrcNode(stream, inst_data.src_node);
1048 }1048 }
10491049
1050 fn writeCmpxchg(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1050 fn writeCmpxchg(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1051 const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;1051 const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;
10521052
1053 try self.writeInstRef(stream, extra.ptr);1053 try self.writeInstRef(stream, extra.ptr);
...@@ -1063,7 +1063,7 @@ const Writer = struct {...@@ -1063,7 +1063,7 @@ const Writer = struct {
1063 try self.writeSrcNode(stream, extra.node);1063 try self.writeSrcNode(stream, extra.node);
1064 }1064 }
10651065
1066 fn writePtrCastFull(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1066 fn writePtrCastFull(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1067 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;1067 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1068 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));1068 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1069 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;1069 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
...@@ -1079,7 +1079,7 @@ const Writer = struct {...@@ -1079,7 +1079,7 @@ const Writer = struct {
1079 try self.writeSrcNode(stream, extra.node);1079 try self.writeSrcNode(stream, extra.node);
1080 }1080 }
10811081
1082 fn writePtrCastNoDest(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1082 fn writePtrCastNoDest(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1083 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;1083 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1084 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));1084 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1085 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;1085 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
...@@ -1090,7 +1090,7 @@ const Writer = struct {...@@ -1090,7 +1090,7 @@ const Writer = struct {
1090 try self.writeSrcNode(stream, extra.node);1090 try self.writeSrcNode(stream, extra.node);
1091 }1091 }
10921092
1093 fn writeAtomicLoad(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1093 fn writeAtomicLoad(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1094 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1094 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1095 const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data;1095 const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data;
10961096
...@@ -1103,7 +1103,7 @@ const Writer = struct {...@@ -1103,7 +1103,7 @@ const Writer = struct {
1103 try self.writeSrcNode(stream, inst_data.src_node);1103 try self.writeSrcNode(stream, inst_data.src_node);
1104 }1104 }
11051105
1106 fn writeAtomicStore(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1106 fn writeAtomicStore(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1107 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1107 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1108 const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;1108 const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;
11091109
...@@ -1116,7 +1116,7 @@ const Writer = struct {...@@ -1116,7 +1116,7 @@ const Writer = struct {
1116 try self.writeSrcNode(stream, inst_data.src_node);1116 try self.writeSrcNode(stream, inst_data.src_node);
1117 }1117 }
11181118
1119 fn writeAtomicRmw(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1119 fn writeAtomicRmw(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1120 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1120 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1121 const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;1121 const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
11221122
...@@ -1131,7 +1131,7 @@ const Writer = struct {...@@ -1131,7 +1131,7 @@ const Writer = struct {
1131 try self.writeSrcNode(stream, inst_data.src_node);1131 try self.writeSrcNode(stream, inst_data.src_node);
1132 }1132 }
11331133
1134 fn writeStructInitAnon(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1134 fn writeStructInitAnon(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1135 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1135 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1136 const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);1136 const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
1137 var field_i: u32 = 0;1137 var field_i: u32 = 0;
...@@ -1152,7 +1152,7 @@ const Writer = struct {...@@ -1152,7 +1152,7 @@ const Writer = struct {
1152 try self.writeSrcNode(stream, inst_data.src_node);1152 try self.writeSrcNode(stream, inst_data.src_node);
1153 }1153 }
11541154
1155 fn writeStructInitFieldType(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1155 fn writeStructInitFieldType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1156 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1156 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1157 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;1157 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
1158 try self.writeInstRef(stream, extra.container_type);1158 try self.writeInstRef(stream, extra.container_type);
...@@ -1161,7 +1161,7 @@ const Writer = struct {...@@ -1161,7 +1161,7 @@ const Writer = struct {
1161 try self.writeSrcNode(stream, inst_data.src_node);1161 try self.writeSrcNode(stream, inst_data.src_node);
1162 }1162 }
11631163
1164 fn writeFieldTypeRef(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1164 fn writeFieldTypeRef(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1165 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1165 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1166 const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;1166 const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;
1167 try self.writeInstRef(stream, extra.container_type);1167 try self.writeInstRef(stream, extra.container_type);
...@@ -1171,7 +1171,7 @@ const Writer = struct {...@@ -1171,7 +1171,7 @@ const Writer = struct {
1171 try self.writeSrcNode(stream, inst_data.src_node);1171 try self.writeSrcNode(stream, inst_data.src_node);
1172 }1172 }
11731173
1174 fn writeNodeMultiOp(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1174 fn writeNodeMultiOp(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1175 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);1175 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
1176 const operands = self.code.refSlice(extra.end, extended.small);1176 const operands = self.code.refSlice(extra.end, extended.small);
11771177
...@@ -1185,7 +1185,7 @@ const Writer = struct {...@@ -1185,7 +1185,7 @@ const Writer = struct {
11851185
1186 fn writeInstNode(1186 fn writeInstNode(
1187 self: *Writer,1187 self: *Writer,
1188 stream: *std.io.BufferedWriter,1188 stream: *std.io.Writer,
1189 inst: Zir.Inst.Index,1189 inst: Zir.Inst.Index,
1190 ) Error!void {1190 ) Error!void {
1191 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node;1191 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node;
...@@ -1196,7 +1196,7 @@ const Writer = struct {...@@ -1196,7 +1196,7 @@ const Writer = struct {
11961196
1197 fn writeAsm(1197 fn writeAsm(
1198 self: *Writer,1198 self: *Writer,
1199 stream: *std.io.BufferedWriter,1199 stream: *std.io.Writer,
1200 extended: Zir.Inst.Extended.InstData,1200 extended: Zir.Inst.Extended.InstData,
1201 tmpl_is_expr: bool,1201 tmpl_is_expr: bool,
1202 ) !void {1202 ) !void {
...@@ -1274,7 +1274,7 @@ const Writer = struct {...@@ -1274,7 +1274,7 @@ const Writer = struct {
1274 try self.writeSrcNode(stream, extra.data.src_node);1274 try self.writeSrcNode(stream, extra.data.src_node);
1275 }1275 }
12761276
1277 fn writeOverflowArithmetic(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1277 fn writeOverflowArithmetic(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1278 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;1278 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
12791279
1280 try self.writeInstRef(stream, extra.lhs);1280 try self.writeInstRef(stream, extra.lhs);
...@@ -1286,7 +1286,7 @@ const Writer = struct {...@@ -1286,7 +1286,7 @@ const Writer = struct {
12861286
1287 fn writeCall(1287 fn writeCall(
1288 self: *Writer,1288 self: *Writer,
1289 stream: *std.io.BufferedWriter,1289 stream: *std.io.Writer,
1290 inst: Zir.Inst.Index,1290 inst: Zir.Inst.Index,
1291 comptime kind: enum { direct, field },1291 comptime kind: enum { direct, field },
1292 ) !void {1292 ) !void {
...@@ -1337,7 +1337,7 @@ const Writer = struct {...@@ -1337,7 +1337,7 @@ const Writer = struct {
1337 try self.writeSrcNode(stream, inst_data.src_node);1337 try self.writeSrcNode(stream, inst_data.src_node);
1338 }1338 }
13391339
1340 fn writeBlock(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1340 fn writeBlock(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1341 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1341 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1342 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);1342 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1343 const body = self.code.bodySlice(extra.end, extra.data.body_len);1343 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -1346,7 +1346,7 @@ const Writer = struct {...@@ -1346,7 +1346,7 @@ const Writer = struct {
1346 try self.writeSrcNode(stream, inst_data.src_node);1346 try self.writeSrcNode(stream, inst_data.src_node);
1347 }1347 }
13481348
1349 fn writeBlockComptime(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1349 fn writeBlockComptime(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1350 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1350 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1351 const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);1351 const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);
1352 const body = self.code.bodySlice(extra.end, extra.data.body_len);1352 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -1356,7 +1356,7 @@ const Writer = struct {...@@ -1356,7 +1356,7 @@ const Writer = struct {
1356 try self.writeSrcNode(stream, inst_data.src_node);1356 try self.writeSrcNode(stream, inst_data.src_node);
1357 }1357 }
13581358
1359 fn writeCondBr(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1359 fn writeCondBr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1360 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1360 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1361 const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);1361 const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
1362 const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);1362 const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);
...@@ -1370,7 +1370,7 @@ const Writer = struct {...@@ -1370,7 +1370,7 @@ const Writer = struct {
1370 try self.writeSrcNode(stream, inst_data.src_node);1370 try self.writeSrcNode(stream, inst_data.src_node);
1371 }1371 }
13721372
1373 fn writeTry(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1373 fn writeTry(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1374 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1374 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1375 const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index);1375 const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1376 const body = self.code.bodySlice(extra.end, extra.data.body_len);1376 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -1381,7 +1381,7 @@ const Writer = struct {...@@ -1381,7 +1381,7 @@ const Writer = struct {
1381 try self.writeSrcNode(stream, inst_data.src_node);1381 try self.writeSrcNode(stream, inst_data.src_node);
1382 }1382 }
13831383
1384 fn writeStructDecl(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1384 fn writeStructDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1385 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);1385 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
13861386
1387 const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);1387 const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);
...@@ -1573,7 +1573,7 @@ const Writer = struct {...@@ -1573,7 +1573,7 @@ const Writer = struct {
1573 try self.writeSrcNode(stream, .zero);1573 try self.writeSrcNode(stream, .zero);
1574 }1574 }
15751575
1576 fn writeUnionDecl(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1576 fn writeUnionDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1577 const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));1577 const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));
15781578
1579 const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);1579 const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);
...@@ -1724,7 +1724,7 @@ const Writer = struct {...@@ -1724,7 +1724,7 @@ const Writer = struct {
1724 try self.writeSrcNode(stream, .zero);1724 try self.writeSrcNode(stream, .zero);
1725 }1725 }
17261726
1727 fn writeEnumDecl(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1727 fn writeEnumDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1728 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));1728 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));
17291729
1730 const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);1730 const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);
...@@ -1845,7 +1845,7 @@ const Writer = struct {...@@ -1845,7 +1845,7 @@ const Writer = struct {
18451845
1846 fn writeOpaqueDecl(1846 fn writeOpaqueDecl(
1847 self: *Writer,1847 self: *Writer,
1848 stream: *std.io.BufferedWriter,1848 stream: *std.io.Writer,
1849 extended: Zir.Inst.Extended.InstData,1849 extended: Zir.Inst.Extended.InstData,
1850 ) !void {1850 ) !void {
1851 const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));1851 const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));
...@@ -1887,7 +1887,7 @@ const Writer = struct {...@@ -1887,7 +1887,7 @@ const Writer = struct {
1887 try self.writeSrcNode(stream, .zero);1887 try self.writeSrcNode(stream, .zero);
1888 }1888 }
18891889
1890 fn writeTupleDecl(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {1890 fn writeTupleDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1891 const fields_len = extended.small;1891 const fields_len = extended.small;
1892 assert(fields_len != 0);1892 assert(fields_len != 0);
1893 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);1893 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);
...@@ -1915,7 +1915,7 @@ const Writer = struct {...@@ -1915,7 +1915,7 @@ const Writer = struct {
19151915
1916 fn writeErrorSetDecl(1916 fn writeErrorSetDecl(
1917 self: *Writer,1917 self: *Writer,
1918 stream: *std.io.BufferedWriter,1918 stream: *std.io.Writer,
1919 inst: Zir.Inst.Index,1919 inst: Zir.Inst.Index,
1920 ) !void {1920 ) !void {
1921 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1921 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
...@@ -1940,7 +1940,7 @@ const Writer = struct {...@@ -1940,7 +1940,7 @@ const Writer = struct {
1940 try self.writeSrcNode(stream, inst_data.src_node);1940 try self.writeSrcNode(stream, inst_data.src_node);
1941 }1941 }
19421942
1943 fn writeSwitchBlockErrUnion(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {1943 fn writeSwitchBlockErrUnion(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1944 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1944 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1945 const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);1945 const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);
19461946
...@@ -2077,7 +2077,7 @@ const Writer = struct {...@@ -2077,7 +2077,7 @@ const Writer = struct {
2077 try self.writeSrcNode(stream, inst_data.src_node);2077 try self.writeSrcNode(stream, inst_data.src_node);
2078 }2078 }
20792079
2080 fn writeSwitchBlock(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2080 fn writeSwitchBlock(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2081 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2081 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2082 const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);2082 const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
20832083
...@@ -2207,7 +2207,7 @@ const Writer = struct {...@@ -2207,7 +2207,7 @@ const Writer = struct {
2207 try self.writeSrcNode(stream, inst_data.src_node);2207 try self.writeSrcNode(stream, inst_data.src_node);
2208 }2208 }
22092209
2210 fn writePlNodeField(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2210 fn writePlNodeField(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2211 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2211 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2212 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;2212 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
2213 const name = self.code.nullTerminatedString(extra.field_name_start);2213 const name = self.code.nullTerminatedString(extra.field_name_start);
...@@ -2216,7 +2216,7 @@ const Writer = struct {...@@ -2216,7 +2216,7 @@ const Writer = struct {
2216 try self.writeSrcNode(stream, inst_data.src_node);2216 try self.writeSrcNode(stream, inst_data.src_node);
2217 }2217 }
22182218
2219 fn writePlNodeFieldNamed(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2219 fn writePlNodeFieldNamed(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2220 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2220 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2221 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;2221 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
2222 try self.writeInstRef(stream, extra.lhs);2222 try self.writeInstRef(stream, extra.lhs);
...@@ -2226,7 +2226,7 @@ const Writer = struct {...@@ -2226,7 +2226,7 @@ const Writer = struct {
2226 try self.writeSrcNode(stream, inst_data.src_node);2226 try self.writeSrcNode(stream, inst_data.src_node);
2227 }2227 }
22282228
2229 fn writeAs(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2229 fn writeAs(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2230 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2230 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2231 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;2231 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
2232 try self.writeInstRef(stream, extra.dest_type);2232 try self.writeInstRef(stream, extra.dest_type);
...@@ -2238,7 +2238,7 @@ const Writer = struct {...@@ -2238,7 +2238,7 @@ const Writer = struct {
22382238
2239 fn writeNode(2239 fn writeNode(
2240 self: *Writer,2240 self: *Writer,
2241 stream: *std.io.BufferedWriter,2241 stream: *std.io.Writer,
2242 inst: Zir.Inst.Index,2242 inst: Zir.Inst.Index,
2243 ) Error!void {2243 ) Error!void {
2244 const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node;2244 const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node;
...@@ -2248,7 +2248,7 @@ const Writer = struct {...@@ -2248,7 +2248,7 @@ const Writer = struct {
22482248
2249 fn writeStrTok(2249 fn writeStrTok(
2250 self: *Writer,2250 self: *Writer,
2251 stream: *std.io.BufferedWriter,2251 stream: *std.io.Writer,
2252 inst: Zir.Inst.Index,2252 inst: Zir.Inst.Index,
2253 ) Error!void {2253 ) Error!void {
2254 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;2254 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
...@@ -2257,7 +2257,7 @@ const Writer = struct {...@@ -2257,7 +2257,7 @@ const Writer = struct {
2257 try self.writeSrcTok(stream, inst_data.src_tok);2257 try self.writeSrcTok(stream, inst_data.src_tok);
2258 }2258 }
22592259
2260 fn writeStrOp(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2260 fn writeStrOp(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2261 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;2261 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
2262 const str = inst_data.getStr(self.code);2262 const str = inst_data.getStr(self.code);
2263 try self.writeInstRef(stream, inst_data.operand);2263 try self.writeInstRef(stream, inst_data.operand);
...@@ -2266,7 +2266,7 @@ const Writer = struct {...@@ -2266,7 +2266,7 @@ const Writer = struct {
22662266
2267 fn writeFunc(2267 fn writeFunc(
2268 self: *Writer,2268 self: *Writer,
2269 stream: *std.io.BufferedWriter,2269 stream: *std.io.Writer,
2270 inst: Zir.Inst.Index,2270 inst: Zir.Inst.Index,
2271 inferred_error_set: bool,2271 inferred_error_set: bool,
2272 ) !void {2272 ) !void {
...@@ -2317,7 +2317,7 @@ const Writer = struct {...@@ -2317,7 +2317,7 @@ const Writer = struct {
2317 );2317 );
2318 }2318 }
23192319
2320 fn writeFuncFancy(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2320 fn writeFuncFancy(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2321 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2321 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2322 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);2322 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
23232323
...@@ -2376,7 +2376,7 @@ const Writer = struct {...@@ -2376,7 +2376,7 @@ const Writer = struct {
2376 );2376 );
2377 }2377 }
23782378
2379 fn writeAllocExtended(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {2379 fn writeAllocExtended(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2380 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);2380 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
2381 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));2381 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
23822382
...@@ -2399,7 +2399,7 @@ const Writer = struct {...@@ -2399,7 +2399,7 @@ const Writer = struct {
2399 try self.writeSrcNode(stream, extra.data.src_node);2399 try self.writeSrcNode(stream, extra.data.src_node);
2400 }2400 }
24012401
2402 fn writeTypeofPeer(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {2402 fn writeTypeofPeer(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2403 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);2403 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
2404 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);2404 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);
2405 try self.writeBracedBody(stream, body);2405 try self.writeBracedBody(stream, body);
...@@ -2412,7 +2412,7 @@ const Writer = struct {...@@ -2412,7 +2412,7 @@ const Writer = struct {
2412 try stream.writeAll("])");2412 try stream.writeAll("])");
2413 }2413 }
24142414
2415 fn writeBoolBr(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2415 fn writeBoolBr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2416 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2416 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2417 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);2417 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
2418 const body = self.code.bodySlice(extra.end, extra.data.body_len);2418 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -2423,7 +2423,7 @@ const Writer = struct {...@@ -2423,7 +2423,7 @@ const Writer = struct {
2423 try self.writeSrcNode(stream, inst_data.src_node);2423 try self.writeSrcNode(stream, inst_data.src_node);
2424 }2424 }
24252425
2426 fn writeIntType(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2426 fn writeIntType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2427 const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type;2427 const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type;
2428 const prefix: u8 = switch (int_type.signedness) {2428 const prefix: u8 = switch (int_type.signedness) {
2429 .signed => 'i',2429 .signed => 'i',
...@@ -2433,7 +2433,7 @@ const Writer = struct {...@@ -2433,7 +2433,7 @@ const Writer = struct {
2433 try self.writeSrcNode(stream, int_type.src_node);2433 try self.writeSrcNode(stream, int_type.src_node);
2434 }2434 }
24352435
2436 fn writeSaveErrRetIndex(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2436 fn writeSaveErrRetIndex(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2437 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index;2437 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index;
24382438
2439 try self.writeInstRef(stream, inst_data.operand);2439 try self.writeInstRef(stream, inst_data.operand);
...@@ -2441,7 +2441,7 @@ const Writer = struct {...@@ -2441,7 +2441,7 @@ const Writer = struct {
2441 try stream.writeAll(")");2441 try stream.writeAll(")");
2442 }2442 }
24432443
2444 fn writeRestoreErrRetIndex(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {2444 fn writeRestoreErrRetIndex(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2445 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;2445 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
24462446
2447 try self.writeInstRef(stream, extra.block);2447 try self.writeInstRef(stream, extra.block);
...@@ -2451,7 +2451,7 @@ const Writer = struct {...@@ -2451,7 +2451,7 @@ const Writer = struct {
2451 try self.writeSrcNode(stream, extra.src_node);2451 try self.writeSrcNode(stream, extra.src_node);
2452 }2452 }
24532453
2454 fn writeBreak(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2454 fn writeBreak(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2455 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break";2455 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break";
2456 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;2456 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
24572457
...@@ -2461,7 +2461,7 @@ const Writer = struct {...@@ -2461,7 +2461,7 @@ const Writer = struct {
2461 try stream.writeAll(")");2461 try stream.writeAll(")");
2462 }2462 }
24632463
2464 fn writeArrayInit(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2464 fn writeArrayInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2465 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2465 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24662466
2467 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);2467 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
...@@ -2477,7 +2477,7 @@ const Writer = struct {...@@ -2477,7 +2477,7 @@ const Writer = struct {
2477 try self.writeSrcNode(stream, inst_data.src_node);2477 try self.writeSrcNode(stream, inst_data.src_node);
2478 }2478 }
24792479
2480 fn writeArrayInitAnon(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2480 fn writeArrayInitAnon(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2481 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2481 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24822482
2483 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);2483 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
...@@ -2492,7 +2492,7 @@ const Writer = struct {...@@ -2492,7 +2492,7 @@ const Writer = struct {
2492 try self.writeSrcNode(stream, inst_data.src_node);2492 try self.writeSrcNode(stream, inst_data.src_node);
2493 }2493 }
24942494
2495 fn writeArrayInitSent(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2495 fn writeArrayInitSent(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2496 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2496 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24972497
2498 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);2498 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
...@@ -2512,7 +2512,7 @@ const Writer = struct {...@@ -2512,7 +2512,7 @@ const Writer = struct {
2512 try self.writeSrcNode(stream, inst_data.src_node);2512 try self.writeSrcNode(stream, inst_data.src_node);
2513 }2513 }
25142514
2515 fn writeUnreachable(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2515 fn writeUnreachable(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2516 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";2516 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";
2517 try stream.writeAll(") ");2517 try stream.writeAll(") ");
2518 try self.writeSrcNode(stream, inst_data.src_node);2518 try self.writeSrcNode(stream, inst_data.src_node);
...@@ -2520,7 +2520,7 @@ const Writer = struct {...@@ -2520,7 +2520,7 @@ const Writer = struct {
25202520
2521 fn writeFuncCommon(2521 fn writeFuncCommon(
2522 self: *Writer,2522 self: *Writer,
2523 stream: *std.io.BufferedWriter,2523 stream: *std.io.Writer,
2524 inferred_error_set: bool,2524 inferred_error_set: bool,
2525 var_args: bool,2525 var_args: bool,
2526 is_noinline: bool,2526 is_noinline: bool,
...@@ -2557,19 +2557,19 @@ const Writer = struct {...@@ -2557,19 +2557,19 @@ const Writer = struct {
2557 try self.writeSrcNode(stream, src_node);2557 try self.writeSrcNode(stream, src_node);
2558 }2558 }
25592559
2560 fn writeDbgStmt(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2560 fn writeDbgStmt(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2561 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;2561 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
2562 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });2562 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });
2563 }2563 }
25642564
2565 fn writeDefer(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2565 fn writeDefer(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2566 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";2566 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";
2567 const body = self.code.bodySlice(inst_data.index, inst_data.len);2567 const body = self.code.bodySlice(inst_data.index, inst_data.len);
2568 try self.writeBracedBody(stream, body);2568 try self.writeBracedBody(stream, body);
2569 try stream.writeByte(')');2569 try stream.writeByte(')');
2570 }2570 }
25712571
2572 fn writeDeferErrCode(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2572 fn writeDeferErrCode(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2573 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;2573 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;
2574 const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;2574 const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
25752575
...@@ -2582,7 +2582,7 @@ const Writer = struct {...@@ -2582,7 +2582,7 @@ const Writer = struct {
2582 try stream.writeByte(')');2582 try stream.writeByte(')');
2583 }2583 }
25842584
2585 fn writeDeclaration(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2585 fn writeDeclaration(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2586 const decl = self.code.getDeclaration(inst);2586 const decl = self.code.getDeclaration(inst);
25872587
2588 const prev_parent_decl_node = self.parent_decl_node;2588 const prev_parent_decl_node = self.parent_decl_node;
...@@ -2639,26 +2639,26 @@ const Writer = struct {...@@ -2639,26 +2639,26 @@ const Writer = struct {
2639 try self.writeSrcNode(stream, .zero);2639 try self.writeSrcNode(stream, .zero);
2640 }2640 }
26412641
2642 fn writeClosureGet(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {2642 fn writeClosureGet(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2643 try stream.print("{d})) ", .{extended.small});2643 try stream.print("{d})) ", .{extended.small});
2644 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));2644 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
2645 try self.writeSrcNode(stream, src_node);2645 try self.writeSrcNode(stream, src_node);
2646 }2646 }
26472647
2648 fn writeBuiltinValue(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {2648 fn writeBuiltinValue(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2649 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);2649 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2650 try stream.print("{s})) ", .{@tagName(val)});2650 try stream.print("{s})) ", .{@tagName(val)});
2651 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));2651 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
2652 try self.writeSrcNode(stream, src_node);2652 try self.writeSrcNode(stream, src_node);
2653 }2653 }
26542654
2655 fn writeInplaceArithResultTy(self: *Writer, stream: *std.io.BufferedWriter, extended: Zir.Inst.Extended.InstData) !void {2655 fn writeInplaceArithResultTy(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2656 const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small);2656 const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small);
2657 try self.writeInstRef(stream, @enumFromInt(extended.operand));2657 try self.writeInstRef(stream, @enumFromInt(extended.operand));
2658 try stream.print(", {s}))", .{@tagName(op)});2658 try stream.print(", {s}))", .{@tagName(op)});
2659 }2659 }
26602660
2661 fn writeInstRef(self: *Writer, stream: *std.io.BufferedWriter, ref: Zir.Inst.Ref) !void {2661 fn writeInstRef(self: *Writer, stream: *std.io.Writer, ref: Zir.Inst.Ref) !void {
2662 if (ref == .none) {2662 if (ref == .none) {
2663 return stream.writeAll(".none");2663 return stream.writeAll(".none");
2664 } else if (ref.toIndex()) |i| {2664 } else if (ref.toIndex()) |i| {
...@@ -2669,12 +2669,12 @@ const Writer = struct {...@@ -2669,12 +2669,12 @@ const Writer = struct {
2669 }2669 }
2670 }2670 }
26712671
2672 fn writeInstIndex(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2672 fn writeInstIndex(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2673 _ = self;2673 _ = self;
2674 return stream.print("%{d}", .{@intFromEnum(inst)});2674 return stream.print("%{d}", .{@intFromEnum(inst)});
2675 }2675 }
26762676
2677 fn writeCaptures(self: *Writer, stream: *std.io.BufferedWriter, extra_index: usize, captures_len: u32) !usize {2677 fn writeCaptures(self: *Writer, stream: *std.io.Writer, extra_index: usize, captures_len: u32) !usize {
2678 if (captures_len == 0) {2678 if (captures_len == 0) {
2679 try stream.writeAll("{}");2679 try stream.writeAll("{}");
2680 return extra_index;2680 return extra_index;
...@@ -2694,7 +2694,7 @@ const Writer = struct {...@@ -2694,7 +2694,7 @@ const Writer = struct {
2694 return extra_index + 2 * captures_len;2694 return extra_index + 2 * captures_len;
2695 }2695 }
26962696
2697 fn writeCapture(self: *Writer, stream: *std.io.BufferedWriter, capture: Zir.Inst.Capture) !void {2697 fn writeCapture(self: *Writer, stream: *std.io.Writer, capture: Zir.Inst.Capture) !void {
2698 switch (capture.unwrap()) {2698 switch (capture.unwrap()) {
2699 .nested => |i| return stream.print("[{d}]", .{i}),2699 .nested => |i| return stream.print("[{d}]", .{i}),
2700 .instruction => |inst| return self.writeInstIndex(stream, inst),2700 .instruction => |inst| return self.writeInstIndex(stream, inst),
...@@ -2713,7 +2713,7 @@ const Writer = struct {...@@ -2713,7 +2713,7 @@ const Writer = struct {
27132713
2714 fn writeOptionalInstRef(2714 fn writeOptionalInstRef(
2715 self: *Writer,2715 self: *Writer,
2716 stream: *std.io.BufferedWriter,2716 stream: *std.io.Writer,
2717 prefix: []const u8,2717 prefix: []const u8,
2718 inst: Zir.Inst.Ref,2718 inst: Zir.Inst.Ref,
2719 ) !void {2719 ) !void {
...@@ -2724,7 +2724,7 @@ const Writer = struct {...@@ -2724,7 +2724,7 @@ const Writer = struct {
27242724
2725 fn writeOptionalInstRefOrBody(2725 fn writeOptionalInstRefOrBody(
2726 self: *Writer,2726 self: *Writer,
2727 stream: *std.io.BufferedWriter,2727 stream: *std.io.Writer,
2728 prefix: []const u8,2728 prefix: []const u8,
2729 ref: Zir.Inst.Ref,2729 ref: Zir.Inst.Ref,
2730 body: []const Zir.Inst.Index,2730 body: []const Zir.Inst.Index,
...@@ -2742,7 +2742,7 @@ const Writer = struct {...@@ -2742,7 +2742,7 @@ const Writer = struct {
27422742
2743 fn writeFlag(2743 fn writeFlag(
2744 self: *Writer,2744 self: *Writer,
2745 stream: *std.io.BufferedWriter,2745 stream: *std.io.Writer,
2746 name: []const u8,2746 name: []const u8,
2747 flag: bool,2747 flag: bool,
2748 ) !void {2748 ) !void {
...@@ -2751,7 +2751,7 @@ const Writer = struct {...@@ -2751,7 +2751,7 @@ const Writer = struct {
2751 try stream.writeAll(name);2751 try stream.writeAll(name);
2752 }2752 }
27532753
2754 fn writeSrcNode(self: *Writer, stream: *std.io.BufferedWriter, src_node: Ast.Node.Offset) !void {2754 fn writeSrcNode(self: *Writer, stream: *std.io.Writer, src_node: Ast.Node.Offset) !void {
2755 const tree = self.tree orelse return;2755 const tree = self.tree orelse return;
2756 const abs_node = src_node.toAbsolute(self.parent_decl_node);2756 const abs_node = src_node.toAbsolute(self.parent_decl_node);
2757 const src_span = tree.nodeToSpan(abs_node);2757 const src_span = tree.nodeToSpan(abs_node);
...@@ -2763,7 +2763,7 @@ const Writer = struct {...@@ -2763,7 +2763,7 @@ const Writer = struct {
2763 });2763 });
2764 }2764 }
27652765
2766 fn writeSrcTok(self: *Writer, stream: *std.io.BufferedWriter, src_tok: Ast.TokenOffset) !void {2766 fn writeSrcTok(self: *Writer, stream: *std.io.Writer, src_tok: Ast.TokenOffset) !void {
2767 const tree = self.tree orelse return;2767 const tree = self.tree orelse return;
2768 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));2768 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2769 const span_start = tree.tokenStart(abs_tok);2769 const span_start = tree.tokenStart(abs_tok);
...@@ -2776,7 +2776,7 @@ const Writer = struct {...@@ -2776,7 +2776,7 @@ const Writer = struct {
2776 });2776 });
2777 }2777 }
27782778
2779 fn writeSrcTokAbs(self: *Writer, stream: *std.io.BufferedWriter, src_tok: Ast.TokenIndex) !void {2779 fn writeSrcTokAbs(self: *Writer, stream: *std.io.Writer, src_tok: Ast.TokenIndex) !void {
2780 const tree = self.tree orelse return;2780 const tree = self.tree orelse return;
2781 const span_start = tree.tokenStart(src_tok);2781 const span_start = tree.tokenStart(src_tok);
2782 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));2782 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
...@@ -2788,15 +2788,15 @@ const Writer = struct {...@@ -2788,15 +2788,15 @@ const Writer = struct {
2788 });2788 });
2789 }2789 }
27902790
2791 fn writeBracedDecl(self: *Writer, stream: *std.io.BufferedWriter, body: []const Zir.Inst.Index) !void {2791 fn writeBracedDecl(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
2792 try self.writeBracedBodyConditional(stream, body, self.recurse_decls);2792 try self.writeBracedBodyConditional(stream, body, self.recurse_decls);
2793 }2793 }
27942794
2795 fn writeBracedBody(self: *Writer, stream: *std.io.BufferedWriter, body: []const Zir.Inst.Index) !void {2795 fn writeBracedBody(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
2796 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);2796 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);
2797 }2797 }
27982798
2799 fn writeBracedBodyConditional(self: *Writer, stream: *std.io.BufferedWriter, body: []const Zir.Inst.Index, enabled: bool) !void {2799 fn writeBracedBodyConditional(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index, enabled: bool) !void {
2800 if (body.len == 0) {2800 if (body.len == 0) {
2801 try stream.writeAll("{}");2801 try stream.writeAll("{}");
2802 } else if (enabled) {2802 } else if (enabled) {
...@@ -2825,7 +2825,7 @@ const Writer = struct {...@@ -2825,7 +2825,7 @@ const Writer = struct {
2825 }2825 }
2826 }2826 }
28272827
2828 fn writeBody(self: *Writer, stream: *std.io.BufferedWriter, body: []const Zir.Inst.Index) !void {2828 fn writeBody(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
2829 for (body) |inst| {2829 for (body) |inst| {
2830 try stream.splatByteAll(' ', self.indent);2830 try stream.splatByteAll(' ', self.indent);
2831 try stream.print("%{d} ", .{@intFromEnum(inst)});2831 try stream.print("%{d} ", .{@intFromEnum(inst)});
...@@ -2834,7 +2834,7 @@ const Writer = struct {...@@ -2834,7 +2834,7 @@ const Writer = struct {
2834 }2834 }
2835 }2835 }
28362836
2837 fn writeImport(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {2837 fn writeImport(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2838 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;2838 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
2839 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;2839 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
2840 try self.writeInstRef(stream, extra.res_ty);2840 try self.writeInstRef(stream, extra.res_ty);
src/print_zoir.zig+4-3
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *std.io.BufferedWriter) error{ WriteFailed, OutOfMemory }!void {1pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *Writer) error{ WriteFailed, OutOfMemory }!void {
2 assert(!zoir.hasCompileErrors());2 assert(!zoir.hasCompileErrors());
33
4 const bytes_per_node = comptime n: {4 const bytes_per_node = comptime n: {
...@@ -41,12 +41,12 @@ pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *std.io.BufferedWriter) e...@@ -41,12 +41,12 @@ pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *std.io.BufferedWriter) e
41}41}
4242
43const PrintZon = struct {43const PrintZon = struct {
44 w: *std.io.BufferedWriter,44 w: *Writer,
45 arena: Allocator,45 arena: Allocator,
46 zoir: Zoir,46 zoir: Zoir,
47 indent: u32,47 indent: u32,
4848
49 const Error = std.io.Writer.Error;49 const Error = Writer.Error;
5050
51 fn renderRoot(pz: *PrintZon) Error!void {51 fn renderRoot(pz: *PrintZon) Error!void {
52 try pz.renderNode(.root);52 try pz.renderNode(.root);
...@@ -113,3 +113,4 @@ const std = @import("std");...@@ -113,3 +113,4 @@ const std = @import("std");
113const assert = std.debug.assert;113const assert = std.debug.assert;
114const Allocator = std.mem.Allocator;114const Allocator = std.mem.Allocator;
115const Zoir = std.zig.Zoir;115const Zoir = std.zig.Zoir;
116const Writer = std.io.Writer;