authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-12 19:04:35-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:09-08:00
log1925e0319f1337b4856bd5a181bf4f6d3ac7d428
treeb38839cca2604368b01b4312119083a5cdf3d224
parentec56696503e702e063af8740a77376b2e7694c29

update lockStderrWriter sites

use the application's Io implementation where possible. This correctly makes writing to stderr cancelable, fallible, and participate in the application's event loop. It also removes one more hard-coded dependency on a secondary Io implementation.

32 files changed, 345 insertions(+), 247 deletions(-)

lib/compiler/build_runner.zig+10-8
......@@ -522,7 +522,7 @@ pub fn main() !void {
522522 // Perhaps in the future there could be an Advanced Options flag
523523 // such as --debug-build-runner-leaks which would make this code
524524 // return instead of calling exit.
525 _ = std.debug.lockStderrWriter(&.{});
525 _ = io.lockStderrWriter(&.{}) catch {};
526526 process.exit(1);
527527 },
528528 else => |e| return e,
......@@ -554,8 +554,8 @@ pub fn main() !void {
554554 }
555555
556556 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {
557 const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation);
558 defer std.debug.unlockStderrWriter();
557 const stderr = try io.lockStderrWriter(&stdio_buffer_allocation);
558 defer io.unlockStderrWriter();
559559 try stderr.writeAllUnescaped("\x1B[2J\x1B[3J\x1B[H");
560560 }) {
561561 if (run.web_server) |*ws| ws.startBuild();
......@@ -856,8 +856,8 @@ fn runStepNames(
856856 .none => break :summary,
857857 }
858858
859 const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation);
860 defer std.debug.unlockStderrWriter();
859 const stderr = try io.lockStderrWriter(&stdio_buffer_allocation);
860 defer io.unlockStderrWriter();
861861
862862 const w = &stderr.interface;
863863 const fwm = stderr.mode;
......@@ -954,7 +954,7 @@ fn runStepNames(
954954 if (run.error_style.verboseContext()) break :code 1; // failure; print build command
955955 break :code 2; // failure; do not print build command
956956 };
957 _ = std.debug.lockStderrWriter(&.{});
957 _ = io.lockStderrWriter(&.{}) catch {};
958958 process.exit(code);
959959}
960960
......@@ -1369,8 +1369,10 @@ fn workerMakeOneStep(
13691369 const show_error_msgs = s.result_error_msgs.items.len > 0;
13701370 const show_stderr = s.result_stderr.len > 0;
13711371 if (show_error_msgs or show_compile_errors or show_stderr) {
1372 const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation);
1373 defer std.debug.unlockStderrWriter();
1372 const stderr = io.lockStderrWriter(&stdio_buffer_allocation) catch |err| switch (err) {
1373 error.Canceled => return,
1374 };
1375 defer io.unlockStderrWriter();
13741376 printErrorMessages(gpa, s, .{}, &stderr.interface, stderr.mode, run.error_style, run.multiline_errors) catch {};
13751377 }
13761378
lib/compiler/resinator/cli.zig+4-4
......@@ -125,10 +125,10 @@ pub const Diagnostics = struct {
125125 try self.errors.append(self.allocator, error_details);
126126 }
127127
128 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8) void {
129 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
130 defer std.debug.unlockStderrWriter();
131 self.renderToWriter(args, stderr, ttyconf) catch return;
128 pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) void {
129 const stderr = io.lockStderrWriter(&.{});
130 defer io.unlockStderrWriter();
131 self.renderToWriter(args, &stderr.interface, stderr.mode) catch return;
132132 }
133133
134134 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void {
lib/compiler/resinator/errors.zig+4-4
......@@ -67,12 +67,12 @@ pub const Diagnostics = struct {
6767 return @intCast(index);
6868 }
6969
70 pub fn renderToStdErr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
70 pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
7171 const io = self.io;
72 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
73 defer std.debug.unlockStderrWriter();
72 const stderr = io.lockStderrWriter(&.{});
73 defer io.unlockStderrWriter();
7474 for (self.errors.items) |err_details| {
75 renderErrorMessage(io, stderr, ttyconf, cwd, err_details, source, self.strings.items, source_mappings) catch return;
75 renderErrorMessage(io, &stderr.interface, stderr.mode, cwd, err_details, source, self.strings.items, source_mappings) catch return;
7676 }
7777 }
7878
lib/compiler/resinator/main.zig+51-47
......@@ -24,6 +24,10 @@ pub fn main() !void {
2424 defer std.debug.assert(debug_allocator.deinit() == .ok);
2525 const gpa = debug_allocator.allocator();
2626
27 var threaded: std.Io.Threaded = .init(gpa);
28 defer threaded.deinit();
29 const io = threaded.io();
30
2731 var arena_state = std.heap.ArenaAllocator.init(gpa);
2832 defer arena_state.deinit();
2933 const arena = arena_state.allocator();
......@@ -31,8 +35,8 @@ pub fn main() !void {
3135 const args = try std.process.argsAlloc(arena);
3236
3337 if (args.len < 2) {
34 const w, const ttyconf = std.debug.lockStderrWriter(&.{});
35 try renderErrorMessage(w, ttyconf, .err, "expected zig lib dir as first argument", .{});
38 const stderr = io.lockStderrWriter(&.{});
39 try renderErrorMessage(&stderr.interface, stderr.mode, .err, "expected zig lib dir as first argument", .{});
3640 std.process.exit(1);
3741 }
3842 const zig_lib_dir = args[1];
......@@ -45,7 +49,7 @@ pub fn main() !void {
4549 }
4650
4751 var stdout_buffer: [1024]u8 = undefined;
48 var stdout_writer = Io.File.stdout().writer(&stdout_buffer);
52 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
4953 const stdout = &stdout_writer.interface;
5054 var error_handler: ErrorHandler = switch (zig_integration) {
5155 true => .{
......@@ -71,24 +75,20 @@ pub fn main() !void {
7175
7276 if (!zig_integration) {
7377 // print any warnings/notes
74 cli_diagnostics.renderToStdErr(cli_args);
78 cli_diagnostics.renderToStderr(io, cli_args);
7579 // If there was something printed, then add an extra newline separator
7680 // so that there is a clear separation between the cli diagnostics and whatever
7781 // gets printed after
7882 if (cli_diagnostics.errors.items.len > 0) {
79 const stderr, _ = std.debug.lockStderrWriter(&.{});
80 defer std.debug.unlockStderrWriter();
81 try stderr.writeByte('\n');
83 const stderr = io.lockStderrWriter(&.{});
84 defer io.unlockStderrWriter();
85 try stderr.interface.writeByte('\n');
8286 }
8387 }
8488 break :options options;
8589 };
8690 defer options.deinit();
8791
88 var threaded: std.Io.Threaded = .init(gpa);
89 defer threaded.deinit();
90 const io = threaded.io();
91
9292 if (options.print_help_and_exit) {
9393 try cli.writeUsage(stdout, "zig rc");
9494 try stdout.flush();
......@@ -130,10 +130,10 @@ pub fn main() !void {
130130 var stderr_buf: [512]u8 = undefined;
131131 var diagnostics: aro.Diagnostics = .{ .output = output: {
132132 if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } };
133 const w, const ttyconf = std.debug.lockStderrWriter(&stderr_buf);
133 const stderr = io.lockStderrWriter(&stderr_buf);
134134 break :output .{ .to_writer = .{
135 .writer = w,
136 .color = ttyconf,
135 .writer = &stderr.interface,
136 .color = stderr.mode,
137137 } };
138138 } };
139139 defer {
......@@ -175,11 +175,11 @@ pub fn main() !void {
175175 std.process.exit(1);
176176 },
177177 error.FileTooBig => {
178 try error_handler.emitMessage(gpa, .err, "failed during preprocessing: maximum file size exceeded", .{});
178 try error_handler.emitMessage(gpa, io, .err, "failed during preprocessing: maximum file size exceeded", .{});
179179 std.process.exit(1);
180180 },
181181 error.WriteFailed => {
182 try error_handler.emitMessage(gpa, .err, "failed during preprocessing: error writing the preprocessed output", .{});
182 try error_handler.emitMessage(gpa, io, .err, "failed during preprocessing: error writing the preprocessed output", .{});
183183 std.process.exit(1);
184184 },
185185 error.OutOfMemory => |e| return e,
......@@ -191,13 +191,13 @@ pub fn main() !void {
191191 .stdio => |file| {
192192 var file_reader = file.reader(io, &.{});
193193 break :full_input file_reader.interface.allocRemaining(gpa, .unlimited) catch |err| {
194 try error_handler.emitMessage(gpa, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
194 try error_handler.emitMessage(gpa, io, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
195195 std.process.exit(1);
196196 };
197197 },
198198 .filename => |input_filename| {
199199 break :full_input Io.Dir.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| {
200 try error_handler.emitMessage(gpa, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
200 try error_handler.emitMessage(gpa, io, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
201201 std.process.exit(1);
202202 };
203203 },
......@@ -228,12 +228,12 @@ pub fn main() !void {
228228 }
229229 else if (options.input_format == .res)
230230 IoStream.fromIoSource(options.input_source, .input) catch |err| {
231 try error_handler.emitMessage(gpa, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
231 try error_handler.emitMessage(gpa, io, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
232232 std.process.exit(1);
233233 }
234234 else
235235 IoStream.fromIoSource(options.output_source, .output) catch |err| {
236 try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
236 try error_handler.emitMessage(gpa, io, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
237237 std.process.exit(1);
238238 };
239239 defer res_stream.deinit(gpa);
......@@ -246,17 +246,17 @@ pub fn main() !void {
246246 var mapping_results = parseAndRemoveLineCommands(gpa, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {
247247 error.InvalidLineCommand => {
248248 // TODO: Maybe output the invalid line command
249 try error_handler.emitMessage(gpa, .err, "invalid line command in the preprocessed source", .{});
249 try error_handler.emitMessage(gpa, io, .err, "invalid line command in the preprocessed source", .{});
250250 if (options.preprocess == .no) {
251 try error_handler.emitMessage(gpa, .note, "line commands must be of the format: #line <num> \"<path>\"", .{});
251 try error_handler.emitMessage(gpa, io, .note, "line commands must be of the format: #line <num> \"<path>\"", .{});
252252 } else {
253 try error_handler.emitMessage(gpa, .note, "this is likely to be a bug, please report it", .{});
253 try error_handler.emitMessage(gpa, io, .note, "this is likely to be a bug, please report it", .{});
254254 }
255255 std.process.exit(1);
256256 },
257257 error.LineNumberOverflow => {
258258 // TODO: Better error message
259 try error_handler.emitMessage(gpa, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)});
259 try error_handler.emitMessage(gpa, io, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)});
260260 std.process.exit(1);
261261 },
262262 error.OutOfMemory => |e| return e,
......@@ -306,13 +306,13 @@ pub fn main() !void {
306306
307307 // print any warnings/notes
308308 if (!zig_integration) {
309 diagnostics.renderToStdErr(Io.Dir.cwd(), final_input, mapping_results.mappings);
309 diagnostics.renderToStderr(io, Io.Dir.cwd(), final_input, mapping_results.mappings);
310310 }
311311
312312 // write the depfile
313313 if (options.depfile_path) |depfile_path| {
314314 var depfile = Io.Dir.cwd().createFile(io, depfile_path, .{}) catch |err| {
315 try error_handler.emitMessage(gpa, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) });
315 try error_handler.emitMessage(gpa, io, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) });
316316 std.process.exit(1);
317317 };
318318 defer depfile.close(io);
......@@ -340,7 +340,7 @@ pub fn main() !void {
340340 if (options.output_format != .coff) return;
341341
342342 break :res_data res_stream.source.readAll(gpa, io) catch |err| {
343 try error_handler.emitMessage(gpa, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
343 try error_handler.emitMessage(gpa, io, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
344344 std.process.exit(1);
345345 };
346346 };
......@@ -353,14 +353,14 @@ pub fn main() !void {
353353 var res_reader: std.Io.Reader = .fixed(res_data.bytes);
354354 break :resources cvtres.parseRes(gpa, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {
355355 // TODO: Better errors
356 try error_handler.emitMessage(gpa, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
356 try error_handler.emitMessage(gpa, io, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
357357 std.process.exit(1);
358358 };
359359 };
360360 defer resources.deinit();
361361
362362 var coff_stream = IoStream.fromIoSource(options.output_source, .output) catch |err| {
363 try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
363 try error_handler.emitMessage(gpa, io, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
364364 std.process.exit(1);
365365 };
366366 defer coff_stream.deinit(gpa);
......@@ -373,7 +373,7 @@ pub fn main() !void {
373373 switch (err) {
374374 error.DuplicateResource => {
375375 const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
376 try error_handler.emitMessage(gpa, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
376 try error_handler.emitMessage(gpa, io, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
377377 duplicate_resource.name_value,
378378 fmtResourceType(duplicate_resource.type_value),
379379 duplicate_resource.language,
......@@ -381,8 +381,8 @@ pub fn main() !void {
381381 },
382382 error.ResourceDataTooLong => {
383383 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
384 try error_handler.emitMessage(gpa, .err, "resource has a data length that is too large to be written into a coff section", .{});
385 try error_handler.emitMessage(gpa, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
384 try error_handler.emitMessage(gpa, io, .err, "resource has a data length that is too large to be written into a coff section", .{});
385 try error_handler.emitMessage(gpa, io, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
386386 overflow_resource.name_value,
387387 fmtResourceType(overflow_resource.type_value),
388388 overflow_resource.language,
......@@ -390,15 +390,15 @@ pub fn main() !void {
390390 },
391391 error.TotalResourceDataTooLong => {
392392 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
393 try error_handler.emitMessage(gpa, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
394 try error_handler.emitMessage(gpa, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
393 try error_handler.emitMessage(gpa, io, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
394 try error_handler.emitMessage(gpa, io, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
395395 overflow_resource.name_value,
396396 fmtResourceType(overflow_resource.type_value),
397397 overflow_resource.language,
398398 });
399399 },
400400 else => {
401 try error_handler.emitMessage(gpa, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) });
401 try error_handler.emitMessage(gpa, io, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) });
402402 },
403403 }
404404 // Delete the output file on error
......@@ -550,16 +550,16 @@ const LazyIncludePaths = struct {
550550 else => |e| {
551551 switch (e) {
552552 error.UnsupportedAutoIncludesMachineType => {
553 try error_handler.emitMessage(self.arena, .err, "automatic include path detection is not supported for target '{s}'", .{@tagName(self.target_machine_type)});
553 try error_handler.emitMessage(self.arena, io, .err, "automatic include path detection is not supported for target '{s}'", .{@tagName(self.target_machine_type)});
554554 },
555555 error.MsvcIncludesNotFound => {
556 try error_handler.emitMessage(self.arena, .err, "MSVC include paths could not be automatically detected", .{});
556 try error_handler.emitMessage(self.arena, io, .err, "MSVC include paths could not be automatically detected", .{});
557557 },
558558 error.MingwIncludesNotFound => {
559 try error_handler.emitMessage(self.arena, .err, "MinGW include paths could not be automatically detected", .{});
559 try error_handler.emitMessage(self.arena, io, .err, "MinGW include paths could not be automatically detected", .{});
560560 },
561561 }
562 try error_handler.emitMessage(self.arena, .note, "to disable auto includes, use the option /:auto-includes none", .{});
562 try error_handler.emitMessage(self.arena, io, .note, "to disable auto includes, use the option /:auto-includes none", .{});
563563 std.process.exit(1);
564564 },
565565 };
......@@ -664,6 +664,7 @@ const ErrorHandler = union(enum) {
664664 pub fn emitCliDiagnostics(
665665 self: *ErrorHandler,
666666 allocator: Allocator,
667 io: Io,
667668 args: []const []const u8,
668669 diagnostics: *cli.Diagnostics,
669670 ) !void {
......@@ -674,7 +675,7 @@ const ErrorHandler = union(enum) {
674675
675676 try server.serveErrorBundle(error_bundle);
676677 },
677 .stderr => diagnostics.renderToStdErr(args),
678 .stderr => diagnostics.renderToStderr(io, args),
678679 }
679680 }
680681
......@@ -684,6 +685,7 @@ const ErrorHandler = union(enum) {
684685 fail_msg: []const u8,
685686 comp: *aro.Compilation,
686687 ) !void {
688 const io = comp.io;
687689 switch (self.*) {
688690 .server => |*server| {
689691 var error_bundle = try compiler_util.aroDiagnosticsToErrorBundle(
......@@ -697,9 +699,9 @@ const ErrorHandler = union(enum) {
697699 },
698700 .stderr => {
699701 // aro errors have already been emitted
700 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
701 defer std.debug.unlockStderrWriter();
702 try renderErrorMessage(stderr, ttyconf, .err, "{s}", .{fail_msg});
702 const stderr = io.lockStderrWriter(&.{});
703 defer io.unlockStderrWriter();
704 try renderErrorMessage(&stderr.interface, stderr.mode, .err, "{s}", .{fail_msg});
703705 },
704706 }
705707 }
......@@ -707,6 +709,7 @@ const ErrorHandler = union(enum) {
707709 pub fn emitDiagnostics(
708710 self: *ErrorHandler,
709711 allocator: Allocator,
712 io: Io,
710713 cwd: Io.Dir,
711714 source: []const u8,
712715 diagnostics: *Diagnostics,
......@@ -719,13 +722,14 @@ const ErrorHandler = union(enum) {
719722
720723 try server.serveErrorBundle(error_bundle);
721724 },
722 .stderr => diagnostics.renderToStdErr(cwd, source, mappings),
725 .stderr => diagnostics.renderToStderr(io, cwd, source, mappings),
723726 }
724727 }
725728
726729 pub fn emitMessage(
727730 self: *ErrorHandler,
728731 allocator: Allocator,
732 io: Io,
729733 msg_type: @import("utils.zig").ErrorMessageType,
730734 comptime format: []const u8,
731735 args: anytype,
......@@ -741,9 +745,9 @@ const ErrorHandler = union(enum) {
741745 try server.serveErrorBundle(error_bundle);
742746 },
743747 .stderr => {
744 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
745 defer std.debug.unlockStderrWriter();
746 try renderErrorMessage(stderr, ttyconf, msg_type, format, args);
748 const stderr = io.lockStderrWriter(&.{});
749 defer io.unlockStderrWriter();
750 try renderErrorMessage(&stderr.interface, stderr.mode, msg_type, format, args);
747751 },
748752 }
749753 }
lib/compiler/std-docs.zig+1-1
......@@ -407,7 +407,7 @@ fn buildWasmBinary(
407407 }
408408
409409 if (result_error_bundle.errorMessageCount() > 0) {
410 result_error_bundle.renderToStdErr(.{}, true);
410 result_error_bundle.renderToStderr(io, .{}, true);
411411 std.log.err("the following command failed with {d} compilation errors:\n{s}", .{
412412 result_error_bundle.errorMessageCount(),
413413 try std.Build.Step.allocPrintCmd(arena, null, argv.items),
lib/compiler/test_runner.zig-3
......@@ -411,16 +411,13 @@ pub fn fuzz(
411411 std.debug.writeStackTrace(trace, &stderr.interface, stderr.mode) catch break :p;
412412 }
413413 stderr.interface.print("failed with error.{t}\n", .{err}) catch break :p;
414 stderr.interface.flush() catch break :p;
415414 }
416 stderr.interface.flush() catch {};
417415 std.process.exit(1);
418416 },
419417 };
420418 if (log_err_count != 0) {
421419 const stderr = std.debug.lockStderrWriter(&.{});
422420 stderr.interface.print("error logs detected\n", .{}) catch {};
423 stderr.interface.flush() catch {};
424421 std.process.exit(1);
425422 }
426423 }
lib/std/Build.zig+23-8
......@@ -2238,7 +2238,7 @@ pub const GeneratedFile = struct {
22382238 /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
22392239 path: ?[]const u8 = null,
22402240
2241 /// Deprecated, see `getPath2`.
2241 /// Deprecated, see `getPath3`.
22422242 pub fn getPath(gen: GeneratedFile) []const u8 {
22432243 return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic(
22442244 "getPath() was called on a GeneratedFile that wasn't built yet. Is there a missing Step dependency on step '{s}'?",
......@@ -2246,11 +2246,18 @@ pub const GeneratedFile = struct {
22462246 ));
22472247 }
22482248
2249 /// Deprecated, see `getPath3`.
22492250 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {
2251 return getPath3(gen, src_builder, asking_step) catch |err| switch (err) {
2252 error.Canceled => std.process.exit(1),
2253 };
2254 }
2255
2256 pub fn getPath3(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) Io.Cancelable![]const u8 {
22502257 return gen.path orelse {
2251 const stderr = std.debug.lockStderrWriter(&.{});
2258 const io = gen.step.owner.graph.io;
2259 const stderr = try io.lockStderrWriter(&.{});
22522260 dumpBadGetPathHelp(gen.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};
2253 std.debug.unlockStderrWriter();
22542261 @panic("misconfigured build script");
22552262 };
22562263 }
......@@ -2425,22 +2432,29 @@ pub const LazyPath = union(enum) {
24252432 }
24262433 }
24272434
2428 /// Deprecated, see `getPath3`.
2435 /// Deprecated, see `getPath4`.
24292436 pub fn getPath(lazy_path: LazyPath, src_builder: *Build) []const u8 {
24302437 return getPath2(lazy_path, src_builder, null);
24312438 }
24322439
2433 /// Deprecated, see `getPath3`.
2440 /// Deprecated, see `getPath4`.
24342441 pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
24352442 const p = getPath3(lazy_path, src_builder, asking_step);
24362443 return src_builder.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path });
24372444 }
24382445
2446 /// Deprecated, see `getPath4`.
2447 pub fn getPath3(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Cache.Path {
2448 return getPath4(lazy_path, src_builder, asking_step) catch |err| switch (err) {
2449 error.Canceled => std.process.exit(1),
2450 };
2451 }
2452
24392453 /// Intended to be used during the make phase only.
24402454 ///
24412455 /// `asking_step` is only used for debugging purposes; it's the step being
24422456 /// run that is asking for the path.
2443 pub fn getPath3(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Cache.Path {
2457 pub fn getPath4(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Io.Cancelable!Cache.Path {
24442458 switch (lazy_path) {
24452459 .src_path => |sp| return .{
24462460 .root_dir = sp.owner.build_root,
......@@ -2457,9 +2471,10 @@ pub const LazyPath = union(enum) {
24572471 var file_path: Cache.Path = .{
24582472 .root_dir = Cache.Directory.cwd(),
24592473 .sub_path = gen.file.path orelse {
2460 const stderr = std.debug.lockStderrWriter(&.{});
2474 const io = src_builder.graph.io;
2475 const stderr = try io.lockStderrWriter(&.{});
24612476 dumpBadGetPathHelp(gen.file.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};
2462 std.debug.unlockStderrWriter();
2477 io.unlockStderrWriter();
24632478 @panic("misconfigured build script");
24642479 },
24652480 };
lib/std/Build/Fuzz.zig+11-10
......@@ -158,6 +158,7 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.P
158158}
159159
160160fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void {
161 const io = run.step.owner.graph.io;
161162 const compile = run.producer.?;
162163 const prog_node = parent_prog_node.start(compile.step.name, 0);
163164 defer prog_node.end();
......@@ -170,8 +171,8 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
170171
171172 if (show_error_msgs or show_compile_errors or show_stderr) {
172173 var buf: [256]u8 = undefined;
173 const stderr = std.debug.lockStderrWriter(&buf);
174 defer std.debug.unlockStderrWriter();
174 const stderr = try io.lockStderrWriter(&buf);
175 defer io.unlockStderrWriter();
175176 build_runner.printErrorMessages(gpa, &compile.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};
176177 }
177178
......@@ -182,12 +183,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
182183 run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename);
183184}
184185
185fn fuzzWorkerRun(
186 fuzz: *Fuzz,
187 run: *Step.Run,
188 unit_test_index: u32,
189) void {
190 const gpa = run.step.owner.allocator;
186fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void {
187 const owner = run.step.owner;
188 const gpa = owner.allocator;
189 const io = owner.graph.io;
191190 const test_name = run.cached_test_metadata.?.testName(unit_test_index);
192191
193192 const prog_node = fuzz.prog_node.start(test_name, 0);
......@@ -196,8 +195,10 @@ fn fuzzWorkerRun(
196195 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {
197196 error.MakeFailed => {
198197 var buf: [256]u8 = undefined;
199 const stderr = std.debug.lockStderrWriter(&buf);
200 defer std.debug.unlockStderrWriter();
198 const stderr = io.lockStderrWriter(&buf) catch |e| switch (e) {
199 error.Canceled => return,
200 };
201 defer io.unlockStderrWriter();
201202 build_runner.printErrorMessages(gpa, &run.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};
202203 return;
203204 },
lib/std/Build/Step/Compile.zig+10-7
......@@ -922,20 +922,23 @@ const CliNamedModules = struct {
922922 }
923923};
924924
925fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) []const u8 {
925fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 {
926 const step = &compile.step;
927 const b = step.owner;
928 const io = b.graph.io;
926929 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
927930
928931 const generated_file = maybe_path orelse {
929 const stderr = std.debug.lockStderrWriter(&.{});
932 const stderr = try io.lockStderrWriter(&.{});
930933 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};
931 std.debug.unlockStderrWriter();
934 io.unlockStderrWriter();
932935 @panic("missing emit option for " ++ tag_name);
933936 };
934937
935938 const path = generated_file.path orelse {
936 const stderr = std.debug.lockStderrWriter(&.{});
939 const stderr = try io.lockStderrWriter(&.{});
937940 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};
938 std.debug.unlockStderrWriter();
941 io.unlockStderrWriter();
939942 @panic(tag_name ++ " is null. Is there a missing step dependency?");
940943 };
941944
......@@ -1149,9 +1152,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
11491152 // For everything else, we directly link
11501153 // against the library file.
11511154 const full_path_lib = if (other_produces_implib)
1152 other.getGeneratedFilePath("generated_implib", &compile.step)
1155 try other.getGeneratedFilePath("generated_implib", &compile.step)
11531156 else
1154 other.getGeneratedFilePath("generated_bin", &compile.step);
1157 try other.getGeneratedFilePath("generated_bin", &compile.step);
11551158
11561159 try zig_args.append(full_path_lib);
11571160 total_linker_objects += 1;
lib/std/Build/Step/Run.zig+3-2
......@@ -1559,6 +1559,7 @@ fn spawnChildAndCollect(
15591559) !?EvalGenericResult {
15601560 const b = run.step.owner;
15611561 const arena = b.allocator;
1562 const io = b.graph.io;
15621563
15631564 if (fuzz_context != null) {
15641565 assert(!has_side_effects);
......@@ -1625,10 +1626,10 @@ fn spawnChildAndCollect(
16251626 child.progress_node = options.progress_node;
16261627 }
16271628 if (inherit) {
1628 const stderr = std.debug.lockStderrWriter(&.{});
1629 const stderr = try io.lockStderrWriter(&.{});
16291630 try setColorEnvironmentVariables(run, env_map, stderr.mode);
16301631 }
1631 defer if (inherit) std.debug.unlockStderrWriter();
1632 defer if (inherit) io.unlockStderrWriter();
16321633 var timer = try std.time.Timer.start();
16331634 const res = try evalGeneric(run, &child);
16341635 run.step.result_duration_ns = timer.read();
lib/std/Build/WebServer.zig+1-1
......@@ -655,7 +655,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
655655 }
656656
657657 if (result_error_bundle.errorMessageCount() > 0) {
658 result_error_bundle.renderToStdErr(.{}, .auto);
658 try result_error_bundle.renderToStderr(io, .{}, .auto);
659659 log.err("the following command failed with {d} compilation errors:\n{s}", .{
660660 result_error_bundle.errorMessageCount(),
661661 try Build.Step.allocPrintCmd(arena, null, argv.items),
lib/std/Progress.zig+1-1
......@@ -764,7 +764,7 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {
764764 }
765765}
766766
767pub fn clearWrittenWithEscapeCodes(file_writer: *Io.File.Writer) anyerror!void {
767pub fn clearWrittenWithEscapeCodes(file_writer: *Io.File.Writer) Io.Writer.Error!void {
768768 if (noop_impl or !global_progress.need_clear) return;
769769 try file_writer.writeAllUnescaped(clear ++ progress_remove);
770770 global_progress.need_clear = false;
lib/std/json/dynamic.zig+2-3
......@@ -47,10 +47,9 @@ pub const Value = union(enum) {
4747 }
4848
4949 pub fn dump(v: Value) void {
50 const w, _ = std.debug.lockStderrWriter(&.{});
50 const stderr = std.debug.lockStderrWriter(&.{});
5151 defer std.debug.unlockStderrWriter();
52
53 json.Stringify.value(v, .{}, w) catch return;
52 json.Stringify.value(v, .{}, &stderr.interface) catch return;
5453 }
5554
5655 pub fn jsonStringify(value: @This(), jws: anytype) !void {
lib/std/process.zig+1-1
......@@ -1849,7 +1849,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
18491849/// and does not return.
18501850pub fn cleanExit(io: Io) void {
18511851 if (builtin.mode == .Debug) return;
1852 _ = io.lockStderrWriter(&.{});
1852 _ = io.lockStderrWriter(&.{}) catch {};
18531853 exit(0);
18541854}
18551855
lib/std/testing.zig+12-4
......@@ -368,13 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
368368 break :diff_index if (expected.len == actual.len) return else shortest;
369369 };
370370 if (!backend_can_print) return error.TestExpectedEqual;
371 const stderr = std.debug.lockStderrWriter(&.{});
372 defer std.debug.unlockStderrWriter();
373 failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {};
371 if (io.lockStderrWriter(&.{})) |stderr| {
372 defer io.unlockStderrWriter();
373 failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {};
374 } else |_| {}
374375 return error.TestExpectedEqual;
375376}
376377
377fn failEqualSlices(comptime T: type, expected: []const T, actual: []const T, diff_index: usize, w: *Io.Writer, fwm: Io.File.Writer.Mode) !void {
378fn failEqualSlices(
379 comptime T: type,
380 expected: []const T,
381 actual: []const T,
382 diff_index: usize,
383 w: *Io.Writer,
384 fwm: Io.File.Writer.Mode,
385) !void {
378386 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });
379387
380388 // TODO: Should this be configurable by the caller?
lib/std/zig.zig+2-2
......@@ -639,7 +639,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *Io.File.Reader) ![
639639 return buffer.toOwnedSliceSentinel(gpa, 0);
640640}
641641
642pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void {
642pub fn printAstErrorsToStderr(gpa: Allocator, io: Io, tree: Ast, path: []const u8, color: Color) !void {
643643 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
644644 try wip_errors.init(gpa);
645645 defer wip_errors.deinit();
......@@ -648,7 +648,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color
648648
649649 var error_bundle = try wip_errors.toOwnedBundle("");
650650 defer error_bundle.deinit(gpa);
651 error_bundle.renderToStdErr(.{}, color);
651 error_bundle.renderToStderr(io, .{}, color);
652652}
653653
654654pub fn putAstErrorsIntoBundle(
lib/std/zig/ErrorBundle.zig+6-4
......@@ -162,11 +162,13 @@ pub const RenderOptions = struct {
162162 include_log_text: bool = true,
163163};
164164
165pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions, color: std.zig.Color) void {
165pub const RenderToStderrError = Io.Cancelable || Io.File.Writer.Mode.SetColorError;
166
167pub fn renderToStderr(eb: ErrorBundle, io: Io, options: RenderOptions, color: std.zig.Color) RenderToStderrError!void {
166168 var buffer: [256]u8 = undefined;
167 const stderr = std.debug.lockStderrWriter(&buffer);
168 defer std.debug.unlockStderrWriter();
169 renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode)) catch return;
169 const stderr = try io.lockStderrWriter(&buffer);
170 defer io.unlockStderrWriter();
171 try renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode));
170172}
171173
172174pub fn renderToWriter(
lib/std/zig/parser_test.zig+19-11
......@@ -1,7 +1,6 @@
11const std = @import("std");
2const mem = std.mem;
3const print = std.debug.print;
4const maxInt = std.math.maxInt;
2const Io = std.Io;
3const Allocator = std.mem.Allocator;
54
65test "zig fmt: remove extra whitespace at start and end of file with comment between" {
76 try testTransform(
......@@ -6332,10 +6331,10 @@ test "ampersand" {
63326331
63336332var fixed_buffer_mem: [100 * 1024]u8 = undefined;
63346333
6335fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
6334fn testParse(io: Io, source: [:0]const u8, allocator: Allocator, anything_changed: *bool) ![]u8 {
63366335 var buffer: [64]u8 = undefined;
6337 const stderr = std.debug.lockStderrWriter(&buffer);
6338 defer std.debug.unlockStderrWriter();
6336 const stderr = try io.lockStderrWriter(&buffer);
6337 defer io.unlockStderrWriter();
63396338
63406339 var tree = try std.zig.Ast.parse(allocator, source, .zig);
63416340 defer tree.deinit(allocator);
......@@ -6359,27 +6358,36 @@ fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *
63596358 }
63606359
63616360 const formatted = try tree.renderAlloc(allocator);
6362 anything_changed.* = !mem.eql(u8, formatted, source);
6361 anything_changed.* = !std.mem.eql(u8, formatted, source);
63636362 return formatted;
63646363}
6365fn testTransformImpl(allocator: mem.Allocator, fba: *std.heap.FixedBufferAllocator, source: [:0]const u8, expected_source: []const u8) !void {
6364fn testTransformImpl(
6365 io: Io,
6366 allocator: Allocator,
6367 fba: *std.heap.FixedBufferAllocator,
6368 source: [:0]const u8,
6369 expected_source: []const u8,
6370) !void {
63666371 // reset the fixed buffer allocator each run so that it can be re-used for each
63676372 // iteration of the failing index
63686373 fba.reset();
63696374 var anything_changed: bool = undefined;
6370 const result_source = try testParse(source, allocator, &anything_changed);
6375 const result_source = try testParse(io, source, allocator, &anything_changed);
63716376 try std.testing.expectEqualStrings(expected_source, result_source);
63726377 const changes_expected = source.ptr != expected_source.ptr;
63736378 if (anything_changed != changes_expected) {
6374 print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });
6379 std.debug.print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });
63756380 return error.TestFailed;
63766381 }
63776382 try std.testing.expect(anything_changed == changes_expected);
63786383 allocator.free(result_source);
63796384}
63806385fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {
6386 const io = std.testing.io;
63816387 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
6382 return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{ &fixed_allocator, source, expected_source });
6388 return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{
6389 io, &fixed_allocator, source, expected_source,
6390 });
63836391}
63846392fn testCanonical(source: [:0]const u8) !void {
63856393 return testTransform(source, source);
src/Air/print.zig+18-10
......@@ -9,7 +9,7 @@ const Type = @import("../Type.zig");
99const Air = @import("../Air.zig");
1010const InternPool = @import("../InternPool.zig");
1111
12pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
12pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) !void {
1313 comptime assert(build_options.enable_debug_extensions);
1414 const instruction_bytes = air.instructions.len *
1515 // Here we don't use @sizeOf(Air.Inst.Data) because it would include
......@@ -24,7 +24,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
2424 liveness_special_bytes + tomb_bytes;
2525
2626 // zig fmt: off
27 stream.print(
27 try stream.print(
2828 \\# Total AIR+Liveness bytes: {Bi}
2929 \\# AIR Instructions: {d} ({Bi})
3030 \\# AIR Extra Data: {d} ({Bi})
......@@ -39,7 +39,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
3939 tomb_bytes,
4040 if (liveness) |l| l.extra.len else 0, liveness_extra_bytes,
4141 if (liveness) |l| l.special.count() else 0, liveness_special_bytes,
42 }) catch return;
42 });
4343 // zig fmt: on
4444
4545 var writer: Writer = .{
......@@ -50,7 +50,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
5050 .indent = 2,
5151 .skip_body = false,
5252 };
53 writer.writeBody(stream, air.getMainBody()) catch return;
53 try writer.writeBody(stream, air.getMainBody());
5454}
5555
5656pub fn writeInst(
......@@ -73,15 +73,23 @@ pub fn writeInst(
7373}
7474
7575pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
76 const stderr_bw, _ = std.debug.lockStderrWriter(&.{});
77 defer std.debug.unlockStderrWriter();
78 air.write(stderr_bw, pt, liveness);
76 const comp = pt.zcu.comp;
77 const io = comp.io;
78 var buffer: [512]u8 = undefined;
79 const stderr = try io.lockStderrWriter(&buffer);
80 defer io.unlockStderrWriter();
81 const w = &stderr.interface;
82 air.write(w, pt, liveness);
7983}
8084
8185pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
82 const stderr_bw, _ = std.debug.lockStderrWriter(&.{});
83 defer std.debug.unlockStderrWriter();
84 air.writeInst(stderr_bw, inst, pt, liveness);
86 const comp = pt.zcu.comp;
87 const io = comp.io;
88 var buffer: [512]u8 = undefined;
89 const stderr = try io.lockStderrWriter(&buffer);
90 defer io.unlockStderrWriter();
91 const w = &stderr.interface;
92 air.writeInst(w, inst, pt, liveness);
8593}
8694
8795const Writer = struct {
src/Compilation.zig+30-23
......@@ -2088,12 +2088,13 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
20882088
20892089 if (options.verbose_llvm_cpu_features) {
20902090 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
2091 const stderr_w, _ = std.debug.lockStderrWriter(&.{});
2092 defer std.debug.unlockStderrWriter();
2093 stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
2094 stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
2095 stderr_w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
2096 stderr_w.print(" features: {s}\n", .{cf}) catch {};
2091 const stderr = try io.lockStderrWriter(&.{});
2092 defer io.unlockStderrWriter();
2093 const w = &stderr.interface;
2094 w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
2095 w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
2096 w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
2097 w.print(" features: {s}\n", .{cf}) catch {};
20972098 }
20982099 }
20992100
......@@ -4257,12 +4258,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
42574258 // However, we haven't reported any such error.
42584259 // This is a compiler bug.
42594260 print_ctx: {
4260 var stderr_w, _ = std.debug.lockStderrWriter(&.{});
4261 defer std.debug.unlockStderrWriter();
4262 stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;
4263 stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;
4261 const stderr = try io.lockStderrWriter(&.{});
4262 defer io.unlockStderrWriter();
4263 const w = &stderr.interface;
4264 w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;
4265 w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;
42644266 while (ref) |r| {
4265 stderr_w.print("referenced by: {f}{s}\n", .{
4267 w.print("referenced by: {f}{s}\n", .{
42664268 zcu.fmtAnalUnit(r.referencer),
42674269 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
42684270 }) catch break :print_ctx;
......@@ -5756,7 +5758,7 @@ pub fn translateC(
57565758 try argv.appendSlice(comp.global_cc_argv);
57575759 try argv.appendSlice(owner_mod.cc_argv);
57585760 try argv.appendSlice(&.{ source_path, "-o", translated_path });
5759 if (comp.verbose_cimport) dump_argv(argv.items);
5761 if (comp.verbose_cimport) dumpArgv(io, argv.items);
57605762 }
57615763
57625764 var stdout: []u8 = undefined;
......@@ -6264,7 +6266,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
62646266 }
62656267
62666268 if (comp.verbose_cc) {
6267 dump_argv(argv.items);
6269 dumpArgv(io, argv.items);
62686270 }
62696271
62706272 const err = std.process.execv(arena, argv.items);
......@@ -6310,7 +6312,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
63106312 }
63116313
63126314 if (comp.verbose_cc) {
6313 dump_argv(argv.items);
6315 dumpArgv(io, argv.items);
63146316 }
63156317
63166318 // Just to save disk space, we delete the files that are never needed again.
......@@ -7773,17 +7775,22 @@ pub fn lockAndSetMiscFailure(
77737775 return setMiscFailure(comp, tag, format, args);
77747776}
77757777
7776pub fn dump_argv(argv: []const []const u8) void {
7778pub fn dumpArgv(io: Io, argv: []const []const u8) Io.Cancelable!void {
77777779 var buffer: [64]u8 = undefined;
7778 const stderr, _ = std.debug.lockStderrWriter(&buffer);
7779 defer std.debug.unlockStderrWriter();
7780 nosuspend {
7781 for (argv, 0..) |arg, i| {
7782 if (i != 0) stderr.writeByte(' ') catch return;
7783 stderr.writeAll(arg) catch return;
7784 }
7785 stderr.writeByte('\n') catch return;
7780 const stderr = try io.lockStderrWriter(&buffer);
7781 defer io.unlockStderrWriter();
7782 const w = &stderr.interface;
7783 return dumpArgvWriter(w, argv) catch |err| switch (err) {
7784 error.WriteFailed => return stderr.err.?,
7785 };
7786}
7787
7788fn dumpArgvWriter(w: *Io.Writer, argv: []const []const u8) Io.Writer.Error!void {
7789 for (argv, 0..) |arg, i| {
7790 if (i != 0) try w.writeByte(' ');
7791 try w.writeAll(arg);
77867792 }
7793 try w.writeByte('\n');
77877794}
77887795
77897796pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
src/InternPool.zig+32-31
......@@ -1,8 +1,11 @@
11//! All interned objects have both a value and a type.
22//! This data structure is self-contained.
3const InternPool = @This();
34
45const builtin = @import("builtin");
6
57const std = @import("std");
8const Io = std.Io;
69const Allocator = std.mem.Allocator;
710const assert = std.debug.assert;
811const BigIntConst = std.math.big.int.Const;
......@@ -11,10 +14,9 @@ const Cache = std.Build.Cache;
1114const Io = std.Io;
1215const Limb = std.math.big.Limb;
1316const Hash = std.hash.Wyhash;
17const Zir = std.zig.Zir;
1418
15const InternPool = @This();
1619const Zcu = @import("Zcu.zig");
17const Zir = std.zig.Zir;
1820
1921/// One item per thread, indexed by `tid`, which is dense and unique per thread.
2022locals: []Local,
......@@ -11165,12 +11167,16 @@ pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) v
1116511167 @atomicStore(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.Variable, "init").?], @intFromEnum(init_index), .release);
1116611168}
1116711169
11168pub fn dump(ip: *const InternPool) void {
11169 dumpStatsFallible(ip, std.heap.page_allocator) catch return;
11170 dumpAllFallible(ip) catch return;
11170pub fn dump(ip: *const InternPool, io: Io) Io.Cancelable!void {
11171 var buffer: [4096]u8 = undefined;
11172 const stderr_writer = try io.lockStderrWriter(&buffer);
11173 defer io.unlockStderrWriter();
11174 const w = &stderr_writer.interface;
11175 try dumpStatsFallible(ip, w, std.heap.page_allocator);
11176 try dumpAllFallible(ip, w);
1117111177}
1117211178
11173fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
11179fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) anyerror!void {
1117411180 var items_len: usize = 0;
1117511181 var extra_len: usize = 0;
1117611182 var limbs_len: usize = 0;
......@@ -11423,18 +11429,13 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
1142311429 };
1142411430 counts.sort(SortContext{ .map = &counts });
1142511431 const len = @min(50, counts.count());
11426 std.debug.print(" top 50 tags:\n", .{});
11432 w.print(" top 50 tags:\n", .{});
1142711433 for (counts.keys()[0..len], counts.values()[0..len]) |tag, stats| {
11428 std.debug.print(" {s}: {d} occurrences, {d} total bytes\n", .{
11429 @tagName(tag), stats.count, stats.bytes,
11430 });
11434 w.print(" {t}: {d} occurrences, {d} total bytes\n", .{ tag, stats.count, stats.bytes });
1143111435 }
1143211436}
1143311437
11434fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11435 var buffer: [4096]u8 = undefined;
11436 const stderr_bw, _ = std.debug.lockStderrWriter(&buffer);
11437 defer std.debug.unlockStderrWriter();
11438fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
1143811439 for (ip.locals, 0..) |*local, tid| {
1143911440 const items = local.shared.items.view();
1144011441 for (
......@@ -11443,12 +11444,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
1144311444 0..,
1144411445 ) |tag, data, index| {
1144511446 const i = Index.Unwrapped.wrap(.{ .tid = @enumFromInt(tid), .index = @intCast(index) }, ip);
11446 try stderr_bw.print("${d} = {s}(", .{ i, @tagName(tag) });
11447 try w.print("${d} = {s}(", .{ i, @tagName(tag) });
1144711448 switch (tag) {
1144811449 .removed => {},
1144911450
11450 .simple_type => try stderr_bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),
11451 .simple_value => try stderr_bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),
11451 .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),
11452 .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),
1145211453
1145311454 .type_int_signed,
1145411455 .type_int_unsigned,
......@@ -11521,23 +11522,27 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
1152111522 .func_coerced,
1152211523 .union_value,
1152311524 .memoized_call,
11524 => try stderr_bw.print("{d}", .{data}),
11525 => try w.print("{d}", .{data}),
1152511526
1152611527 .opt_null,
1152711528 .type_slice,
1152811529 .only_possible_value,
11529 => try stderr_bw.print("${d}", .{data}),
11530 => try w.print("${d}", .{data}),
1153011531 }
11531 try stderr_bw.writeAll(")\n");
11532 try w.writeAll(")\n");
1153211533 }
1153311534 }
1153411535}
1153511536
11536pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {
11537 ip.dumpGenericInstancesFallible(allocator) catch return;
11537pub fn dumpGenericInstances(ip: *const InternPool, io: Io, allocator: Allocator) Io.Cancelable!void {
11538 var buffer: [4096]u8 = undefined;
11539 const stderr_writer = try io.lockStderrWriter(&buffer);
11540 defer io.unlockStderrWriter();
11541 const w = &stderr_writer.interface;
11542 try ip.dumpGenericInstancesFallible(allocator, w);
1153811543}
1153911544
11540pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) anyerror!void {
11545pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, w: *Io.Writer) !void {
1154111546 var arena_allocator = std.heap.ArenaAllocator.init(allocator);
1154211547 defer arena_allocator.deinit();
1154311548 const arena = arena_allocator.allocator();
......@@ -11564,10 +11569,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
1156411569 }
1156511570 }
1156611571
11567 var buffer: [4096]u8 = undefined;
11568 const stderr_bw, _ = std.debug.lockStderrWriter(&buffer);
11569 defer std.debug.unlockStderrWriter();
11570
1157111572 const SortContext = struct {
1157211573 values: []std.ArrayList(Index),
1157311574 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
......@@ -11579,19 +11580,19 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
1157911580 var it = instances.iterator();
1158011581 while (it.next()) |entry| {
1158111582 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);
11582 try stderr_bw.print("{f} ({d}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
11583 try w.print("{f} ({d}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
1158311584 for (entry.value_ptr.items) |index| {
1158411585 const unwrapped_index = index.unwrap(ip);
1158511586 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));
1158611587 const owner_nav = ip.getNav(func.owner_nav);
11587 try stderr_bw.print(" {f}: (", .{owner_nav.name.fmt(ip)});
11588 try w.print(" {f}: (", .{owner_nav.name.fmt(ip)});
1158811589 for (func.comptime_args.get(ip)) |arg| {
1158911590 if (arg != .none) {
1159011591 const key = ip.indexToKey(arg);
11591 try stderr_bw.print(" {} ", .{key});
11592 try w.print(" {} ", .{key});
1159211593 }
1159311594 }
11594 try stderr_bw.writeAll(")\n");
11595 try w.writeAll(")\n");
1159511596 }
1159611597 }
1159711598}
src/Sema.zig+5-3
......@@ -2668,16 +2668,18 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T
26682668
26692669pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } {
26702670 @branchHint(.cold);
2671 const gpa = sema.gpa;
26722671 const zcu = sema.pt.zcu;
2672 const comp = zcu.comp;
2673 const gpa = comp.gpa;
2674 const io = comp.io;
26732675
2674 if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) {
2676 if (build_options.enable_debug_extensions and comp.debug_compile_errors) {
26752677 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
26762678 wip_errors.init(gpa) catch @panic("out of memory");
26772679 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory");
26782680 std.debug.print("compile error during Sema:\n", .{});
26792681 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");
2680 error_bundle.renderToStdErr(.{}, .auto);
2682 error_bundle.renderToStderr(io, .{}, .auto);
26812683 std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{});
26822684 }
26832685
src/Zcu/PerThread.zig+3-2
......@@ -4556,8 +4556,9 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
45564556 defer if (liveness) |*l| l.deinit(gpa);
45574557
45584558 if (build_options.enable_debug_extensions and comp.verbose_air) {
4559 const stderr, _ = std.debug.lockStderrWriter(&.{});
4560 defer std.debug.unlockStderrWriter();
4559 const io = comp.io;
4560 const stderr = try io.lockStderrWriter(&.{});
4561 defer io.unlockStderrWriter();
45614562 stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {};
45624563 air.write(stderr, pt, liveness);
45634564 stderr.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}) catch {};
src/codegen/aarch64/Select.zig+7-4
......@@ -11273,15 +11273,18 @@ fn initValueAdvanced(
1127311273 return @enumFromInt(isel.values.items.len);
1127411274}
1127511275pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {
11276 errdefer |err| @panic(@errorName(err));
11277 const stderr, _ = std.debug.lockStderrWriter(&.{});
11278 defer std.debug.unlockStderrWriter();
11279
1128011276 const zcu = isel.pt.zcu;
11277 const io = zcu.comp.io;
1128111278 const gpa = zcu.gpa;
1128211279 const ip = &zcu.intern_pool;
1128311280 const nav = ip.getNav(isel.nav_index);
1128411281
11282 errdefer |err| @panic(@errorName(err));
11283
11284 const stderr_writer = io.lockStderrWriter(&.{}) catch return;
11285 defer io.unlockStderrWriter();
11286 const stderr = &stderr_writer.interface;
11287
1128511288 var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;
1128611289 defer {
1128711290 for (reverse_live_values.values()) |*list| list.deinit(gpa);
src/crash_report.zig+5-4
......@@ -97,17 +97,18 @@ fn dumpCrashContext() Io.Writer.Error!void {
9797 // and the actual panic printing, which would be quite confusing.
9898 const stderr = std.debug.lockStderrWriter(&.{});
9999 defer std.debug.unlockStderrWriter();
100 const w = &stderr.interface;
100101
101 try stderr.interface.writeAll("Compiler crash context:\n");
102 try w.writeAll("Compiler crash context:\n");
102103
103104 if (CodegenFunc.current) |*cg| {
104105 const func_nav = cg.zcu.funcInfo(cg.func_index).owner_nav;
105106 const func_fqn = cg.zcu.intern_pool.getNav(func_nav).fqn;
106 try stderr.interface.print("Generating function '{f}'\n\n", .{func_fqn.fmt(&cg.zcu.intern_pool)});
107 try w.print("Generating function '{f}'\n\n", .{func_fqn.fmt(&cg.zcu.intern_pool)});
107108 } else if (AnalyzeBody.current) |anal| {
108 try dumpCrashContextSema(anal, &stderr.interface, &S.crash_heap);
109 try dumpCrashContextSema(anal, w, &S.crash_heap);
109110 } else {
110 try stderr.interface.writeAll("(no context)\n\n");
111 try w.writeAll("(no context)\n\n");
111112 }
112113}
113114fn dumpCrashContextSema(anal: *AnalyzeBody, stderr: *Io.Writer, crash_heap: []u8) Io.Writer.Error!void {
src/fmt.zig+4-4
......@@ -124,7 +124,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
124124 try wip_errors.addZirErrorMessages(zir, tree, source_code, "<stdin>");
125125 var error_bundle = try wip_errors.toOwnedBundle("");
126126 defer error_bundle.deinit(gpa);
127 error_bundle.renderToStdErr(.{}, color);
127 error_bundle.renderToStderr(io, .{}, color);
128128 process.exit(2);
129129 }
130130 } else {
......@@ -138,7 +138,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
138138 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, "<stdin>");
139139 var error_bundle = try wip_errors.toOwnedBundle("");
140140 defer error_bundle.deinit(gpa);
141 error_bundle.renderToStdErr(.{}, color);
141 error_bundle.renderToStderr(io, .{}, color);
142142 process.exit(2);
143143 }
144144 }
......@@ -319,7 +319,7 @@ fn fmtPathFile(
319319 try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path);
320320 var error_bundle = try wip_errors.toOwnedBundle("");
321321 defer error_bundle.deinit(gpa);
322 error_bundle.renderToStdErr(.{}, fmt.color);
322 error_bundle.renderToStderr(io, .{}, fmt.color);
323323 fmt.any_error = true;
324324 }
325325 },
......@@ -334,7 +334,7 @@ fn fmtPathFile(
334334 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path);
335335 var error_bundle = try wip_errors.toOwnedBundle("");
336336 defer error_bundle.deinit(gpa);
337 error_bundle.renderToStdErr(.{}, fmt.color);
337 error_bundle.renderToStderr(io, .{}, fmt.color);
338338 fmt.any_error = true;
339339 }
340340 },
src/libs/mingw.zig+19-10
......@@ -312,11 +312,17 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
312312
313313 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
314314
315 if (comp.verbose_cc) print: {
316 var stderr, _ = std.debug.lockStderrWriter(&.{});
317 defer std.debug.unlockStderrWriter();
318 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;
319 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
315 if (comp.verbose_cc) {
316 var buffer: [256]u8 = undefined;
317 const stderr = try io.lockStderrWriter(&buffer);
318 defer io.unlockStderrWriter();
319 const w = &stderr.interface;
320 w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) {
321 error.WriteFailed => return stderr.err.?,
322 };
323 w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) {
324 error.WriteFailed => return stderr.err.?,
325 };
320326 }
321327
322328 try aro_comp.search_path.append(gpa, .{ .path = include_dir, .kind = .normal });
......@@ -333,11 +339,13 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
333339
334340 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
335341 var buffer: [64]u8 = undefined;
336 const w, const ttyconf = std.debug.lockStderrWriter(&buffer);
337 defer std.debug.unlockStderrWriter();
342 const stderr = try io.lockStderrWriter(&buffer);
343 defer io.unlockStderrWriter();
338344 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {
339345 if (msg.kind == .@"fatal error" or msg.kind == .@"error") {
340 msg.write(w, ttyconf, true) catch {};
346 msg.write(&stderr.interface, stderr.mode, true) catch |err| switch (err) {
347 error.WriteFailed => return stderr.err.?,
348 };
341349 return error.AroPreprocessorFailed;
342350 }
343351 }
......@@ -357,8 +365,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
357365 error.OutOfMemory => |e| return e,
358366 error.ParseError => {
359367 var buffer: [64]u8 = undefined;
360 const w, _ = std.debug.lockStderrWriter(&buffer);
361 defer std.debug.unlockStderrWriter();
368 const stderr = try io.lockStderrWriter(&buffer);
369 defer io.unlockStderrWriter();
370 const w = &stderr.interface;
362371 try w.writeAll("error: ");
363372 try def_diagnostics.writeMsg(w, input);
364373 try w.writeByte('\n');
src/libs/mingw/def.zig+22-10
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const Io = std.Io;
23
34pub const ModuleDefinitionType = enum {
45 mingw,
......@@ -663,7 +664,9 @@ test parse {
663664 \\
664665 ;
665666
666 try testParse(.AMD64, source, "foo.dll", &[_]ModuleDefinition.Export{
667 const io = std.testing.io;
668
669 try testParse(io, .AMD64, source, "foo.dll", &[_]ModuleDefinition.Export{
667670 .{
668671 .name = "foo",
669672 .mangled_symbol_name = null,
......@@ -743,7 +746,7 @@ test parse {
743746 },
744747 });
745748
746 try testParse(.I386, source, "foo.dll", &[_]ModuleDefinition.Export{
749 try testParse(io, .I386, source, "foo.dll", &[_]ModuleDefinition.Export{
747750 .{
748751 .name = "_foo",
749752 .mangled_symbol_name = null,
......@@ -823,7 +826,7 @@ test parse {
823826 },
824827 });
825828
826 try testParse(.ARMNT, source, "foo.dll", &[_]ModuleDefinition.Export{
829 try testParse(io, .ARMNT, source, "foo.dll", &[_]ModuleDefinition.Export{
827830 .{
828831 .name = "foo",
829832 .mangled_symbol_name = null,
......@@ -903,7 +906,7 @@ test parse {
903906 },
904907 });
905908
906 try testParse(.ARM64, source, "foo.dll", &[_]ModuleDefinition.Export{
909 try testParse(io, .ARM64, source, "foo.dll", &[_]ModuleDefinition.Export{
907910 .{
908911 .name = "foo",
909912 .mangled_symbol_name = null,
......@@ -997,7 +1000,9 @@ test "ntdll" {
9971000 \\RtlActivateActivationContextUnsafeFast@0
9981001 ;
9991002
1000 try testParse(.AMD64, source, "ntdll.dll", &[_]ModuleDefinition.Export{
1003 const io = std.testing.io;
1004
1005 try testParse(io, .AMD64, source, "ntdll.dll", &[_]ModuleDefinition.Export{
10011006 .{
10021007 .name = "RtlDispatchAPC@12",
10031008 .mangled_symbol_name = null,
......@@ -1023,15 +1028,22 @@ test "ntdll" {
10231028 });
10241029}
10251030
1026fn testParse(machine_type: std.coff.IMAGE.FILE.MACHINE, source: [:0]const u8, expected_module_name: []const u8, expected_exports: []const ModuleDefinition.Export) !void {
1031fn testParse(
1032 io: Io,
1033 machine_type: std.coff.IMAGE.FILE.MACHINE,
1034 source: [:0]const u8,
1035 expected_module_name: []const u8,
1036 expected_exports: []const ModuleDefinition.Export,
1037) !void {
10271038 var diagnostics: Diagnostics = undefined;
10281039 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {
10291040 error.OutOfMemory => |e| return e,
10301041 error.ParseError => {
1031 const stderr, _ = std.debug.lockStderrWriter(&.{});
1032 defer std.debug.unlockStderrWriter();
1033 try diagnostics.writeMsg(stderr, source);
1034 try stderr.writeByte('\n');
1042 const stderr = try io.lockStderrWriter(&.{});
1043 defer io.unlockStderrWriter();
1044 const w = &stderr.interface;
1045 try diagnostics.writeMsg(w, source);
1046 try w.writeByte('\n');
10351047 return err;
10361048 },
10371049 };
src/link.zig+1-1
......@@ -2246,7 +2246,7 @@ fn resolvePathInputLib(
22462246 var error_bundle = try wip_errors.toOwnedBundle("");
22472247 defer error_bundle.deinit(gpa);
22482248
2249 error_bundle.renderToStdErr(.{}, color);
2249 error_bundle.renderToStderr(io, .{}, color);
22502250
22512251 std.process.exit(1);
22522252 }
src/link/Coff.zig+11-4
......@@ -4,6 +4,7 @@ const builtin = @import("builtin");
44const native_endian = builtin.cpu.arch.endian();
55
66const std = @import("std");
7const Io = std.Io;
78const assert = std.debug.assert;
89const log = std.log.scoped(.link);
910
......@@ -2377,10 +2378,16 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe
23772378 _ = name;
23782379}
23792380
2380pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) void {
2381 const w, _ = std.debug.lockStderrWriter(&.{});
2382 defer std.debug.unlockStderrWriter();
2383 coff.printNode(tid, w, .root, 0) catch {};
2381pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
2382 const comp = coff.base.comp;
2383 const io = comp.io;
2384 var buffer: [512]u8 = undefined;
2385 const stderr = try io.lockStderrWriter(&buffer);
2386 defer io.unlockStderrWriter();
2387 const w = &stderr.interface;
2388 coff.printNode(tid, w, .root, 0) catch |err| switch (err) {
2389 error.WriteFailed => return stderr.err.?,
2390 };
23842391}
23852392
23862393pub fn printNode(
src/link/Elf2.zig+10-4
......@@ -3729,10 +3729,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
37293729 _ = name;
37303730}
37313731
3732pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void {
3733 const w, _ = std.debug.lockStderrWriter(&.{});
3734 defer std.debug.unlockStderrWriter();
3735 elf.printNode(tid, w, .root, 0) catch {};
3732pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
3733 const comp = elf.base.comp;
3734 const io = comp.io;
3735 var buffer: [512]u8 = undefined;
3736 const stderr = try io.lockStderrWriter(&buffer);
3737 defer io.unlockStderrWriter();
3738 const w = &stderr.interface;
3739 elf.printNode(tid, w, .root, 0) catch |err| switch (err) {
3740 error.WriteFailed => return stderr.err.?,
3741 };
37363742}
37373743
37383744pub fn printNode(
src/main.zig+17-16
......@@ -4429,9 +4429,9 @@ fn runOrTest(
44294429 // the error message and invocation below.
44304430 if (process.can_execv and arg_mode == .run) {
44314431 // execv releases the locks; no need to destroy the Compilation here.
4432 _ = std.debug.lockStderrWriter(&.{});
4432 _ = try io.lockStderrWriter(&.{});
44334433 const err = process.execve(gpa, argv.items, &env_map);
4434 std.debug.unlockStderrWriter();
4434 io.unlockStderrWriter();
44354435 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc);
44364436 const cmd = try std.mem.join(arena, " ", argv.items);
44374437 fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd });
......@@ -4448,8 +4448,8 @@ fn runOrTest(
44484448 comp_destroyed.* = true;
44494449
44504450 const term_result = t: {
4451 _ = std.debug.lockStderrWriter();
4452 defer std.debug.unlockStderrWriter();
4451 _ = try io.lockStderrWriter(&.{});
4452 defer io.unlockStderrWriter();
44534453 break :t child.spawnAndWait(io);
44544454 };
44554455 const term = term_result catch |err| {
......@@ -4606,7 +4606,8 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)
46064606 defer errors.deinit(comp.gpa);
46074607
46084608 if (errors.errorMessageCount() > 0) {
4609 errors.renderToStdErr(.{}, color);
4609 const io = comp.io;
4610 errors.renderToStderr(io, .{}, color);
46104611 return error.CompileErrorsReported;
46114612 }
46124613}
......@@ -4659,7 +4660,7 @@ fn cmdTranslateC(
46594660 return;
46604661 } else {
46614662 const color: Color = .auto;
4662 result.errors.renderToStdErr(.{}, color);
4663 result.errors.renderToStderr(io, .{}, color);
46634664 process.exit(1);
46644665 }
46654666 }
......@@ -5280,7 +5281,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
52805281
52815282 if (fetch.error_bundle.root_list.items.len > 0) {
52825283 var errors = try fetch.error_bundle.toOwnedBundle("");
5283 errors.renderToStdErr(.{}, color);
5284 errors.renderToStderr(io, .{}, color);
52845285 process.exit(1);
52855286 }
52865287
......@@ -5412,8 +5413,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
54125413 child.stderr_behavior = .Inherit;
54135414
54145415 const term = t: {
5415 _ = std.debug.lockStderrWriter(&.{});
5416 defer std.debug.unlockStderrWriter();
5416 _ = try io.lockStderrWriter(&.{});
5417 defer io.unlockStderrWriter();
54175418 break :t child.spawnAndWait(io) catch |err|
54185419 fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err });
54195420 };
......@@ -6212,7 +6213,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
62126213 try wip_errors.init(arena);
62136214 try wip_errors.addZirErrorMessages(zir, tree, source, display_path);
62146215 var error_bundle = try wip_errors.toOwnedBundle("");
6215 error_bundle.renderToStdErr(.{}, color);
6216 error_bundle.renderToStderr(io, .{}, color);
62166217 if (zir.loweringFailed()) {
62176218 process.exit(1);
62186219 }
......@@ -6283,7 +6284,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
62836284 try wip_errors.init(arena);
62846285 try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);
62856286 var error_bundle = try wip_errors.toOwnedBundle("");
6286 error_bundle.renderToStdErr(.{}, color);
6287 error_bundle.renderToStderr(io, .{}, color);
62876288 process.exit(1);
62886289 }
62896290
......@@ -6557,7 +6558,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {
65576558 try wip_errors.init(arena);
65586559 try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path);
65596560 var error_bundle = try wip_errors.toOwnedBundle("");
6560 error_bundle.renderToStdErr(.{}, color);
6561 error_bundle.renderToStderr(io, .{}, color);
65616562 process.exit(1);
65626563 }
65636564
......@@ -6569,7 +6570,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {
65696570 try wip_errors.init(arena);
65706571 try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path);
65716572 var error_bundle = try wip_errors.toOwnedBundle("");
6572 error_bundle.renderToStdErr(.{}, color);
6573 error_bundle.renderToStderr(io, .{}, color);
65736574 process.exit(1);
65746575 }
65756576
......@@ -7005,7 +7006,7 @@ fn cmdFetch(
70057006
70067007 if (fetch.error_bundle.root_list.items.len > 0) {
70077008 var errors = try fetch.error_bundle.toOwnedBundle("");
7008 errors.renderToStdErr(.{}, color);
7009 errors.renderToStderr(io, .{}, color);
70097010 process.exit(1);
70107011 }
70117012
......@@ -7345,7 +7346,7 @@ fn loadManifest(
73457346 errdefer ast.deinit(gpa);
73467347
73477348 if (ast.errors.len > 0) {
7348 try std.zig.printAstErrorsToStderr(gpa, ast, Package.Manifest.basename, options.color);
7349 try std.zig.printAstErrorsToStderr(gpa, io, ast, Package.Manifest.basename, options.color);
73497350 process.exit(2);
73507351 }
73517352
......@@ -7362,7 +7363,7 @@ fn loadManifest(
73627363
73637364 var error_bundle = try wip_errors.toOwnedBundle("");
73647365 defer error_bundle.deinit(gpa);
7365 error_bundle.renderToStdErr(.{}, options.color);
7366 error_bundle.renderToStderr(io, .{}, options.color);
73667367
73677368 process.exit(2);
73687369 }