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 {...@@ -522,7 +522,7 @@ pub fn main() !void {
522 // Perhaps in the future there could be an Advanced Options flag522 // Perhaps in the future there could be an Advanced Options flag
523 // such as --debug-build-runner-leaks which would make this code523 // such as --debug-build-runner-leaks which would make this code
524 // return instead of calling exit.524 // return instead of calling exit.
525 _ = std.debug.lockStderrWriter(&.{});525 _ = io.lockStderrWriter(&.{}) catch {};
526 process.exit(1);526 process.exit(1);
527 },527 },
528 else => |e| return e,528 else => |e| return e,
...@@ -554,8 +554,8 @@ pub fn main() !void {...@@ -554,8 +554,8 @@ pub fn main() !void {
554 }554 }
555555
556 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {556 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {
557 const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation);557 const stderr = try io.lockStderrWriter(&stdio_buffer_allocation);
558 defer std.debug.unlockStderrWriter();558 defer io.unlockStderrWriter();
559 try stderr.writeAllUnescaped("\x1B[2J\x1B[3J\x1B[H");559 try stderr.writeAllUnescaped("\x1B[2J\x1B[3J\x1B[H");
560 }) {560 }) {
561 if (run.web_server) |*ws| ws.startBuild();561 if (run.web_server) |*ws| ws.startBuild();
...@@ -856,8 +856,8 @@ fn runStepNames(...@@ -856,8 +856,8 @@ fn runStepNames(
856 .none => break :summary,856 .none => break :summary,
857 }857 }
858858
859 const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation);859 const stderr = try io.lockStderrWriter(&stdio_buffer_allocation);
860 defer std.debug.unlockStderrWriter();860 defer io.unlockStderrWriter();
861861
862 const w = &stderr.interface;862 const w = &stderr.interface;
863 const fwm = stderr.mode;863 const fwm = stderr.mode;
...@@ -954,7 +954,7 @@ fn runStepNames(...@@ -954,7 +954,7 @@ fn runStepNames(
954 if (run.error_style.verboseContext()) break :code 1; // failure; print build command954 if (run.error_style.verboseContext()) break :code 1; // failure; print build command
955 break :code 2; // failure; do not print build command955 break :code 2; // failure; do not print build command
956 };956 };
957 _ = std.debug.lockStderrWriter(&.{});957 _ = io.lockStderrWriter(&.{}) catch {};
958 process.exit(code);958 process.exit(code);
959}959}
960960
...@@ -1369,8 +1369,10 @@ fn workerMakeOneStep(...@@ -1369,8 +1369,10 @@ fn workerMakeOneStep(
1369 const show_error_msgs = s.result_error_msgs.items.len > 0;1369 const show_error_msgs = s.result_error_msgs.items.len > 0;
1370 const show_stderr = s.result_stderr.len > 0;1370 const show_stderr = s.result_stderr.len > 0;
1371 if (show_error_msgs or show_compile_errors or show_stderr) {1371 if (show_error_msgs or show_compile_errors or show_stderr) {
1372 const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation);1372 const stderr = io.lockStderrWriter(&stdio_buffer_allocation) catch |err| switch (err) {
1373 defer std.debug.unlockStderrWriter();1373 error.Canceled => return,
1374 };
1375 defer io.unlockStderrWriter();
1374 printErrorMessages(gpa, s, .{}, &stderr.interface, stderr.mode, run.error_style, run.multiline_errors) catch {};1376 printErrorMessages(gpa, s, .{}, &stderr.interface, stderr.mode, run.error_style, run.multiline_errors) catch {};
1375 }1377 }
13761378
lib/compiler/resinator/cli.zig+4-4
...@@ -125,10 +125,10 @@ pub const Diagnostics = struct {...@@ -125,10 +125,10 @@ pub const Diagnostics = struct {
125 try self.errors.append(self.allocator, error_details);125 try self.errors.append(self.allocator, error_details);
126 }126 }
127127
128 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8) void {128 pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) void {
129 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});129 const stderr = io.lockStderrWriter(&.{});
130 defer std.debug.unlockStderrWriter();130 defer io.unlockStderrWriter();
131 self.renderToWriter(args, stderr, ttyconf) catch return;131 self.renderToWriter(args, &stderr.interface, stderr.mode) catch return;
132 }132 }
133133
134 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void {134 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 {...@@ -67,12 +67,12 @@ pub const Diagnostics = struct {
67 return @intCast(index);67 return @intCast(index);
68 }68 }
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 {
71 const io = self.io;71 const io = self.io;
72 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});72 const stderr = io.lockStderrWriter(&.{});
73 defer std.debug.unlockStderrWriter();73 defer io.unlockStderrWriter();
74 for (self.errors.items) |err_details| {74 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;
76 }76 }
77 }77 }
7878
lib/compiler/resinator/main.zig+51-47
...@@ -24,6 +24,10 @@ pub fn main() !void {...@@ -24,6 +24,10 @@ pub fn main() !void {
24 defer std.debug.assert(debug_allocator.deinit() == .ok);24 defer std.debug.assert(debug_allocator.deinit() == .ok);
25 const gpa = debug_allocator.allocator();25 const gpa = debug_allocator.allocator();
2626
27 var threaded: std.Io.Threaded = .init(gpa);
28 defer threaded.deinit();
29 const io = threaded.io();
30
27 var arena_state = std.heap.ArenaAllocator.init(gpa);31 var arena_state = std.heap.ArenaAllocator.init(gpa);
28 defer arena_state.deinit();32 defer arena_state.deinit();
29 const arena = arena_state.allocator();33 const arena = arena_state.allocator();
...@@ -31,8 +35,8 @@ pub fn main() !void {...@@ -31,8 +35,8 @@ pub fn main() !void {
31 const args = try std.process.argsAlloc(arena);35 const args = try std.process.argsAlloc(arena);
3236
33 if (args.len < 2) {37 if (args.len < 2) {
34 const w, const ttyconf = std.debug.lockStderrWriter(&.{});38 const stderr = io.lockStderrWriter(&.{});
35 try renderErrorMessage(w, ttyconf, .err, "expected zig lib dir as first argument", .{});39 try renderErrorMessage(&stderr.interface, stderr.mode, .err, "expected zig lib dir as first argument", .{});
36 std.process.exit(1);40 std.process.exit(1);
37 }41 }
38 const zig_lib_dir = args[1];42 const zig_lib_dir = args[1];
...@@ -45,7 +49,7 @@ pub fn main() !void {...@@ -45,7 +49,7 @@ pub fn main() !void {
45 }49 }
4650
47 var stdout_buffer: [1024]u8 = undefined;51 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);
49 const stdout = &stdout_writer.interface;53 const stdout = &stdout_writer.interface;
50 var error_handler: ErrorHandler = switch (zig_integration) {54 var error_handler: ErrorHandler = switch (zig_integration) {
51 true => .{55 true => .{
...@@ -71,24 +75,20 @@ pub fn main() !void {...@@ -71,24 +75,20 @@ pub fn main() !void {
7175
72 if (!zig_integration) {76 if (!zig_integration) {
73 // print any warnings/notes77 // print any warnings/notes
74 cli_diagnostics.renderToStdErr(cli_args);78 cli_diagnostics.renderToStderr(io, cli_args);
75 // If there was something printed, then add an extra newline separator79 // If there was something printed, then add an extra newline separator
76 // so that there is a clear separation between the cli diagnostics and whatever80 // so that there is a clear separation between the cli diagnostics and whatever
77 // gets printed after81 // gets printed after
78 if (cli_diagnostics.errors.items.len > 0) {82 if (cli_diagnostics.errors.items.len > 0) {
79 const stderr, _ = std.debug.lockStderrWriter(&.{});83 const stderr = io.lockStderrWriter(&.{});
80 defer std.debug.unlockStderrWriter();84 defer io.unlockStderrWriter();
81 try stderr.writeByte('\n');85 try stderr.interface.writeByte('\n');
82 }86 }
83 }87 }
84 break :options options;88 break :options options;
85 };89 };
86 defer options.deinit();90 defer options.deinit();
8791
88 var threaded: std.Io.Threaded = .init(gpa);
89 defer threaded.deinit();
90 const io = threaded.io();
91
92 if (options.print_help_and_exit) {92 if (options.print_help_and_exit) {
93 try cli.writeUsage(stdout, "zig rc");93 try cli.writeUsage(stdout, "zig rc");
94 try stdout.flush();94 try stdout.flush();
...@@ -130,10 +130,10 @@ pub fn main() !void {...@@ -130,10 +130,10 @@ pub fn main() !void {
130 var stderr_buf: [512]u8 = undefined;130 var stderr_buf: [512]u8 = undefined;
131 var diagnostics: aro.Diagnostics = .{ .output = output: {131 var diagnostics: aro.Diagnostics = .{ .output = output: {
132 if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } };132 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);
134 break :output .{ .to_writer = .{134 break :output .{ .to_writer = .{
135 .writer = w,135 .writer = &stderr.interface,
136 .color = ttyconf,136 .color = stderr.mode,
137 } };137 } };
138 } };138 } };
139 defer {139 defer {
...@@ -175,11 +175,11 @@ pub fn main() !void {...@@ -175,11 +175,11 @@ pub fn main() !void {
175 std.process.exit(1);175 std.process.exit(1);
176 },176 },
177 error.FileTooBig => {177 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", .{});
179 std.process.exit(1);179 std.process.exit(1);
180 },180 },
181 error.WriteFailed => {181 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", .{});
183 std.process.exit(1);183 std.process.exit(1);
184 },184 },
185 error.OutOfMemory => |e| return e,185 error.OutOfMemory => |e| return e,
...@@ -191,13 +191,13 @@ pub fn main() !void {...@@ -191,13 +191,13 @@ pub fn main() !void {
191 .stdio => |file| {191 .stdio => |file| {
192 var file_reader = file.reader(io, &.{});192 var file_reader = file.reader(io, &.{});
193 break :full_input file_reader.interface.allocRemaining(gpa, .unlimited) catch |err| {193 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)});
195 std.process.exit(1);195 std.process.exit(1);
196 };196 };
197 },197 },
198 .filename => |input_filename| {198 .filename => |input_filename| {
199 break :full_input Io.Dir.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| {199 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) });
201 std.process.exit(1);201 std.process.exit(1);
202 };202 };
203 },203 },
...@@ -228,12 +228,12 @@ pub fn main() !void {...@@ -228,12 +228,12 @@ pub fn main() !void {
228 }228 }
229 else if (options.input_format == .res)229 else if (options.input_format == .res)
230 IoStream.fromIoSource(options.input_source, .input) catch |err| {230 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) });
232 std.process.exit(1);232 std.process.exit(1);
233 }233 }
234 else234 else
235 IoStream.fromIoSource(options.output_source, .output) catch |err| {235 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) });
237 std.process.exit(1);237 std.process.exit(1);
238 };238 };
239 defer res_stream.deinit(gpa);239 defer res_stream.deinit(gpa);
...@@ -246,17 +246,17 @@ pub fn main() !void {...@@ -246,17 +246,17 @@ pub fn main() !void {
246 var mapping_results = parseAndRemoveLineCommands(gpa, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {246 var mapping_results = parseAndRemoveLineCommands(gpa, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {
247 error.InvalidLineCommand => {247 error.InvalidLineCommand => {
248 // TODO: Maybe output the invalid line command248 // 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", .{});
250 if (options.preprocess == .no) {250 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>\"", .{});
252 } else {252 } 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", .{});
254 }254 }
255 std.process.exit(1);255 std.process.exit(1);
256 },256 },
257 error.LineNumberOverflow => {257 error.LineNumberOverflow => {
258 // TODO: Better error message258 // 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)});
260 std.process.exit(1);260 std.process.exit(1);
261 },261 },
262 error.OutOfMemory => |e| return e,262 error.OutOfMemory => |e| return e,
...@@ -306,13 +306,13 @@ pub fn main() !void {...@@ -306,13 +306,13 @@ pub fn main() !void {
306306
307 // print any warnings/notes307 // print any warnings/notes
308 if (!zig_integration) {308 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);
310 }310 }
311311
312 // write the depfile312 // write the depfile
313 if (options.depfile_path) |depfile_path| {313 if (options.depfile_path) |depfile_path| {
314 var depfile = Io.Dir.cwd().createFile(io, depfile_path, .{}) catch |err| {314 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) });
316 std.process.exit(1);316 std.process.exit(1);
317 };317 };
318 defer depfile.close(io);318 defer depfile.close(io);
...@@ -340,7 +340,7 @@ pub fn main() !void {...@@ -340,7 +340,7 @@ pub fn main() !void {
340 if (options.output_format != .coff) return;340 if (options.output_format != .coff) return;
341341
342 break :res_data res_stream.source.readAll(gpa, io) catch |err| {342 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) });
344 std.process.exit(1);344 std.process.exit(1);
345 };345 };
346 };346 };
...@@ -353,14 +353,14 @@ pub fn main() !void {...@@ -353,14 +353,14 @@ pub fn main() !void {
353 var res_reader: std.Io.Reader = .fixed(res_data.bytes);353 var res_reader: std.Io.Reader = .fixed(res_data.bytes);
354 break :resources cvtres.parseRes(gpa, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {354 break :resources cvtres.parseRes(gpa, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {
355 // TODO: Better errors355 // 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) });
357 std.process.exit(1);357 std.process.exit(1);
358 };358 };
359 };359 };
360 defer resources.deinit();360 defer resources.deinit();
361361
362 var coff_stream = IoStream.fromIoSource(options.output_source, .output) catch |err| {362 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) });
364 std.process.exit(1);364 std.process.exit(1);
365 };365 };
366 defer coff_stream.deinit(gpa);366 defer coff_stream.deinit(gpa);
...@@ -373,7 +373,7 @@ pub fn main() !void {...@@ -373,7 +373,7 @@ pub fn main() !void {
373 switch (err) {373 switch (err) {
374 error.DuplicateResource => {374 error.DuplicateResource => {
375 const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];375 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}]", .{
377 duplicate_resource.name_value,377 duplicate_resource.name_value,
378 fmtResourceType(duplicate_resource.type_value),378 fmtResourceType(duplicate_resource.type_value),
379 duplicate_resource.language,379 duplicate_resource.language,
...@@ -381,8 +381,8 @@ pub fn main() !void {...@@ -381,8 +381,8 @@ pub fn main() !void {
381 },381 },
382 error.ResourceDataTooLong => {382 error.ResourceDataTooLong => {
383 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];383 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", .{});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, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{385 try error_handler.emitMessage(gpa, io, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
386 overflow_resource.name_value,386 overflow_resource.name_value,
387 fmtResourceType(overflow_resource.type_value),387 fmtResourceType(overflow_resource.type_value),
388 overflow_resource.language,388 overflow_resource.language,
...@@ -390,15 +390,15 @@ pub fn main() !void {...@@ -390,15 +390,15 @@ pub fn main() !void {
390 },390 },
391 error.TotalResourceDataTooLong => {391 error.TotalResourceDataTooLong => {
392 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];392 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", .{});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, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{394 try error_handler.emitMessage(gpa, io, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
395 overflow_resource.name_value,395 overflow_resource.name_value,
396 fmtResourceType(overflow_resource.type_value),396 fmtResourceType(overflow_resource.type_value),
397 overflow_resource.language,397 overflow_resource.language,
398 });398 });
399 },399 },
400 else => {400 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) });
402 },402 },
403 }403 }
404 // Delete the output file on error404 // Delete the output file on error
...@@ -550,16 +550,16 @@ const LazyIncludePaths = struct {...@@ -550,16 +550,16 @@ const LazyIncludePaths = struct {
550 else => |e| {550 else => |e| {
551 switch (e) {551 switch (e) {
552 error.UnsupportedAutoIncludesMachineType => {552 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)});
554 },554 },
555 error.MsvcIncludesNotFound => {555 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", .{});
557 },557 },
558 error.MingwIncludesNotFound => {558 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", .{});
560 },560 },
561 }561 }
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", .{});
563 std.process.exit(1);563 std.process.exit(1);
564 },564 },
565 };565 };
...@@ -664,6 +664,7 @@ const ErrorHandler = union(enum) {...@@ -664,6 +664,7 @@ const ErrorHandler = union(enum) {
664 pub fn emitCliDiagnostics(664 pub fn emitCliDiagnostics(
665 self: *ErrorHandler,665 self: *ErrorHandler,
666 allocator: Allocator,666 allocator: Allocator,
667 io: Io,
667 args: []const []const u8,668 args: []const []const u8,
668 diagnostics: *cli.Diagnostics,669 diagnostics: *cli.Diagnostics,
669 ) !void {670 ) !void {
...@@ -674,7 +675,7 @@ const ErrorHandler = union(enum) {...@@ -674,7 +675,7 @@ const ErrorHandler = union(enum) {
674675
675 try server.serveErrorBundle(error_bundle);676 try server.serveErrorBundle(error_bundle);
676 },677 },
677 .stderr => diagnostics.renderToStdErr(args),678 .stderr => diagnostics.renderToStderr(io, args),
678 }679 }
679 }680 }
680681
...@@ -684,6 +685,7 @@ const ErrorHandler = union(enum) {...@@ -684,6 +685,7 @@ const ErrorHandler = union(enum) {
684 fail_msg: []const u8,685 fail_msg: []const u8,
685 comp: *aro.Compilation,686 comp: *aro.Compilation,
686 ) !void {687 ) !void {
688 const io = comp.io;
687 switch (self.*) {689 switch (self.*) {
688 .server => |*server| {690 .server => |*server| {
689 var error_bundle = try compiler_util.aroDiagnosticsToErrorBundle(691 var error_bundle = try compiler_util.aroDiagnosticsToErrorBundle(
...@@ -697,9 +699,9 @@ const ErrorHandler = union(enum) {...@@ -697,9 +699,9 @@ const ErrorHandler = union(enum) {
697 },699 },
698 .stderr => {700 .stderr => {
699 // aro errors have already been emitted701 // aro errors have already been emitted
700 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});702 const stderr = io.lockStderrWriter(&.{});
701 defer std.debug.unlockStderrWriter();703 defer io.unlockStderrWriter();
702 try renderErrorMessage(stderr, ttyconf, .err, "{s}", .{fail_msg});704 try renderErrorMessage(&stderr.interface, stderr.mode, .err, "{s}", .{fail_msg});
703 },705 },
704 }706 }
705 }707 }
...@@ -707,6 +709,7 @@ const ErrorHandler = union(enum) {...@@ -707,6 +709,7 @@ const ErrorHandler = union(enum) {
707 pub fn emitDiagnostics(709 pub fn emitDiagnostics(
708 self: *ErrorHandler,710 self: *ErrorHandler,
709 allocator: Allocator,711 allocator: Allocator,
712 io: Io,
710 cwd: Io.Dir,713 cwd: Io.Dir,
711 source: []const u8,714 source: []const u8,
712 diagnostics: *Diagnostics,715 diagnostics: *Diagnostics,
...@@ -719,13 +722,14 @@ const ErrorHandler = union(enum) {...@@ -719,13 +722,14 @@ const ErrorHandler = union(enum) {
719722
720 try server.serveErrorBundle(error_bundle);723 try server.serveErrorBundle(error_bundle);
721 },724 },
722 .stderr => diagnostics.renderToStdErr(cwd, source, mappings),725 .stderr => diagnostics.renderToStderr(io, cwd, source, mappings),
723 }726 }
724 }727 }
725728
726 pub fn emitMessage(729 pub fn emitMessage(
727 self: *ErrorHandler,730 self: *ErrorHandler,
728 allocator: Allocator,731 allocator: Allocator,
732 io: Io,
729 msg_type: @import("utils.zig").ErrorMessageType,733 msg_type: @import("utils.zig").ErrorMessageType,
730 comptime format: []const u8,734 comptime format: []const u8,
731 args: anytype,735 args: anytype,
...@@ -741,9 +745,9 @@ const ErrorHandler = union(enum) {...@@ -741,9 +745,9 @@ const ErrorHandler = union(enum) {
741 try server.serveErrorBundle(error_bundle);745 try server.serveErrorBundle(error_bundle);
742 },746 },
743 .stderr => {747 .stderr => {
744 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});748 const stderr = io.lockStderrWriter(&.{});
745 defer std.debug.unlockStderrWriter();749 defer io.unlockStderrWriter();
746 try renderErrorMessage(stderr, ttyconf, msg_type, format, args);750 try renderErrorMessage(&stderr.interface, stderr.mode, msg_type, format, args);
747 },751 },
748 }752 }
749 }753 }
lib/compiler/std-docs.zig+1-1
...@@ -407,7 +407,7 @@ fn buildWasmBinary(...@@ -407,7 +407,7 @@ fn buildWasmBinary(
407 }407 }
408408
409 if (result_error_bundle.errorMessageCount() > 0) {409 if (result_error_bundle.errorMessageCount() > 0) {
410 result_error_bundle.renderToStdErr(.{}, true);410 result_error_bundle.renderToStderr(io, .{}, true);
411 std.log.err("the following command failed with {d} compilation errors:\n{s}", .{411 std.log.err("the following command failed with {d} compilation errors:\n{s}", .{
412 result_error_bundle.errorMessageCount(),412 result_error_bundle.errorMessageCount(),
413 try std.Build.Step.allocPrintCmd(arena, null, argv.items),413 try std.Build.Step.allocPrintCmd(arena, null, argv.items),
lib/compiler/test_runner.zig-3
...@@ -411,16 +411,13 @@ pub fn fuzz(...@@ -411,16 +411,13 @@ pub fn fuzz(
411 std.debug.writeStackTrace(trace, &stderr.interface, stderr.mode) catch break :p;411 std.debug.writeStackTrace(trace, &stderr.interface, stderr.mode) catch break :p;
412 }412 }
413 stderr.interface.print("failed with error.{t}\n", .{err}) catch break :p;413 stderr.interface.print("failed with error.{t}\n", .{err}) catch break :p;
414 stderr.interface.flush() catch break :p;
415 }414 }
416 stderr.interface.flush() catch {};
417 std.process.exit(1);415 std.process.exit(1);
418 },416 },
419 };417 };
420 if (log_err_count != 0) {418 if (log_err_count != 0) {
421 const stderr = std.debug.lockStderrWriter(&.{});419 const stderr = std.debug.lockStderrWriter(&.{});
422 stderr.interface.print("error logs detected\n", .{}) catch {};420 stderr.interface.print("error logs detected\n", .{}) catch {};
423 stderr.interface.flush() catch {};
424 std.process.exit(1);421 std.process.exit(1);
425 }422 }
426 }423 }
lib/std/Build.zig+23-8
...@@ -2238,7 +2238,7 @@ pub const GeneratedFile = struct {...@@ -2238,7 +2238,7 @@ pub const GeneratedFile = struct {
2238 /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.2238 /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
2239 path: ?[]const u8 = null,2239 path: ?[]const u8 = null,
22402240
2241 /// Deprecated, see `getPath2`.2241 /// Deprecated, see `getPath3`.
2242 pub fn getPath(gen: GeneratedFile) []const u8 {2242 pub fn getPath(gen: GeneratedFile) []const u8 {
2243 return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic(2243 return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic(
2244 "getPath() was called on a GeneratedFile that wasn't built yet. Is there a missing Step dependency on step '{s}'?",2244 "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 {...@@ -2246,11 +2246,18 @@ pub const GeneratedFile = struct {
2246 ));2246 ));
2247 }2247 }
22482248
2249 /// Deprecated, see `getPath3`.
2249 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {2250 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 {
2250 return gen.path orelse {2257 return gen.path orelse {
2251 const stderr = std.debug.lockStderrWriter(&.{});2258 const io = gen.step.owner.graph.io;
2259 const stderr = try io.lockStderrWriter(&.{});
2252 dumpBadGetPathHelp(gen.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};2260 dumpBadGetPathHelp(gen.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};
2253 std.debug.unlockStderrWriter();
2254 @panic("misconfigured build script");2261 @panic("misconfigured build script");
2255 };2262 };
2256 }2263 }
...@@ -2425,22 +2432,29 @@ pub const LazyPath = union(enum) {...@@ -2425,22 +2432,29 @@ pub const LazyPath = union(enum) {
2425 }2432 }
2426 }2433 }
24272434
2428 /// Deprecated, see `getPath3`.2435 /// Deprecated, see `getPath4`.
2429 pub fn getPath(lazy_path: LazyPath, src_builder: *Build) []const u8 {2436 pub fn getPath(lazy_path: LazyPath, src_builder: *Build) []const u8 {
2430 return getPath2(lazy_path, src_builder, null);2437 return getPath2(lazy_path, src_builder, null);
2431 }2438 }
24322439
2433 /// Deprecated, see `getPath3`.2440 /// Deprecated, see `getPath4`.
2434 pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {2441 pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
2435 const p = getPath3(lazy_path, src_builder, asking_step);2442 const p = getPath3(lazy_path, src_builder, asking_step);
2436 return src_builder.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path });2443 return src_builder.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path });
2437 }2444 }
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
2439 /// Intended to be used during the make phase only.2453 /// Intended to be used during the make phase only.
2440 ///2454 ///
2441 /// `asking_step` is only used for debugging purposes; it's the step being2455 /// `asking_step` is only used for debugging purposes; it's the step being
2442 /// run that is asking for the path.2456 /// 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 {
2444 switch (lazy_path) {2458 switch (lazy_path) {
2445 .src_path => |sp| return .{2459 .src_path => |sp| return .{
2446 .root_dir = sp.owner.build_root,2460 .root_dir = sp.owner.build_root,
...@@ -2457,9 +2471,10 @@ pub const LazyPath = union(enum) {...@@ -2457,9 +2471,10 @@ pub const LazyPath = union(enum) {
2457 var file_path: Cache.Path = .{2471 var file_path: Cache.Path = .{
2458 .root_dir = Cache.Directory.cwd(),2472 .root_dir = Cache.Directory.cwd(),
2459 .sub_path = gen.file.path orelse {2473 .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(&.{});
2461 dumpBadGetPathHelp(gen.file.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};2476 dumpBadGetPathHelp(gen.file.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};
2462 std.debug.unlockStderrWriter();2477 io.unlockStderrWriter();
2463 @panic("misconfigured build script");2478 @panic("misconfigured build script");
2464 },2479 },
2465 };2480 };
lib/std/Build/Fuzz.zig+11-10
...@@ -158,6 +158,7 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.P...@@ -158,6 +158,7 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.P
158}158}
159159
160fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void {160fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void {
161 const io = run.step.owner.graph.io;
161 const compile = run.producer.?;162 const compile = run.producer.?;
162 const prog_node = parent_prog_node.start(compile.step.name, 0);163 const prog_node = parent_prog_node.start(compile.step.name, 0);
163 defer prog_node.end();164 defer prog_node.end();
...@@ -170,8 +171,8 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod...@@ -170,8 +171,8 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
170171
171 if (show_error_msgs or show_compile_errors or show_stderr) {172 if (show_error_msgs or show_compile_errors or show_stderr) {
172 var buf: [256]u8 = undefined;173 var buf: [256]u8 = undefined;
173 const stderr = std.debug.lockStderrWriter(&buf);174 const stderr = try io.lockStderrWriter(&buf);
174 defer std.debug.unlockStderrWriter();175 defer io.unlockStderrWriter();
175 build_runner.printErrorMessages(gpa, &compile.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};176 build_runner.printErrorMessages(gpa, &compile.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};
176 }177 }
177178
...@@ -182,12 +183,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod...@@ -182,12 +183,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
182 run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename);183 run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename);
183}184}
184185
185fn fuzzWorkerRun(186fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void {
186 fuzz: *Fuzz,187 const owner = run.step.owner;
187 run: *Step.Run,188 const gpa = owner.allocator;
188 unit_test_index: u32,189 const io = owner.graph.io;
189) void {
190 const gpa = run.step.owner.allocator;
191 const test_name = run.cached_test_metadata.?.testName(unit_test_index);190 const test_name = run.cached_test_metadata.?.testName(unit_test_index);
192191
193 const prog_node = fuzz.prog_node.start(test_name, 0);192 const prog_node = fuzz.prog_node.start(test_name, 0);
...@@ -196,8 +195,10 @@ fn fuzzWorkerRun(...@@ -196,8 +195,10 @@ fn fuzzWorkerRun(
196 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {195 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {
197 error.MakeFailed => {196 error.MakeFailed => {
198 var buf: [256]u8 = undefined;197 var buf: [256]u8 = undefined;
199 const stderr = std.debug.lockStderrWriter(&buf);198 const stderr = io.lockStderrWriter(&buf) catch |e| switch (e) {
200 defer std.debug.unlockStderrWriter();199 error.Canceled => return,
200 };
201 defer io.unlockStderrWriter();
201 build_runner.printErrorMessages(gpa, &run.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};202 build_runner.printErrorMessages(gpa, &run.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};
202 return;203 return;
203 },204 },
lib/std/Build/Step/Compile.zig+10-7
...@@ -922,20 +922,23 @@ const CliNamedModules = struct {...@@ -922,20 +922,23 @@ const CliNamedModules = struct {
922 }922 }
923};923};
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;
926 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);929 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
927930
928 const generated_file = maybe_path orelse {931 const generated_file = maybe_path orelse {
929 const stderr = std.debug.lockStderrWriter(&.{});932 const stderr = try io.lockStderrWriter(&.{});
930 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};933 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};
931 std.debug.unlockStderrWriter();934 io.unlockStderrWriter();
932 @panic("missing emit option for " ++ tag_name);935 @panic("missing emit option for " ++ tag_name);
933 };936 };
934937
935 const path = generated_file.path orelse {938 const path = generated_file.path orelse {
936 const stderr = std.debug.lockStderrWriter(&.{});939 const stderr = try io.lockStderrWriter(&.{});
937 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};940 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};
938 std.debug.unlockStderrWriter();941 io.unlockStderrWriter();
939 @panic(tag_name ++ " is null. Is there a missing step dependency?");942 @panic(tag_name ++ " is null. Is there a missing step dependency?");
940 };943 };
941944
...@@ -1149,9 +1152,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1149,9 +1152,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1149 // For everything else, we directly link1152 // For everything else, we directly link
1150 // against the library file.1153 // against the library file.
1151 const full_path_lib = if (other_produces_implib)1154 const full_path_lib = if (other_produces_implib)
1152 other.getGeneratedFilePath("generated_implib", &compile.step)1155 try other.getGeneratedFilePath("generated_implib", &compile.step)
1153 else1156 else
1154 other.getGeneratedFilePath("generated_bin", &compile.step);1157 try other.getGeneratedFilePath("generated_bin", &compile.step);
11551158
1156 try zig_args.append(full_path_lib);1159 try zig_args.append(full_path_lib);
1157 total_linker_objects += 1;1160 total_linker_objects += 1;
lib/std/Build/Step/Run.zig+3-2
...@@ -1559,6 +1559,7 @@ fn spawnChildAndCollect(...@@ -1559,6 +1559,7 @@ fn spawnChildAndCollect(
1559) !?EvalGenericResult {1559) !?EvalGenericResult {
1560 const b = run.step.owner;1560 const b = run.step.owner;
1561 const arena = b.allocator;1561 const arena = b.allocator;
1562 const io = b.graph.io;
15621563
1563 if (fuzz_context != null) {1564 if (fuzz_context != null) {
1564 assert(!has_side_effects);1565 assert(!has_side_effects);
...@@ -1625,10 +1626,10 @@ fn spawnChildAndCollect(...@@ -1625,10 +1626,10 @@ fn spawnChildAndCollect(
1625 child.progress_node = options.progress_node;1626 child.progress_node = options.progress_node;
1626 }1627 }
1627 if (inherit) {1628 if (inherit) {
1628 const stderr = std.debug.lockStderrWriter(&.{});1629 const stderr = try io.lockStderrWriter(&.{});
1629 try setColorEnvironmentVariables(run, env_map, stderr.mode);1630 try setColorEnvironmentVariables(run, env_map, stderr.mode);
1630 }1631 }
1631 defer if (inherit) std.debug.unlockStderrWriter();1632 defer if (inherit) io.unlockStderrWriter();
1632 var timer = try std.time.Timer.start();1633 var timer = try std.time.Timer.start();
1633 const res = try evalGeneric(run, &child);1634 const res = try evalGeneric(run, &child);
1634 run.step.result_duration_ns = timer.read();1635 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...@@ -655,7 +655,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
655 }655 }
656656
657 if (result_error_bundle.errorMessageCount() > 0) {657 if (result_error_bundle.errorMessageCount() > 0) {
658 result_error_bundle.renderToStdErr(.{}, .auto);658 try result_error_bundle.renderToStderr(io, .{}, .auto);
659 log.err("the following command failed with {d} compilation errors:\n{s}", .{659 log.err("the following command failed with {d} compilation errors:\n{s}", .{
660 result_error_bundle.errorMessageCount(),660 result_error_bundle.errorMessageCount(),
661 try Build.Step.allocPrintCmd(arena, null, argv.items),661 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 {...@@ -764,7 +764,7 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {
764 }764 }
765}765}
766766
767pub fn clearWrittenWithEscapeCodes(file_writer: *Io.File.Writer) anyerror!void {767pub fn clearWrittenWithEscapeCodes(file_writer: *Io.File.Writer) Io.Writer.Error!void {
768 if (noop_impl or !global_progress.need_clear) return;768 if (noop_impl or !global_progress.need_clear) return;
769 try file_writer.writeAllUnescaped(clear ++ progress_remove);769 try file_writer.writeAllUnescaped(clear ++ progress_remove);
770 global_progress.need_clear = false;770 global_progress.need_clear = false;
lib/std/json/dynamic.zig+2-3
...@@ -47,10 +47,9 @@ pub const Value = union(enum) {...@@ -47,10 +47,9 @@ pub const Value = union(enum) {
47 }47 }
4848
49 pub fn dump(v: Value) void {49 pub fn dump(v: Value) void {
50 const w, _ = std.debug.lockStderrWriter(&.{});50 const stderr = std.debug.lockStderrWriter(&.{});
51 defer std.debug.unlockStderrWriter();51 defer std.debug.unlockStderrWriter();
5252 json.Stringify.value(v, .{}, &stderr.interface) catch return;
53 json.Stringify.value(v, .{}, w) catch return;
54 }53 }
5554
56 pub fn jsonStringify(value: @This(), jws: anytype) !void {55 pub fn jsonStringify(value: @This(), jws: anytype) !void {
lib/std/process.zig+1-1
...@@ -1849,7 +1849,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {...@@ -1849,7 +1849,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
1849/// and does not return.1849/// and does not return.
1850pub fn cleanExit(io: Io) void {1850pub fn cleanExit(io: Io) void {
1851 if (builtin.mode == .Debug) return;1851 if (builtin.mode == .Debug) return;
1852 _ = io.lockStderrWriter(&.{});1852 _ = io.lockStderrWriter(&.{}) catch {};
1853 exit(0);1853 exit(0);
1854}1854}
18551855
lib/std/testing.zig+12-4
...@@ -368,13 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -368,13 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
368 break :diff_index if (expected.len == actual.len) return else shortest;368 break :diff_index if (expected.len == actual.len) return else shortest;
369 };369 };
370 if (!backend_can_print) return error.TestExpectedEqual;370 if (!backend_can_print) return error.TestExpectedEqual;
371 const stderr = std.debug.lockStderrWriter(&.{});371 if (io.lockStderrWriter(&.{})) |stderr| {
372 defer std.debug.unlockStderrWriter();372 defer io.unlockStderrWriter();
373 failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {};373 failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {};
374 } else |_| {}
374 return error.TestExpectedEqual;375 return error.TestExpectedEqual;
375}376}
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 {
378 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });386 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });
379387
380 // TODO: Should this be configurable by the caller?388 // 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) ![...@@ -639,7 +639,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *Io.File.Reader) ![
639 return buffer.toOwnedSliceSentinel(gpa, 0);639 return buffer.toOwnedSliceSentinel(gpa, 0);
640}640}
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 {
643 var wip_errors: std.zig.ErrorBundle.Wip = undefined;643 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
644 try wip_errors.init(gpa);644 try wip_errors.init(gpa);
645 defer wip_errors.deinit();645 defer wip_errors.deinit();
...@@ -648,7 +648,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color...@@ -648,7 +648,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color
648648
649 var error_bundle = try wip_errors.toOwnedBundle("");649 var error_bundle = try wip_errors.toOwnedBundle("");
650 defer error_bundle.deinit(gpa);650 defer error_bundle.deinit(gpa);
651 error_bundle.renderToStdErr(.{}, color);651 error_bundle.renderToStderr(io, .{}, color);
652}652}
653653
654pub fn putAstErrorsIntoBundle(654pub fn putAstErrorsIntoBundle(
lib/std/zig/ErrorBundle.zig+6-4
...@@ -162,11 +162,13 @@ pub const RenderOptions = struct {...@@ -162,11 +162,13 @@ pub const RenderOptions = struct {
162 include_log_text: bool = true,162 include_log_text: bool = true,
163};163};
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 {
166 var buffer: [256]u8 = undefined;168 var buffer: [256]u8 = undefined;
167 const stderr = std.debug.lockStderrWriter(&buffer);169 const stderr = try io.lockStderrWriter(&buffer);
168 defer std.debug.unlockStderrWriter();170 defer io.unlockStderrWriter();
169 renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode)) catch return;171 try renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode));
170}172}
171173
172pub fn renderToWriter(174pub fn renderToWriter(
lib/std/zig/parser_test.zig+19-11
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;2const Io = std.Io;
3const print = std.debug.print;3const Allocator = std.mem.Allocator;
4const maxInt = std.math.maxInt;
54
6test "zig fmt: remove extra whitespace at start and end of file with comment between" {5test "zig fmt: remove extra whitespace at start and end of file with comment between" {
7 try testTransform(6 try testTransform(
...@@ -6332,10 +6331,10 @@ test "ampersand" {...@@ -6332,10 +6331,10 @@ test "ampersand" {
63326331
6333var fixed_buffer_mem: [100 * 1024]u8 = undefined;6332var 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 {
6336 var buffer: [64]u8 = undefined;6335 var buffer: [64]u8 = undefined;
6337 const stderr = std.debug.lockStderrWriter(&buffer);6336 const stderr = try io.lockStderrWriter(&buffer);
6338 defer std.debug.unlockStderrWriter();6337 defer io.unlockStderrWriter();
63396338
6340 var tree = try std.zig.Ast.parse(allocator, source, .zig);6339 var tree = try std.zig.Ast.parse(allocator, source, .zig);
6341 defer tree.deinit(allocator);6340 defer tree.deinit(allocator);
...@@ -6359,27 +6358,36 @@ fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *...@@ -6359,27 +6358,36 @@ fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *
6359 }6358 }
63606359
6361 const formatted = try tree.renderAlloc(allocator);6360 const formatted = try tree.renderAlloc(allocator);
6362 anything_changed.* = !mem.eql(u8, formatted, source);6361 anything_changed.* = !std.mem.eql(u8, formatted, source);
6363 return formatted;6362 return formatted;
6364}6363}
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 {
6366 // reset the fixed buffer allocator each run so that it can be re-used for each6371 // reset the fixed buffer allocator each run so that it can be re-used for each
6367 // iteration of the failing index6372 // iteration of the failing index
6368 fba.reset();6373 fba.reset();
6369 var anything_changed: bool = undefined;6374 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);
6371 try std.testing.expectEqualStrings(expected_source, result_source);6376 try std.testing.expectEqualStrings(expected_source, result_source);
6372 const changes_expected = source.ptr != expected_source.ptr;6377 const changes_expected = source.ptr != expected_source.ptr;
6373 if (anything_changed != changes_expected) {6378 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 });
6375 return error.TestFailed;6380 return error.TestFailed;
6376 }6381 }
6377 try std.testing.expect(anything_changed == changes_expected);6382 try std.testing.expect(anything_changed == changes_expected);
6378 allocator.free(result_source);6383 allocator.free(result_source);
6379}6384}
6380fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {6385fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {
6386 const io = std.testing.io;
6381 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);6387 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 });
6383}6391}
6384fn testCanonical(source: [:0]const u8) !void {6392fn testCanonical(source: [:0]const u8) !void {
6385 return testTransform(source, source);6393 return testTransform(source, source);
src/Air/print.zig+18-10
...@@ -9,7 +9,7 @@ const Type = @import("../Type.zig");...@@ -9,7 +9,7 @@ const Type = @import("../Type.zig");
9const Air = @import("../Air.zig");9const Air = @import("../Air.zig");
10const InternPool = @import("../InternPool.zig");10const 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 {
13 comptime assert(build_options.enable_debug_extensions);13 comptime assert(build_options.enable_debug_extensions);
14 const instruction_bytes = air.instructions.len *14 const instruction_bytes = air.instructions.len *
15 // Here we don't use @sizeOf(Air.Inst.Data) because it would include15 // 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...@@ -24,7 +24,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
24 liveness_special_bytes + tomb_bytes;24 liveness_special_bytes + tomb_bytes;
2525
26 // zig fmt: off26 // zig fmt: off
27 stream.print(27 try stream.print(
28 \\# Total AIR+Liveness bytes: {Bi}28 \\# Total AIR+Liveness bytes: {Bi}
29 \\# AIR Instructions: {d} ({Bi})29 \\# AIR Instructions: {d} ({Bi})
30 \\# AIR Extra Data: {d} ({Bi})30 \\# AIR Extra Data: {d} ({Bi})
...@@ -39,7 +39,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air...@@ -39,7 +39,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
39 tomb_bytes,39 tomb_bytes,
40 if (liveness) |l| l.extra.len else 0, liveness_extra_bytes,40 if (liveness) |l| l.extra.len else 0, liveness_extra_bytes,
41 if (liveness) |l| l.special.count() else 0, liveness_special_bytes,41 if (liveness) |l| l.special.count() else 0, liveness_special_bytes,
42 }) catch return;42 });
43 // zig fmt: on43 // zig fmt: on
4444
45 var writer: Writer = .{45 var writer: Writer = .{
...@@ -50,7 +50,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air...@@ -50,7 +50,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
50 .indent = 2,50 .indent = 2,
51 .skip_body = false,51 .skip_body = false,
52 };52 };
53 writer.writeBody(stream, air.getMainBody()) catch return;53 try writer.writeBody(stream, air.getMainBody());
54}54}
5555
56pub fn writeInst(56pub fn writeInst(
...@@ -73,15 +73,23 @@ pub fn writeInst(...@@ -73,15 +73,23 @@ pub fn writeInst(
73}73}
7474
75pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {75pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
76 const stderr_bw, _ = std.debug.lockStderrWriter(&.{});76 const comp = pt.zcu.comp;
77 defer std.debug.unlockStderrWriter();77 const io = comp.io;
78 air.write(stderr_bw, pt, liveness);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);
79}83}
8084
81pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {85pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
82 const stderr_bw, _ = std.debug.lockStderrWriter(&.{});86 const comp = pt.zcu.comp;
83 defer std.debug.unlockStderrWriter();87 const io = comp.io;
84 air.writeInst(stderr_bw, inst, pt, liveness);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);
85}93}
8694
87const Writer = struct {95const Writer = struct {
src/Compilation.zig+30-23
...@@ -2088,12 +2088,13 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2088,12 +2088,13 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
20882088
2089 if (options.verbose_llvm_cpu_features) {2089 if (options.verbose_llvm_cpu_features) {
2090 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {2090 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
2091 const stderr_w, _ = std.debug.lockStderrWriter(&.{});2091 const stderr = try io.lockStderrWriter(&.{});
2092 defer std.debug.unlockStderrWriter();2092 defer io.unlockStderrWriter();
2093 stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;2093 const w = &stderr.interface;
2094 stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;2094 w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
2095 stderr_w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;2095 w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
2096 stderr_w.print(" features: {s}\n", .{cf}) catch {};2096 w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
2097 w.print(" features: {s}\n", .{cf}) catch {};
2097 }2098 }
2098 }2099 }
20992100
...@@ -4257,12 +4258,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4257,12 +4258,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
4257 // However, we haven't reported any such error.4258 // However, we haven't reported any such error.
4258 // This is a compiler bug.4259 // This is a compiler bug.
4259 print_ctx: {4260 print_ctx: {
4260 var stderr_w, _ = std.debug.lockStderrWriter(&.{});4261 const stderr = try io.lockStderrWriter(&.{});
4261 defer std.debug.unlockStderrWriter();4262 defer io.unlockStderrWriter();
4262 stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;4263 const w = &stderr.interface;
4263 stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;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;
4264 while (ref) |r| {4266 while (ref) |r| {
4265 stderr_w.print("referenced by: {f}{s}\n", .{4267 w.print("referenced by: {f}{s}\n", .{
4266 zcu.fmtAnalUnit(r.referencer),4268 zcu.fmtAnalUnit(r.referencer),
4267 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",4269 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
4268 }) catch break :print_ctx;4270 }) catch break :print_ctx;
...@@ -5756,7 +5758,7 @@ pub fn translateC(...@@ -5756,7 +5758,7 @@ pub fn translateC(
5756 try argv.appendSlice(comp.global_cc_argv);5758 try argv.appendSlice(comp.global_cc_argv);
5757 try argv.appendSlice(owner_mod.cc_argv);5759 try argv.appendSlice(owner_mod.cc_argv);
5758 try argv.appendSlice(&.{ source_path, "-o", translated_path });5760 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);
5760 }5762 }
57615763
5762 var stdout: []u8 = undefined;5764 var stdout: []u8 = undefined;
...@@ -6264,7 +6266,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -6264,7 +6266,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
6264 }6266 }
62656267
6266 if (comp.verbose_cc) {6268 if (comp.verbose_cc) {
6267 dump_argv(argv.items);6269 dumpArgv(io, argv.items);
6268 }6270 }
62696271
6270 const err = std.process.execv(arena, argv.items);6272 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...@@ -6310,7 +6312,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
6310 }6312 }
63116313
6312 if (comp.verbose_cc) {6314 if (comp.verbose_cc) {
6313 dump_argv(argv.items);6315 dumpArgv(io, argv.items);
6314 }6316 }
63156317
6316 // Just to save disk space, we delete the files that are never needed again.6318 // Just to save disk space, we delete the files that are never needed again.
...@@ -7773,17 +7775,22 @@ pub fn lockAndSetMiscFailure(...@@ -7773,17 +7775,22 @@ pub fn lockAndSetMiscFailure(
7773 return setMiscFailure(comp, tag, format, args);7775 return setMiscFailure(comp, tag, format, args);
7774}7776}
77757777
7776pub fn dump_argv(argv: []const []const u8) void {7778pub fn dumpArgv(io: Io, argv: []const []const u8) Io.Cancelable!void {
7777 var buffer: [64]u8 = undefined;7779 var buffer: [64]u8 = undefined;
7778 const stderr, _ = std.debug.lockStderrWriter(&buffer);7780 const stderr = try io.lockStderrWriter(&buffer);
7779 defer std.debug.unlockStderrWriter();7781 defer io.unlockStderrWriter();
7780 nosuspend {7782 const w = &stderr.interface;
7781 for (argv, 0..) |arg, i| {7783 return dumpArgvWriter(w, argv) catch |err| switch (err) {
7782 if (i != 0) stderr.writeByte(' ') catch return;7784 error.WriteFailed => return stderr.err.?,
7783 stderr.writeAll(arg) catch return;7785 };
7784 }7786}
7785 stderr.writeByte('\n') catch return;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);
7786 }7792 }
7793 try w.writeByte('\n');
7787}7794}
77887795
7789pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {7796pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
src/InternPool.zig+32-31
...@@ -1,8 +1,11 @@...@@ -1,8 +1,11 @@
1//! All interned objects have both a value and a type.1//! All interned objects have both a value and a type.
2//! This data structure is self-contained.2//! This data structure is self-contained.
3const InternPool = @This();
34
4const builtin = @import("builtin");5const builtin = @import("builtin");
6
5const std = @import("std");7const std = @import("std");
8const Io = std.Io;
6const Allocator = std.mem.Allocator;9const Allocator = std.mem.Allocator;
7const assert = std.debug.assert;10const assert = std.debug.assert;
8const BigIntConst = std.math.big.int.Const;11const BigIntConst = std.math.big.int.Const;
...@@ -11,10 +14,9 @@ const Cache = std.Build.Cache;...@@ -11,10 +14,9 @@ const Cache = std.Build.Cache;
11const Io = std.Io;14const Io = std.Io;
12const Limb = std.math.big.Limb;15const Limb = std.math.big.Limb;
13const Hash = std.hash.Wyhash;16const Hash = std.hash.Wyhash;
17const Zir = std.zig.Zir;
1418
15const InternPool = @This();
16const Zcu = @import("Zcu.zig");19const Zcu = @import("Zcu.zig");
17const Zir = std.zig.Zir;
1820
19/// One item per thread, indexed by `tid`, which is dense and unique per thread.21/// One item per thread, indexed by `tid`, which is dense and unique per thread.
20locals: []Local,22locals: []Local,
...@@ -11165,12 +11167,16 @@ pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) v...@@ -11165,12 +11167,16 @@ pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) v
11165 @atomicStore(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.Variable, "init").?], @intFromEnum(init_index), .release);11167 @atomicStore(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.Variable, "init").?], @intFromEnum(init_index), .release);
11166}11168}
1116711169
11168pub fn dump(ip: *const InternPool) void {11170pub fn dump(ip: *const InternPool, io: Io) Io.Cancelable!void {
11169 dumpStatsFallible(ip, std.heap.page_allocator) catch return;11171 var buffer: [4096]u8 = undefined;
11170 dumpAllFallible(ip) catch return;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);
11171}11177}
1117211178
11173fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {11179fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) anyerror!void {
11174 var items_len: usize = 0;11180 var items_len: usize = 0;
11175 var extra_len: usize = 0;11181 var extra_len: usize = 0;
11176 var limbs_len: usize = 0;11182 var limbs_len: usize = 0;
...@@ -11423,18 +11429,13 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -11423,18 +11429,13 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
11423 };11429 };
11424 counts.sort(SortContext{ .map = &counts });11430 counts.sort(SortContext{ .map = &counts });
11425 const len = @min(50, counts.count());11431 const len = @min(50, counts.count());
11426 std.debug.print(" top 50 tags:\n", .{});11432 w.print(" top 50 tags:\n", .{});
11427 for (counts.keys()[0..len], counts.values()[0..len]) |tag, stats| {11433 for (counts.keys()[0..len], counts.values()[0..len]) |tag, stats| {
11428 std.debug.print(" {s}: {d} occurrences, {d} total bytes\n", .{11434 w.print(" {t}: {d} occurrences, {d} total bytes\n", .{ tag, stats.count, stats.bytes });
11429 @tagName(tag), stats.count, stats.bytes,
11430 });
11431 }11435 }
11432}11436}
1143311437
11434fn dumpAllFallible(ip: *const InternPool) anyerror!void {11438fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
11435 var buffer: [4096]u8 = undefined;
11436 const stderr_bw, _ = std.debug.lockStderrWriter(&buffer);
11437 defer std.debug.unlockStderrWriter();
11438 for (ip.locals, 0..) |*local, tid| {11439 for (ip.locals, 0..) |*local, tid| {
11439 const items = local.shared.items.view();11440 const items = local.shared.items.view();
11440 for (11441 for (
...@@ -11443,12 +11444,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -11443,12 +11444,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11443 0..,11444 0..,
11444 ) |tag, data, index| {11445 ) |tag, data, index| {
11445 const i = Index.Unwrapped.wrap(.{ .tid = @enumFromInt(tid), .index = @intCast(index) }, ip);11446 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) });
11447 switch (tag) {11448 switch (tag) {
11448 .removed => {},11449 .removed => {},
1144911450
11450 .simple_type => try stderr_bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),11451 .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),
11451 .simple_value => try stderr_bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),11452 .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),
1145211453
11453 .type_int_signed,11454 .type_int_signed,
11454 .type_int_unsigned,11455 .type_int_unsigned,
...@@ -11521,23 +11522,27 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -11521,23 +11522,27 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11521 .func_coerced,11522 .func_coerced,
11522 .union_value,11523 .union_value,
11523 .memoized_call,11524 .memoized_call,
11524 => try stderr_bw.print("{d}", .{data}),11525 => try w.print("{d}", .{data}),
1152511526
11526 .opt_null,11527 .opt_null,
11527 .type_slice,11528 .type_slice,
11528 .only_possible_value,11529 .only_possible_value,
11529 => try stderr_bw.print("${d}", .{data}),11530 => try w.print("${d}", .{data}),
11530 }11531 }
11531 try stderr_bw.writeAll(")\n");11532 try w.writeAll(")\n");
11532 }11533 }
11533 }11534 }
11534}11535}
1153511536
11536pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {11537pub fn dumpGenericInstances(ip: *const InternPool, io: Io, allocator: Allocator) Io.Cancelable!void {
11537 ip.dumpGenericInstancesFallible(allocator) catch return;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);
11538}11543}
1153911544
11540pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) anyerror!void {11545pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, w: *Io.Writer) !void {
11541 var arena_allocator = std.heap.ArenaAllocator.init(allocator);11546 var arena_allocator = std.heap.ArenaAllocator.init(allocator);
11542 defer arena_allocator.deinit();11547 defer arena_allocator.deinit();
11543 const arena = arena_allocator.allocator();11548 const arena = arena_allocator.allocator();
...@@ -11564,10 +11569,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11564,10 +11569,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11564 }11569 }
11565 }11570 }
1156611571
11567 var buffer: [4096]u8 = undefined;
11568 const stderr_bw, _ = std.debug.lockStderrWriter(&buffer);
11569 defer std.debug.unlockStderrWriter();
11570
11571 const SortContext = struct {11572 const SortContext = struct {
11572 values: []std.ArrayList(Index),11573 values: []std.ArrayList(Index),
11573 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {11574 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
...@@ -11579,19 +11580,19 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11579,19 +11580,19 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11579 var it = instances.iterator();11580 var it = instances.iterator();
11580 while (it.next()) |entry| {11581 while (it.next()) |entry| {
11581 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);11582 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 });
11583 for (entry.value_ptr.items) |index| {11584 for (entry.value_ptr.items) |index| {
11584 const unwrapped_index = index.unwrap(ip);11585 const unwrapped_index = index.unwrap(ip);
11585 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));11586 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));
11586 const owner_nav = ip.getNav(func.owner_nav);11587 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)});
11588 for (func.comptime_args.get(ip)) |arg| {11589 for (func.comptime_args.get(ip)) |arg| {
11589 if (arg != .none) {11590 if (arg != .none) {
11590 const key = ip.indexToKey(arg);11591 const key = ip.indexToKey(arg);
11591 try stderr_bw.print(" {} ", .{key});11592 try w.print(" {} ", .{key});
11592 }11593 }
11593 }11594 }
11594 try stderr_bw.writeAll(")\n");11595 try w.writeAll(")\n");
11595 }11596 }
11596 }11597 }
11597}11598}
src/Sema.zig+5-3
...@@ -2668,16 +2668,18 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T...@@ -2668,16 +2668,18 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T
26682668
2669pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } {2669pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } {
2670 @branchHint(.cold);2670 @branchHint(.cold);
2671 const gpa = sema.gpa;
2672 const zcu = sema.pt.zcu;2671 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) {
2675 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2677 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
2676 wip_errors.init(gpa) catch @panic("out of memory");2678 wip_errors.init(gpa) catch @panic("out of memory");
2677 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory");2679 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory");
2678 std.debug.print("compile error during Sema:\n", .{});2680 std.debug.print("compile error during Sema:\n", .{});
2679 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");2681 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");
2680 error_bundle.renderToStdErr(.{}, .auto);2682 error_bundle.renderToStderr(io, .{}, .auto);
2681 std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{});2683 std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{});
2682 }2684 }
26832685
src/Zcu/PerThread.zig+3-2
...@@ -4556,8 +4556,9 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4556,8 +4556,9 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4556 defer if (liveness) |*l| l.deinit(gpa);4556 defer if (liveness) |*l| l.deinit(gpa);
45574557
4558 if (build_options.enable_debug_extensions and comp.verbose_air) {4558 if (build_options.enable_debug_extensions and comp.verbose_air) {
4559 const stderr, _ = std.debug.lockStderrWriter(&.{});4559 const io = comp.io;
4560 defer std.debug.unlockStderrWriter();4560 const stderr = try io.lockStderrWriter(&.{});
4561 defer io.unlockStderrWriter();
4561 stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {};4562 stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {};
4562 air.write(stderr, pt, liveness);4563 air.write(stderr, pt, liveness);
4563 stderr.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}) catch {};4564 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(...@@ -11273,15 +11273,18 @@ fn initValueAdvanced(
11273 return @enumFromInt(isel.values.items.len);11273 return @enumFromInt(isel.values.items.len);
11274}11274}
11275pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {11275pub 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
11280 const zcu = isel.pt.zcu;11276 const zcu = isel.pt.zcu;
11277 const io = zcu.comp.io;
11281 const gpa = zcu.gpa;11278 const gpa = zcu.gpa;
11282 const ip = &zcu.intern_pool;11279 const ip = &zcu.intern_pool;
11283 const nav = ip.getNav(isel.nav_index);11280 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
11285 var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;11288 var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;
11286 defer {11289 defer {
11287 for (reverse_live_values.values()) |*list| list.deinit(gpa);11290 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 {...@@ -97,17 +97,18 @@ fn dumpCrashContext() Io.Writer.Error!void {
97 // and the actual panic printing, which would be quite confusing.97 // and the actual panic printing, which would be quite confusing.
98 const stderr = std.debug.lockStderrWriter(&.{});98 const stderr = std.debug.lockStderrWriter(&.{});
99 defer std.debug.unlockStderrWriter();99 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
103 if (CodegenFunc.current) |*cg| {104 if (CodegenFunc.current) |*cg| {
104 const func_nav = cg.zcu.funcInfo(cg.func_index).owner_nav;105 const func_nav = cg.zcu.funcInfo(cg.func_index).owner_nav;
105 const func_fqn = cg.zcu.intern_pool.getNav(func_nav).fqn;106 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)});
107 } else if (AnalyzeBody.current) |anal| {108 } else if (AnalyzeBody.current) |anal| {
108 try dumpCrashContextSema(anal, &stderr.interface, &S.crash_heap);109 try dumpCrashContextSema(anal, w, &S.crash_heap);
109 } else {110 } else {
110 try stderr.interface.writeAll("(no context)\n\n");111 try w.writeAll("(no context)\n\n");
111 }112 }
112}113}
113fn dumpCrashContextSema(anal: *AnalyzeBody, stderr: *Io.Writer, crash_heap: []u8) Io.Writer.Error!void {114fn 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) !...@@ -124,7 +124,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
124 try wip_errors.addZirErrorMessages(zir, tree, source_code, "<stdin>");124 try wip_errors.addZirErrorMessages(zir, tree, source_code, "<stdin>");
125 var error_bundle = try wip_errors.toOwnedBundle("");125 var error_bundle = try wip_errors.toOwnedBundle("");
126 defer error_bundle.deinit(gpa);126 defer error_bundle.deinit(gpa);
127 error_bundle.renderToStdErr(.{}, color);127 error_bundle.renderToStderr(io, .{}, color);
128 process.exit(2);128 process.exit(2);
129 }129 }
130 } else {130 } else {
...@@ -138,7 +138,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -138,7 +138,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
138 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, "<stdin>");138 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, "<stdin>");
139 var error_bundle = try wip_errors.toOwnedBundle("");139 var error_bundle = try wip_errors.toOwnedBundle("");
140 defer error_bundle.deinit(gpa);140 defer error_bundle.deinit(gpa);
141 error_bundle.renderToStdErr(.{}, color);141 error_bundle.renderToStderr(io, .{}, color);
142 process.exit(2);142 process.exit(2);
143 }143 }
144 }144 }
...@@ -319,7 +319,7 @@ fn fmtPathFile(...@@ -319,7 +319,7 @@ fn fmtPathFile(
319 try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path);319 try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path);
320 var error_bundle = try wip_errors.toOwnedBundle("");320 var error_bundle = try wip_errors.toOwnedBundle("");
321 defer error_bundle.deinit(gpa);321 defer error_bundle.deinit(gpa);
322 error_bundle.renderToStdErr(.{}, fmt.color);322 error_bundle.renderToStderr(io, .{}, fmt.color);
323 fmt.any_error = true;323 fmt.any_error = true;
324 }324 }
325 },325 },
...@@ -334,7 +334,7 @@ fn fmtPathFile(...@@ -334,7 +334,7 @@ fn fmtPathFile(
334 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path);334 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path);
335 var error_bundle = try wip_errors.toOwnedBundle("");335 var error_bundle = try wip_errors.toOwnedBundle("");
336 defer error_bundle.deinit(gpa);336 defer error_bundle.deinit(gpa);
337 error_bundle.renderToStdErr(.{}, fmt.color);337 error_bundle.renderToStderr(io, .{}, fmt.color);
338 fmt.any_error = true;338 fmt.any_error = true;
339 }339 }
340 },340 },
src/libs/mingw.zig+19-10
...@@ -312,11 +312,17 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -312,11 +312,17 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
312312
313 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });313 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
314314
315 if (comp.verbose_cc) print: {315 if (comp.verbose_cc) {
316 var stderr, _ = std.debug.lockStderrWriter(&.{});316 var buffer: [256]u8 = undefined;
317 defer std.debug.unlockStderrWriter();317 const stderr = try io.lockStderrWriter(&buffer);
318 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;318 defer io.unlockStderrWriter();
319 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;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 };
320 }326 }
321327
322 try aro_comp.search_path.append(gpa, .{ .path = include_dir, .kind = .normal });328 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 {...@@ -333,11 +339,13 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
333339
334 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {340 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
335 var buffer: [64]u8 = undefined;341 var buffer: [64]u8 = undefined;
336 const w, const ttyconf = std.debug.lockStderrWriter(&buffer);342 const stderr = try io.lockStderrWriter(&buffer);
337 defer std.debug.unlockStderrWriter();343 defer io.unlockStderrWriter();
338 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {344 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {
339 if (msg.kind == .@"fatal error" or msg.kind == .@"error") {345 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 };
341 return error.AroPreprocessorFailed;349 return error.AroPreprocessorFailed;
342 }350 }
343 }351 }
...@@ -357,8 +365,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -357,8 +365,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
357 error.OutOfMemory => |e| return e,365 error.OutOfMemory => |e| return e,
358 error.ParseError => {366 error.ParseError => {
359 var buffer: [64]u8 = undefined;367 var buffer: [64]u8 = undefined;
360 const w, _ = std.debug.lockStderrWriter(&buffer);368 const stderr = try io.lockStderrWriter(&buffer);
361 defer std.debug.unlockStderrWriter();369 defer io.unlockStderrWriter();
370 const w = &stderr.interface;
362 try w.writeAll("error: ");371 try w.writeAll("error: ");
363 try def_diagnostics.writeMsg(w, input);372 try def_diagnostics.writeMsg(w, input);
364 try w.writeByte('\n');373 try w.writeByte('\n');
src/libs/mingw/def.zig+22-10
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const Io = std.Io;
23
3pub const ModuleDefinitionType = enum {4pub const ModuleDefinitionType = enum {
4 mingw,5 mingw,
...@@ -663,7 +664,9 @@ test parse {...@@ -663,7 +664,9 @@ test parse {
663 \\664 \\
664 ;665 ;
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{
667 .{670 .{
668 .name = "foo",671 .name = "foo",
669 .mangled_symbol_name = null,672 .mangled_symbol_name = null,
...@@ -743,7 +746,7 @@ test parse {...@@ -743,7 +746,7 @@ test parse {
743 },746 },
744 });747 });
745748
746 try testParse(.I386, source, "foo.dll", &[_]ModuleDefinition.Export{749 try testParse(io, .I386, source, "foo.dll", &[_]ModuleDefinition.Export{
747 .{750 .{
748 .name = "_foo",751 .name = "_foo",
749 .mangled_symbol_name = null,752 .mangled_symbol_name = null,
...@@ -823,7 +826,7 @@ test parse {...@@ -823,7 +826,7 @@ test parse {
823 },826 },
824 });827 });
825828
826 try testParse(.ARMNT, source, "foo.dll", &[_]ModuleDefinition.Export{829 try testParse(io, .ARMNT, source, "foo.dll", &[_]ModuleDefinition.Export{
827 .{830 .{
828 .name = "foo",831 .name = "foo",
829 .mangled_symbol_name = null,832 .mangled_symbol_name = null,
...@@ -903,7 +906,7 @@ test parse {...@@ -903,7 +906,7 @@ test parse {
903 },906 },
904 });907 });
905908
906 try testParse(.ARM64, source, "foo.dll", &[_]ModuleDefinition.Export{909 try testParse(io, .ARM64, source, "foo.dll", &[_]ModuleDefinition.Export{
907 .{910 .{
908 .name = "foo",911 .name = "foo",
909 .mangled_symbol_name = null,912 .mangled_symbol_name = null,
...@@ -997,7 +1000,9 @@ test "ntdll" {...@@ -997,7 +1000,9 @@ test "ntdll" {
997 \\RtlActivateActivationContextUnsafeFast@01000 \\RtlActivateActivationContextUnsafeFast@0
998 ;1001 ;
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{
1001 .{1006 .{
1002 .name = "RtlDispatchAPC@12",1007 .name = "RtlDispatchAPC@12",
1003 .mangled_symbol_name = null,1008 .mangled_symbol_name = null,
...@@ -1023,15 +1028,22 @@ test "ntdll" {...@@ -1023,15 +1028,22 @@ test "ntdll" {
1023 });1028 });
1024}1029}
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 {
1027 var diagnostics: Diagnostics = undefined;1038 var diagnostics: Diagnostics = undefined;
1028 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {1039 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {
1029 error.OutOfMemory => |e| return e,1040 error.OutOfMemory => |e| return e,
1030 error.ParseError => {1041 error.ParseError => {
1031 const stderr, _ = std.debug.lockStderrWriter(&.{});1042 const stderr = try io.lockStderrWriter(&.{});
1032 defer std.debug.unlockStderrWriter();1043 defer io.unlockStderrWriter();
1033 try diagnostics.writeMsg(stderr, source);1044 const w = &stderr.interface;
1034 try stderr.writeByte('\n');1045 try diagnostics.writeMsg(w, source);
1046 try w.writeByte('\n');
1035 return err;1047 return err;
1036 },1048 },
1037 };1049 };
src/link.zig+1-1
...@@ -2246,7 +2246,7 @@ fn resolvePathInputLib(...@@ -2246,7 +2246,7 @@ fn resolvePathInputLib(
2246 var error_bundle = try wip_errors.toOwnedBundle("");2246 var error_bundle = try wip_errors.toOwnedBundle("");
2247 defer error_bundle.deinit(gpa);2247 defer error_bundle.deinit(gpa);
22482248
2249 error_bundle.renderToStdErr(.{}, color);2249 error_bundle.renderToStderr(io, .{}, color);
22502250
2251 std.process.exit(1);2251 std.process.exit(1);
2252 }2252 }
src/link/Coff.zig+11-4
...@@ -4,6 +4,7 @@ const builtin = @import("builtin");...@@ -4,6 +4,7 @@ const builtin = @import("builtin");
4const native_endian = builtin.cpu.arch.endian();4const native_endian = builtin.cpu.arch.endian();
55
6const std = @import("std");6const std = @import("std");
7const Io = std.Io;
7const assert = std.debug.assert;8const assert = std.debug.assert;
8const log = std.log.scoped(.link);9const log = std.log.scoped(.link);
910
...@@ -2377,10 +2378,16 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe...@@ -2377,10 +2378,16 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe
2377 _ = name;2378 _ = name;
2378}2379}
23792380
2380pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) void {2381pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
2381 const w, _ = std.debug.lockStderrWriter(&.{});2382 const comp = coff.base.comp;
2382 defer std.debug.unlockStderrWriter();2383 const io = comp.io;
2383 coff.printNode(tid, w, .root, 0) catch {};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 };
2384}2391}
23852392
2386pub fn printNode(2393pub fn printNode(
src/link/Elf2.zig+10-4
...@@ -3729,10 +3729,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm...@@ -3729,10 +3729,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
3729 _ = name;3729 _ = name;
3730}3730}
37313731
3732pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void {3732pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
3733 const w, _ = std.debug.lockStderrWriter(&.{});3733 const comp = elf.base.comp;
3734 defer std.debug.unlockStderrWriter();3734 const io = comp.io;
3735 elf.printNode(tid, w, .root, 0) catch {};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 };
3736}3742}
37373743
3738pub fn printNode(3744pub fn printNode(
src/main.zig+17-16
...@@ -4429,9 +4429,9 @@ fn runOrTest(...@@ -4429,9 +4429,9 @@ fn runOrTest(
4429 // the error message and invocation below.4429 // the error message and invocation below.
4430 if (process.can_execv and arg_mode == .run) {4430 if (process.can_execv and arg_mode == .run) {
4431 // execv releases the locks; no need to destroy the Compilation here.4431 // execv releases the locks; no need to destroy the Compilation here.
4432 _ = std.debug.lockStderrWriter(&.{});4432 _ = try io.lockStderrWriter(&.{});
4433 const err = process.execve(gpa, argv.items, &env_map);4433 const err = process.execve(gpa, argv.items, &env_map);
4434 std.debug.unlockStderrWriter();4434 io.unlockStderrWriter();
4435 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc);4435 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc);
4436 const cmd = try std.mem.join(arena, " ", argv.items);4436 const cmd = try std.mem.join(arena, " ", argv.items);
4437 fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd });4437 fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd });
...@@ -4448,8 +4448,8 @@ fn runOrTest(...@@ -4448,8 +4448,8 @@ fn runOrTest(
4448 comp_destroyed.* = true;4448 comp_destroyed.* = true;
44494449
4450 const term_result = t: {4450 const term_result = t: {
4451 _ = std.debug.lockStderrWriter();4451 _ = try io.lockStderrWriter(&.{});
4452 defer std.debug.unlockStderrWriter();4452 defer io.unlockStderrWriter();
4453 break :t child.spawnAndWait(io);4453 break :t child.spawnAndWait(io);
4454 };4454 };
4455 const term = term_result catch |err| {4455 const term = term_result catch |err| {
...@@ -4606,7 +4606,8 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)...@@ -4606,7 +4606,8 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)
4606 defer errors.deinit(comp.gpa);4606 defer errors.deinit(comp.gpa);
46074607
4608 if (errors.errorMessageCount() > 0) {4608 if (errors.errorMessageCount() > 0) {
4609 errors.renderToStdErr(.{}, color);4609 const io = comp.io;
4610 errors.renderToStderr(io, .{}, color);
4610 return error.CompileErrorsReported;4611 return error.CompileErrorsReported;
4611 }4612 }
4612}4613}
...@@ -4659,7 +4660,7 @@ fn cmdTranslateC(...@@ -4659,7 +4660,7 @@ fn cmdTranslateC(
4659 return;4660 return;
4660 } else {4661 } else {
4661 const color: Color = .auto;4662 const color: Color = .auto;
4662 result.errors.renderToStdErr(.{}, color);4663 result.errors.renderToStderr(io, .{}, color);
4663 process.exit(1);4664 process.exit(1);
4664 }4665 }
4665 }4666 }
...@@ -5280,7 +5281,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)...@@ -5280,7 +5281,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
52805281
5281 if (fetch.error_bundle.root_list.items.len > 0) {5282 if (fetch.error_bundle.root_list.items.len > 0) {
5282 var errors = try fetch.error_bundle.toOwnedBundle("");5283 var errors = try fetch.error_bundle.toOwnedBundle("");
5283 errors.renderToStdErr(.{}, color);5284 errors.renderToStderr(io, .{}, color);
5284 process.exit(1);5285 process.exit(1);
5285 }5286 }
52865287
...@@ -5412,8 +5413,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)...@@ -5412,8 +5413,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
5412 child.stderr_behavior = .Inherit;5413 child.stderr_behavior = .Inherit;
54135414
5414 const term = t: {5415 const term = t: {
5415 _ = std.debug.lockStderrWriter(&.{});5416 _ = try io.lockStderrWriter(&.{});
5416 defer std.debug.unlockStderrWriter();5417 defer io.unlockStderrWriter();
5417 break :t child.spawnAndWait(io) catch |err|5418 break :t child.spawnAndWait(io) catch |err|
5418 fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err });5419 fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err });
5419 };5420 };
...@@ -6212,7 +6213,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6212,7 +6213,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
6212 try wip_errors.init(arena);6213 try wip_errors.init(arena);
6213 try wip_errors.addZirErrorMessages(zir, tree, source, display_path);6214 try wip_errors.addZirErrorMessages(zir, tree, source, display_path);
6214 var error_bundle = try wip_errors.toOwnedBundle("");6215 var error_bundle = try wip_errors.toOwnedBundle("");
6215 error_bundle.renderToStdErr(.{}, color);6216 error_bundle.renderToStderr(io, .{}, color);
6216 if (zir.loweringFailed()) {6217 if (zir.loweringFailed()) {
6217 process.exit(1);6218 process.exit(1);
6218 }6219 }
...@@ -6283,7 +6284,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6283,7 +6284,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
6283 try wip_errors.init(arena);6284 try wip_errors.init(arena);
6284 try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);6285 try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);
6285 var error_bundle = try wip_errors.toOwnedBundle("");6286 var error_bundle = try wip_errors.toOwnedBundle("");
6286 error_bundle.renderToStdErr(.{}, color);6287 error_bundle.renderToStderr(io, .{}, color);
6287 process.exit(1);6288 process.exit(1);
6288 }6289 }
62896290
...@@ -6557,7 +6558,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6557,7 +6558,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {
6557 try wip_errors.init(arena);6558 try wip_errors.init(arena);
6558 try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path);6559 try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path);
6559 var error_bundle = try wip_errors.toOwnedBundle("");6560 var error_bundle = try wip_errors.toOwnedBundle("");
6560 error_bundle.renderToStdErr(.{}, color);6561 error_bundle.renderToStderr(io, .{}, color);
6561 process.exit(1);6562 process.exit(1);
6562 }6563 }
65636564
...@@ -6569,7 +6570,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6569,7 +6570,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {
6569 try wip_errors.init(arena);6570 try wip_errors.init(arena);
6570 try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path);6571 try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path);
6571 var error_bundle = try wip_errors.toOwnedBundle("");6572 var error_bundle = try wip_errors.toOwnedBundle("");
6572 error_bundle.renderToStdErr(.{}, color);6573 error_bundle.renderToStderr(io, .{}, color);
6573 process.exit(1);6574 process.exit(1);
6574 }6575 }
65756576
...@@ -7005,7 +7006,7 @@ fn cmdFetch(...@@ -7005,7 +7006,7 @@ fn cmdFetch(
70057006
7006 if (fetch.error_bundle.root_list.items.len > 0) {7007 if (fetch.error_bundle.root_list.items.len > 0) {
7007 var errors = try fetch.error_bundle.toOwnedBundle("");7008 var errors = try fetch.error_bundle.toOwnedBundle("");
7008 errors.renderToStdErr(.{}, color);7009 errors.renderToStderr(io, .{}, color);
7009 process.exit(1);7010 process.exit(1);
7010 }7011 }
70117012
...@@ -7345,7 +7346,7 @@ fn loadManifest(...@@ -7345,7 +7346,7 @@ fn loadManifest(
7345 errdefer ast.deinit(gpa);7346 errdefer ast.deinit(gpa);
73467347
7347 if (ast.errors.len > 0) {7348 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);
7349 process.exit(2);7350 process.exit(2);
7350 }7351 }
73517352
...@@ -7362,7 +7363,7 @@ fn loadManifest(...@@ -7362,7 +7363,7 @@ fn loadManifest(
73627363
7363 var error_bundle = try wip_errors.toOwnedBundle("");7364 var error_bundle = try wip_errors.toOwnedBundle("");
7364 defer error_bundle.deinit(gpa);7365 defer error_bundle.deinit(gpa);
7365 error_bundle.renderToStdErr(.{}, options.color);7366 error_bundle.renderToStderr(io, .{}, options.color);
73667367
7367 process.exit(2);7368 process.exit(2);
7368 }7369 }