authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-20 23:20:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:27-07:00
log6a0f2227e8b40e3456d3c85c72f68f483b239af3
tree11649e598ed1bc743ed946318fea1f47708d72d2
parent7b0d826849f5def7b5c847a35e9e54ef81d70dc7

build_runner: port to `std.io.BufferedReader` API changes


20 files changed, 302 insertions(+), 356 deletions(-)

lib/std/Build/Fuzz/WebServer.zig+14-24
......@@ -100,8 +100,7 @@ fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {
100100
101101 var sr = connection.stream.reader();
102102 var rb: [0x4000]u8 = undefined;
103 var br: std.io.BufferedReader = undefined;
104 br.init(sr.interface(), &rb);
103 var br = sr.interface().buffered(&rb);
105104
106105 var sw = connection.stream.writer();
107106 var wb: [0x4000]u8 = undefined;
......@@ -109,7 +108,6 @@ fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {
109108
110109 var server: std.http.Server = .init(&br, &bw);
111110 var web_socket: std.http.WebSocket = undefined;
112 var send_buffer: [0x4000]u8 = undefined;
113111 var ws_recv_buffer: [0x4000]u8 align(4) = undefined;
114112 while (server.state == .ready) {
115113 var request = server.receiveHead() catch |err| switch (err) {
......@@ -119,7 +117,7 @@ fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {
119117 return;
120118 },
121119 };
122 if (web_socket.init(&request, &send_buffer, &ws_recv_buffer) catch |err| {
120 if (web_socket.init(&request, &ws_recv_buffer) catch |err| {
123121 log.err("initializing web socket: {s}", .{@errorName(err)});
124122 return;
125123 }) {
......@@ -281,19 +279,16 @@ fn buildWasmBinary(
281279 try sendMessage(child.stdin.?, .update);
282280 try sendMessage(child.stdin.?, .exit);
283281
284 const Header = std.zig.Server.Message.Header;
285282 var result: ?Path = null;
286283 var result_error_bundle = std.zig.ErrorBundle.empty;
287284
288 const stdout = poller.fifo(.stdout);
289
285 const stdout_br = poller.reader(.stdout);
290286 poll: while (true) {
291 while (stdout.readableLength() < @sizeOf(Header)) if (!try poller.poll()) break :poll;
292 var header: Header = undefined;
293 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
294 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll;
295 const body = stdout.readableSliceOfLen(header.bytes_len);
296
287 const Header = std.zig.Server.Message.Header;
288 while (stdout_br.bufferContents().len < @sizeOf(Header)) if (!try poller.poll()) break :poll;
289 const header = (stdout_br.takeStruct(Header) catch unreachable).*;
290 while (stdout_br.bufferContents().len < header.bytes_len) if (!try poller.poll()) break :poll;
291 const body = stdout_br.take(header.bytes_len) catch unreachable;
297292 switch (header.tag) {
298293 .zig_version => {
299294 if (!std.mem.eql(u8, builtin.zig_version_string, body)) {
......@@ -330,15 +325,12 @@ fn buildWasmBinary(
330325 },
331326 else => {}, // ignore other messages
332327 }
333
334 stdout.discard(body.len);
335328 }
336329
337 const stderr = poller.fifo(.stderr);
338 if (stderr.readableLength() > 0) {
339 const owned_stderr = try stderr.toOwnedSlice();
340 defer gpa.free(owned_stderr);
341 std.debug.print("{s}", .{owned_stderr});
330 const stderr_br = poller.reader(.stderr);
331 const stderr_contents = stderr_br.bufferContents();
332 if (stderr_contents.len > 0) {
333 std.debug.print("{s}", .{stderr_contents});
342334 }
343335
344336 // Send EOF to stdin.
......@@ -484,9 +476,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
484476 defer arena_instance.deinit();
485477 const arena = arena_instance.allocator();
486478
487 var send_buffer: [0x4000]u8 = undefined;
488 var response = request.respondStreaming(.{
489 .send_buffer = &send_buffer,
479 var response = try request.respondStreaming(.{
490480 .respond_options = .{
491481 .extra_headers = &.{
492482 .{ .name = "content-type", .value = "application/x-tar" },
......@@ -538,7 +528,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
538528 defer file.close();
539529
540530 archiver.prefix = joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache);
541 try archiver.writeFile(joined_path.sub_path, file);
531 try archiver.writeFile(joined_path.sub_path, file, try file.stat());
542532 }
543533
544534 // intentionally omitting the pointless trailer
lib/std/Build/Step.zig+12-19
......@@ -511,18 +511,15 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
511511 try sendMessage(zp.child.stdin.?, .update);
512512 if (!watch) try sendMessage(zp.child.stdin.?, .exit);
513513
514 const Header = std.zig.Server.Message.Header;
515514 var result: ?Path = null;
516515
517 const stdout = zp.poller.fifo(.stdout);
518
516 const stdout_br = zp.poller.reader(.stdout);
519517 poll: while (true) {
520 while (stdout.readableLength() < @sizeOf(Header)) if (!try zp.poller.poll()) break :poll;
521 var header: Header = undefined;
522 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
523 while (stdout.readableLength() < header.bytes_len) if (!try zp.poller.poll()) break :poll;
524 const body = stdout.readableSliceOfLen(header.bytes_len);
525
518 const Header = std.zig.Server.Message.Header;
519 while (stdout_br.bufferContents().len < @sizeOf(Header)) if (!try zp.poller.poll()) break :poll;
520 const header = (stdout_br.takeStruct(Header) catch unreachable).*;
521 while (stdout_br.bufferContents().len < header.bytes_len) if (!try zp.poller.poll()) break :poll;
522 const body = stdout_br.take(header.bytes_len) catch unreachable;
526523 switch (header.tag) {
527524 .zig_version => {
528525 if (!std.mem.eql(u8, builtin.zig_version_string, body)) {
......@@ -547,11 +544,8 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
547544 .string_bytes = try arena.dupe(u8, string_bytes),
548545 .extra = extra_array,
549546 };
550 if (watch) {
551 // This message indicates the end of the update.
552 stdout.discard(body.len);
553 break;
554 }
547 // This message indicates the end of the update.
548 if (watch) break :poll;
555549 },
556550 .emit_digest => {
557551 const EmitDigest = std.zig.Server.Message.EmitDigest;
......@@ -611,15 +605,14 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
611605 },
612606 else => {}, // ignore other messages
613607 }
614
615 stdout.discard(body.len);
616608 }
617609
618610 s.result_duration_ns = timer.read();
619611
620 const stderr = zp.poller.fifo(.stderr);
621 if (stderr.readableLength() > 0) {
622 try s.result_error_msgs.append(arena, try stderr.toOwnedSlice());
612 const stderr_br = zp.poller.reader(.stderr);
613 const stderr_contents = stderr_br.bufferContents();
614 if (stderr_contents.len > 0) {
615 try s.result_error_msgs.append(arena, try arena.dupe(u8, stderr_contents));
623616 }
624617
625618 return result;
lib/std/Build/Step/CheckObject.zig+12-12
......@@ -1239,7 +1239,7 @@ const MachODumper = struct {
12391239
12401240 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
12411241 var br: std.io.BufferedReader = undefined;
1242 br.initFixed(data);
1242 br.initFixed(@constCast(data));
12431243
12441244 var seg_id: ?u8 = null;
12451245 var offset: u64 = 0;
......@@ -1350,7 +1350,7 @@ const MachODumper = struct {
13501350
13511351 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
13521352 var br: std.io.BufferedReader = undefined;
1353 br.initFixed(data);
1353 br.initFixed(@constCast(data));
13541354
13551355 var seg_id: ?u8 = null;
13561356 var tag: Binding.Tag = .self;
......@@ -1448,7 +1448,7 @@ const MachODumper = struct {
14481448
14491449 var exports: std.ArrayList(Export) = .init(arena.allocator());
14501450 var br: std.io.BufferedReader = undefined;
1451 br.initFixed(data);
1451 br.initFixed(@constCast(data));
14521452 try parseTrieNode(arena.allocator(), &br, "", &exports);
14531453
14541454 mem.sort(Export, exports.items, {}, Export.lessThan);
......@@ -1706,7 +1706,7 @@ const ElfDumper = struct {
17061706 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
17071707 const gpa = step.owner.allocator;
17081708 var br: std.io.BufferedReader = undefined;
1709 br.initFixed(bytes);
1709 br.initFixed(@constCast(bytes));
17101710
17111711 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
17121712
......@@ -1781,7 +1781,7 @@ const ElfDumper = struct {
17811781
17821782 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {
17831783 var br: std.io.BufferedReader = undefined;
1784 br.initFixed(data);
1784 br.initFixed(@constCast(data));
17851785 const num = switch (ptr_width) {
17861786 .p32 => try br.takeInt(u32, .big),
17871787 .p64 => try br.takeInt(u64, .big),
......@@ -1791,7 +1791,7 @@ const ElfDumper = struct {
17911791 .p64 => @sizeOf(u64),
17921792 };
17931793 try br.discard(num * ptr_size);
1794 const strtab = try br.peekGreedy(0);
1794 const strtab = br.bufferContents();
17951795
17961796 assert(ctx.symtab.len == 0);
17971797 ctx.symtab = try ctx.gpa.alloc(ArSymtabEntry, num);
......@@ -1852,7 +1852,7 @@ const ElfDumper = struct {
18521852 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
18531853 const gpa = step.owner.allocator;
18541854 var br: std.io.BufferedReader = undefined;
1855 br.initFixed(bytes);
1855 br.initFixed(@constCast(bytes));
18561856
18571857 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
18581858 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;
......@@ -2355,7 +2355,7 @@ const WasmDumper = struct {
23552355 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
23562356 const gpa = step.owner.allocator;
23572357 var br: std.io.BufferedReader = undefined;
2358 br.initFixed(bytes);
2358 br.initFixed(@constCast(bytes));
23592359
23602360 const buf = try br.takeArray(8);
23612361 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;
......@@ -2402,7 +2402,7 @@ const WasmDumper = struct {
24022402 try bw.print(
24032403 \\Section {s}
24042404 \\size {d}
2405 , .{ @tagName(section), br.storageBuffer().len });
2405 , .{ @tagName(section), br.buffer.len });
24062406
24072407 switch (section) {
24082408 .type,
......@@ -2615,7 +2615,7 @@ const WasmDumper = struct {
26152615 /// https://webassembly.github.io/spec/core/appendix/custom.html
26162616 fn parseDumpNames(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
26172617 var subsection_br: std.io.BufferedReader = undefined;
2618 while (br.seek < br.storageBuffer().len) {
2618 while (br.seek < br.buffer.len) {
26192619 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
26202620 // The module name subsection ... consists of a single name
26212621 // that is assigned to the module itself.
......@@ -2626,7 +2626,7 @@ const WasmDumper = struct {
26262626 \\name {s}
26272627 \\
26282628 , .{name});
2629 if (subsection_br.seek != subsection_br.storageBuffer().len) return error.BadSubsectionSize;
2629 if (subsection_br.seek != subsection_br.buffer.len) return error.BadSubsectionSize;
26302630 },
26312631
26322632 // The function name subsection ... consists of a name map
......@@ -2647,7 +2647,7 @@ const WasmDumper = struct {
26472647 \\
26482648 , .{ index, name });
26492649 }
2650 if (subsection_br.seek != subsection_br.storageBuffer().len) return error.BadSubsectionSize;
2650 if (subsection_br.seek != subsection_br.buffer.len) return error.BadSubsectionSize;
26512651 },
26522652
26532653 // The local name subsection ... consists of an indirect name
lib/std/Build/Step/Run.zig+18-24
......@@ -1517,11 +1517,6 @@ fn evalZigTest(
15171517 break :failed false;
15181518 };
15191519
1520 const Header = std.zig.Server.Message.Header;
1521
1522 const stdout = poller.fifo(.stdout);
1523 const stderr = poller.fifo(.stderr);
1524
15251520 var fail_count: u32 = 0;
15261521 var skip_count: u32 = 0;
15271522 var leak_count: u32 = 0;
......@@ -1534,13 +1529,14 @@ fn evalZigTest(
15341529 var sub_prog_node: ?std.Progress.Node = null;
15351530 defer if (sub_prog_node) |n| n.end();
15361531
1532 const stdout_br = poller.reader(.stdout);
1533 const stderr_br = poller.reader(.stderr);
15371534 const any_write_failed = first_write_failed or poll: while (true) {
1538 while (stdout.readableLength() < @sizeOf(Header)) if (!try poller.poll()) break :poll false;
1539 var header: Header = undefined;
1540 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
1541 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll false;
1542 const body = stdout.readableSliceOfLen(header.bytes_len);
1543
1535 const Header = std.zig.Server.Message.Header;
1536 while (stdout_br.bufferContents().len < @sizeOf(Header)) if (!try poller.poll()) break :poll false;
1537 const header = (stdout_br.takeStruct(Header) catch unreachable).*;
1538 while (stdout_br.bufferContents().len < header.bytes_len) if (!try poller.poll()) break :poll false;
1539 const body = stdout_br.take(header.bytes_len) catch unreachable;
15441540 switch (header.tag) {
15451541 .zig_version => {
15461542 if (!std.mem.eql(u8, builtin.zig_version_string, body)) {
......@@ -1597,9 +1593,9 @@ fn evalZigTest(
15971593
15981594 if (tr_hdr.flags.fail or tr_hdr.flags.leak or tr_hdr.flags.log_err_count > 0) {
15991595 const name = std.mem.sliceTo(md.string_bytes[md.names[tr_hdr.index]..], 0);
1600 const orig_msg = stderr.readableSlice(0);
1601 defer stderr.discard(orig_msg.len);
1602 const msg = std.mem.trim(u8, orig_msg, "\n");
1596 const stderr_contents = stderr_br.bufferContents();
1597 stderr_br.toss(stderr_contents.len);
1598 const msg = std.mem.trim(u8, stderr_contents, "\n");
16031599 const label = if (tr_hdr.flags.fail)
16041600 "failed"
16051601 else if (tr_hdr.flags.leak)
......@@ -1650,8 +1646,6 @@ fn evalZigTest(
16501646 },
16511647 else => {}, // ignore other messages
16521648 }
1653
1654 stdout.discard(body.len);
16551649 };
16561650
16571651 if (any_write_failed) {
......@@ -1660,9 +1654,9 @@ fn evalZigTest(
16601654 while (try poller.poll()) {}
16611655 }
16621656
1663 if (stderr.readableLength() > 0) {
1664 const msg = std.mem.trim(u8, try stderr.toOwnedSlice(), "\n");
1665 if (msg.len > 0) run.step.result_stderr = msg;
1657 const stderr_contents = std.mem.trim(u8, stderr_br.bufferContents(), "\n");
1658 if (stderr_contents.len > 0) {
1659 run.step.result_stderr = try arena.dupe(u8, stderr_contents);
16661660 }
16671661
16681662 // Send EOF to stdin.
......@@ -1776,7 +1770,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
17761770 var stdout_bytes: ?[]const u8 = null;
17771771 var stderr_bytes: ?[]const u8 = null;
17781772
1779 run.stdio_limit = .limited(run.stdio_limit.min(run.max_stdio_size));
1773 run.stdio_limit = run.stdio_limit.min(.limited(run.max_stdio_size));
17801774 if (child.stdout) |stdout| {
17811775 if (child.stderr) |stderr| {
17821776 var poller = std.io.poll(arena, enum { stdout, stderr }, .{
......@@ -1787,15 +1781,15 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
17871781
17881782 while (try poller.poll()) {
17891783 if (run.stdio_limit.toInt()) |limit| {
1790 if (poller.fifo(.stderr).count > limit)
1784 if (poller.reader(.stderr).bufferContents().len > limit)
17911785 return error.StdoutStreamTooLong;
1792 if (poller.fifo(.stderr).count > limit)
1786 if (poller.reader(.stderr).bufferContents().len > limit)
17931787 return error.StderrStreamTooLong;
17941788 }
17951789 }
17961790
1797 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
1798 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
1791 stdout_bytes = poller.reader(.stdout).bufferContents();
1792 stderr_bytes = poller.reader(.stderr).bufferContents();
17991793 } else {
18001794 stdout_bytes = try stdout.readToEndAlloc(arena, run.stdio_limit);
18011795 }
lib/std/fs/path.zig+5-6
......@@ -150,27 +150,26 @@ pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter(formatJoin) {
150150 return .{ .data = paths };
151151}
152152
153fn formatJoin(paths: []const []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void {
153fn formatJoin(paths: []const []const u8, bw: *std.io.BufferedWriter, comptime fmt: []const u8) !void {
154154 _ = fmt;
155 _ = options;
156155
157156 const first_path_idx = for (paths, 0..) |p, idx| {
158157 if (p.len != 0) break idx;
159158 } else return;
160159
161 try w.writeAll(paths[first_path_idx]); // first component
160 try bw.writeAll(paths[first_path_idx]); // first component
162161 var prev_path = paths[first_path_idx];
163162 for (paths[first_path_idx + 1 ..]) |this_path| {
164163 if (this_path.len == 0) continue; // skip empty components
165164 const prev_sep = isSep(prev_path[prev_path.len - 1]);
166165 const this_sep = isSep(this_path[0]);
167166 if (!prev_sep and !this_sep) {
168 try w.writeByte(sep);
167 try bw.writeByte(sep);
169168 }
170169 if (prev_sep and this_sep) {
171 try w.writeAll(this_path[1..]); // skip redundant separator
170 try bw.writeAll(this_path[1..]); // skip redundant separator
172171 } else {
173 try w.writeAll(this_path);
172 try bw.writeAll(this_path);
174173 }
175174 prev_path = this_path;
176175 }
lib/std/http/WebSocket.zig+7-11
......@@ -9,7 +9,7 @@ const native_endian = builtin.cpu.arch.endian();
99key: []const u8,
1010request: *std.http.Server.Request,
1111recv_fifo: std.fifo.LinearFifo(u8, .Slice),
12reader: *std.io.BufferedReader,
12reader: std.io.BufferedReader,
1313response: std.http.Server.Response,
1414/// Number of bytes that have been peeked but not discarded yet.
1515outstanding_len: usize,
......@@ -20,7 +20,6 @@ pub const InitError = error{WebSocketUpgradeMissingKey} ||
2020pub fn init(
2121 ws: *WebSocket,
2222 request: *std.http.Server.Request,
23 send_buffer: []u8,
2423 recv_buffer: []align(4) u8,
2524) InitError!bool {
2625 switch (request.head.version) {
......@@ -58,9 +57,8 @@ pub fn init(
5857 ws.* = .{
5958 .key = key,
6059 .recv_fifo = .init(recv_buffer),
61 .reader = undefined,
62 .response = request.respondStreaming(.{
63 .send_buffer = send_buffer,
60 .reader = (try request.reader()).unbuffered(),
61 .response = try request.respondStreaming(.{
6462 .respond_options = .{
6563 .status = .switching_protocols,
6664 .extra_headers = &.{
......@@ -74,7 +72,6 @@ pub fn init(
7472 .request = request,
7573 .outstanding_len = 0,
7674 };
77 ws.reader.init(try request.reader(), &.{});
7875 return true;
7976}
8077
......@@ -239,9 +236,8 @@ pub fn writeMessagev(ws: *WebSocket, message: []const std.posix.iovec_const, opc
239236 },
240237 };
241238
242 const response = &ws.response;
243 try response.writeAll(header);
244 for (message) |iovec|
245 try response.writeAll(iovec.base[0..iovec.len]);
246 try response.flush();
239 var bw = ws.response.writer().unbuffered();
240 try bw.writeAll(header);
241 for (message) |iovec| try bw.writeAll(iovec.base[0..iovec.len]);
242 try bw.flush();
247243}
lib/std/io.zig+6-7
......@@ -53,7 +53,12 @@ pub fn poll(
5353 const enum_fields = @typeInfo(StreamEnum).@"enum".fields;
5454 var result: Poller(StreamEnum) = .{
5555 .gpa = gpa,
56 .readers = undefined,
56 .readers = @splat(.{
57 .unbuffered_reader = .failing,
58 .buffer = &.{},
59 .end = 0,
60 .seek = 0,
61 }),
5762 .poll_fds = undefined,
5863 .windows = if (is_windows) .{
5964 .first_read_done = false,
......@@ -70,12 +75,6 @@ pub fn poll(
7075 };
7176
7277 inline for (enum_fields, 0..) |field, i| {
73 result.readers[i] = .{
74 .unbuffered_reader = .failing,
75 .buffer = &.{},
76 .end = 0,
77 .seek = 0,
78 };
7978 if (is_windows) {
8079 result.windows.active.handles_buf[i] = @field(files, field.name).handle;
8180 } else {
lib/std/io/BufferedReader.zig+57-18
......@@ -51,6 +51,23 @@ pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize {
5151 return passthruReadVec(br, data);
5252}
5353
54pub fn readVecAll(br: *BufferedReader, data: [][]u8) Reader.Error!void {
55 var index: usize = 0;
56 var truncate: usize = 0;
57 while (index < data.len) {
58 {
59 const untruncated = data[index];
60 data[index] = untruncated[truncate..];
61 defer data[index] = untruncated;
62 truncate += try br.readVec(data[index..]);
63 }
64 while (index < data.len and truncate <= data[index].len) {
65 truncate -= data[index].len;
66 index += 1;
67 }
68 }
69}
70
5471pub fn read(br: *BufferedReader, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!usize {
5572 return passthruRead(br, bw, limit);
5673}
......@@ -58,8 +75,8 @@ pub fn read(br: *BufferedReader, bw: *BufferedWriter, limit: Reader.Limit) Reade
5875/// "Pump" data from the reader to the writer.
5976pub fn readAll(br: *BufferedReader, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!void {
6077 var remaining = limit;
61 while (true) {
62 const n = try passthruRead(br, bw, remaining);
78 while (remaining.nonzero()) {
79 const n = try br.read(bw, remaining);
6380 remaining = remaining.subtract(n).?;
6481 }
6582}
......@@ -68,7 +85,7 @@ fn passthruRead(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) Read
6885 const br: *BufferedReader = @alignCast(@ptrCast(ctx));
6986 const buffer = br.buffer[0..br.end];
7087 const buffered = buffer[br.seek..];
71 const limited = buffered[0..limit.min(buffered.len)];
88 const limited = buffered[0..limit.minInt(buffered.len)];
7289 if (limited.len > 0) {
7390 const n = try bw.write(limited);
7491 br.seek += n;
......@@ -93,7 +110,7 @@ fn passthruReadVec(ctx: ?*anyopaque, data: []const []u8) Reader.Error!usize {
93110 vecs[0] = buf[copy_len..];
94111 const vecs_len: usize = @min(vecs.len, data.len - i);
95112 var vec_data_len: usize = vecs[0].len;
96 for (&vecs[1..vecs_len], data[i + 1 ..][0 .. vecs_len - 1]) |*v, d| {
113 for (vecs[1..vecs_len], data[i + 1 ..][0 .. vecs_len - 1]) |*v, d| {
97114 vec_data_len += d.len;
98115 v.* = d;
99116 }
......@@ -149,7 +166,6 @@ pub fn seekForwardBy(br: *BufferedReader, seek_by: u64) !void {
149166/// * `peek`
150167/// * `toss`
151168pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {
152 assert(n <= br.buffer.len);
153169 try br.fill(n);
154170 return br.buffer[br.seek..][0..n];
155171}
......@@ -169,7 +185,6 @@ pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {
169185/// * `peek`
170186/// * `toss`
171187pub fn peekGreedy(br: *BufferedReader, n: usize) Reader.Error![]u8 {
172 assert(n <= br.buffer.len);
173188 try br.fill(n);
174189 return br.buffer[br.seek..br.end];
175190}
......@@ -448,10 +463,12 @@ fn peekDelimiterInclusiveUnlessEnd(br: *BufferedReader, delimiter: u8) Delimiter
448463 @branchHint(.likely);
449464 return buffer[seek .. end + 1];
450465 }
451 const remainder = buffer[seek..];
452 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
453 br.end = remainder.len;
454 br.seek = 0;
466 if (seek > 0) {
467 const remainder = buffer[seek..];
468 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
469 br.end = remainder.len;
470 br.seek = 0;
471 }
455472 while (br.end < br.buffer.len) {
456473 const n = try br.unbuffered_reader.readVec(&.{br.buffer[br.end..]});
457474 const prev_end = br.end;
......@@ -550,10 +567,12 @@ pub fn fill(br: *BufferedReader, n: usize) Reader.Error!void {
550567 @branchHint(.likely);
551568 return;
552569 }
553 const remainder = buffer[seek..];
554 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
555 br.end = remainder.len;
556 br.seek = 0;
570 if (seek > 0) {
571 const remainder = buffer[seek..];
572 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
573 br.end = remainder.len;
574 br.seek = 0;
575 }
557576 while (true) {
558577 br.end += try br.unbuffered_reader.readVec(&.{br.buffer[br.end..]});
559578 if (n <= br.end) return;
......@@ -665,15 +684,35 @@ pub fn writableSliceGreedyAlloc(
665684 allocator: Allocator,
666685 min_len: usize,
667686) error{OutOfMemory}![]u8 {
668 _ = br;
669 _ = allocator;
670 _ = min_len;
671 @panic("TODO");
687 {
688 const unused = br.buffer[br.end..];
689 if (unused.len >= min_len) return unused;
690 }
691 const seek = br.seek;
692 if (seek > 0) {
693 const buffer = br.buffer[0..br.end];
694 const remainder = buffer[seek..];
695 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
696 br.end = remainder.len;
697 br.seek = 0;
698 }
699 {
700 var list: std.ArrayListUnmanaged(u8) = .{
701 .items = br.buffer[0..br.end],
702 .capacity = br.buffer.len,
703 };
704 defer br.buffer = list.allocatedSlice();
705 try list.ensureUnusedCapacity(allocator, min_len);
706 }
707 const unused = br.buffer[br.end..];
708 assert(unused.len >= min_len);
709 return unused;
672710}
673711
674712/// After writing directly into the unused capacity of `buffer`, this function
675713/// updates `end` so that users of `BufferedReader` can receive the data.
676714pub fn advanceBufferEnd(br: *BufferedReader, n: usize) void {
715 assert(n <= br.buffer.len - br.end);
677716 br.end += n;
678717}
679718
lib/std/io/BufferedWriter.zig+12-9
......@@ -141,16 +141,19 @@ pub fn advance(bw: *BufferedWriter, n: usize) void {
141141/// The `data` parameter is mutable because this function needs to mutate the
142142/// fields in order to handle partial writes from `Writer.VTable.writeVec`.
143143pub fn writeVecAll(bw: *BufferedWriter, data: [][]const u8) Writer.Error!void {
144 var i: usize = 0;
145 while (true) {
146 var n = try passthruWriteSplat(bw, data[i..], 1);
147 const len = data[i].len;
148 while (n >= len) {
149 n -= len;
150 i += 1;
151 if (i >= data.len) return;
144 var index: usize = 0;
145 var truncate: usize = 0;
146 while (index < data.len) {
147 {
148 const untruncated = data[index];
149 data[index] = untruncated[truncate..];
150 defer data[index] = untruncated;
151 truncate += try bw.writeVec(data[index..]);
152 }
153 while (index < data.len and truncate <= data[index].len) {
154 truncate -= data[index].len;
155 index += 1;
152156 }
153 data[i] = data[i][n..];
154157 }
155158}
156159
lib/std/io/Reader.zig+1-1
......@@ -94,7 +94,7 @@ pub const Limit = enum(usize) {
9494 }
9595
9696 pub fn slice(l: Limit, s: []u8) []u8 {
97 return s[0..min(l, s.len)];
97 return s[0..l.minInt(s.len)];
9898 }
9999
100100 pub fn toInt(l: Limit) ?usize {
lib/std/process/Child.zig+9-10
......@@ -348,16 +348,15 @@ pub const RunResult = struct {
348348 stderr: []u8,
349349};
350350
351fn writeFifoDataToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), fifo: *std.io.PollFifo) !void {
352 if (fifo.head != 0) fifo.realign();
351fn writeBufferedReaderToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), br: *std.io.BufferedReader) !void {
352 assert(br.seek == 0);
353353 if (list.capacity == 0) {
354354 list.* = .{
355 .items = fifo.buf[0..fifo.count],
356 .capacity = fifo.buf.len,
355 .items = br.bufferContents(),
356 .capacity = br.buffer.len,
357357 };
358 fifo.* = std.io.PollFifo.init(fifo.allocator);
359358 } else {
360 try list.appendSlice(allocator, fifo.buf[0..fifo.count]);
359 try list.appendSlice(allocator, br.bufferContents());
361360 }
362361}
363362
......@@ -384,14 +383,14 @@ pub fn collectOutput(
384383 defer poller.deinit();
385384
386385 while (try poller.poll()) {
387 if (poller.fifo(.stdout).count > max_output_bytes)
386 if (poller.reader(.stdout).bufferContents().len > max_output_bytes)
388387 return error.StdoutStreamTooLong;
389 if (poller.fifo(.stderr).count > max_output_bytes)
388 if (poller.reader(.stderr).bufferContents().len > max_output_bytes)
390389 return error.StderrStreamTooLong;
391390 }
392391
393 try writeFifoDataToArrayList(allocator, stdout, poller.fifo(.stdout));
394 try writeFifoDataToArrayList(allocator, stderr, poller.fifo(.stderr));
392 try writeBufferedReaderToArrayList(allocator, stdout, poller.reader(.stdout));
393 try writeBufferedReaderToArrayList(allocator, stderr, poller.reader(.stderr));
395394}
396395
397396pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{
lib/std/zig/ZonGen.zig+1-1
......@@ -522,7 +522,7 @@ pub fn parseStrLit(
522522 tree: Ast,
523523 node: Ast.Node.Index,
524524 writer: *std.io.BufferedWriter,
525) error{OutOfMemory}!std.zig.string_literal.Result {
525) std.io.Writer.Error!std.zig.string_literal.Result {
526526 switch (tree.nodeTag(node)) {
527527 .string_literal => {
528528 const token = tree.nodeMainToken(node);
src/Air/print.zig+3-3
......@@ -72,9 +72,9 @@ pub fn writeInst(
7272}
7373
7474pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
75 var bw = std.debug.lockStdErr2(&.{});
76 defer std.debug.unlockStdErr();
77 air.write(&bw, pt, liveness);
75 const stderr_bw = std.debug.lockStderrWriter(&.{});
76 defer std.debug.unlockStderrWriter();
77 air.write(stderr_bw, pt, liveness);
7878}
7979
8080pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
src/Compilation.zig+6-8
......@@ -1881,14 +1881,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18811881
18821882 if (options.verbose_llvm_cpu_features) {
18831883 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
1884 var stderr = std.debug.lockStdErr2(&.{});
1885 defer std.debug.unlockStdErr();
1886 nosuspend {
1887 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1888 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
1889 stderr.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
1890 stderr.print(" features: {s}\n", .{cf}) catch {};
1891 }
1884 const stderr_bw = std.debug.lockStderrWriter(&.{});
1885 defer std.debug.unlockStderrWriter();
1886 stderr_bw.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1887 stderr_bw.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
1888 stderr_bw.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
1889 stderr_bw.print(" features: {s}\n", .{cf}) catch {};
18921890 }
18931891 }
18941892
src/InternPool.zig+14-17
......@@ -11263,8 +11263,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
1126311263
1126411264fn dumpAllFallible(ip: *const InternPool) anyerror!void {
1126511265 var buffer: [4096]u8 = undefined;
11266 var bw = std.debug.lockStdErr2(&buffer);
11267 defer std.debug.unlockStdErr();
11266 const stderr_bw = std.debug.lockStderrWriter(&buffer);
11267 defer std.debug.unlockStderrWriter();
1126811268 for (ip.locals, 0..) |*local, tid| {
1126911269 const items = local.shared.items.view();
1127011270 for (
......@@ -11273,12 +11273,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
1127311273 0..,
1127411274 ) |tag, data, index| {
1127511275 const i = Index.Unwrapped.wrap(.{ .tid = @enumFromInt(tid), .index = @intCast(index) }, ip);
11276 try bw.print("${d} = {s}(", .{ i, @tagName(tag) });
11276 try stderr_bw.print("${d} = {s}(", .{ i, @tagName(tag) });
1127711277 switch (tag) {
1127811278 .removed => {},
1127911279
11280 .simple_type => try bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),
11281 .simple_value => try bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),
11280 .simple_type => try stderr_bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),
11281 .simple_value => try stderr_bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),
1128211282
1128311283 .type_int_signed,
1128411284 .type_int_unsigned,
......@@ -11351,17 +11351,16 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
1135111351 .func_coerced,
1135211352 .union_value,
1135311353 .memoized_call,
11354 => try bw.print("{d}", .{data}),
11354 => try stderr_bw.print("{d}", .{data}),
1135511355
1135611356 .opt_null,
1135711357 .type_slice,
1135811358 .only_possible_value,
11359 => try bw.print("${d}", .{data}),
11359 => try stderr_bw.print("${d}", .{data}),
1136011360 }
11361 try bw.writeAll(")\n");
11361 try stderr_bw.writeAll(")\n");
1136211362 }
1136311363 }
11364 try bw.flush();
1136511364}
1136611365
1136711366pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {
......@@ -11396,8 +11395,8 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
1139611395 }
1139711396
1139811397 var buffer: [4096]u8 = undefined;
11399 var bw = std.debug.lockStdErr2(&buffer);
11400 defer std.debug.unlockStdErr();
11398 const stderr_bw = std.debug.lockStderrWriter(&buffer);
11399 defer std.debug.unlockStderrWriter();
1140111400
1140211401 const SortContext = struct {
1140311402 values: []std.ArrayListUnmanaged(Index),
......@@ -11410,23 +11409,21 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
1141011409 var it = instances.iterator();
1141111410 while (it.next()) |entry| {
1141211411 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);
11413 try bw.print("{f} ({}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
11412 try stderr_bw.print("{f} ({}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
1141411413 for (entry.value_ptr.items) |index| {
1141511414 const unwrapped_index = index.unwrap(ip);
1141611415 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));
1141711416 const owner_nav = ip.getNav(func.owner_nav);
11418 try bw.print(" {f}: (", .{owner_nav.name.fmt(ip)});
11417 try stderr_bw.print(" {f}: (", .{owner_nav.name.fmt(ip)});
1141911418 for (func.comptime_args.get(ip)) |arg| {
1142011419 if (arg != .none) {
1142111420 const key = ip.indexToKey(arg);
11422 try bw.print(" {} ", .{key});
11421 try stderr_bw.print(" {} ", .{key});
1142311422 }
1142411423 }
11425 try bw.writeAll(")\n");
11424 try stderr_bw.writeAll(")\n");
1142611425 }
1142711426 }
11428
11429 try bw.flush();
1143011427}
1143111428
1143211429pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
src/Zcu.zig+61-140
......@@ -1043,12 +1043,12 @@ pub const File = struct {
10431043 if (stat.size > std.math.maxInt(u32))
10441044 return error.FileTooBig;
10451045
1046 const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);
1046 const source = try gpa.allocSentinel(u8, @intCast(stat.size), 0);
10471047 errdefer gpa.free(source);
10481048
1049 const amt = try f.readAll(source);
1050 if (amt != stat.size)
1051 return error.UnexpectedEndOfFile;
1049 var fr = f.reader();
1050 var br = fr.interface().unbuffered();
1051 try br.readSlice(source);
10521052
10531053 // Here we do not modify stat fields because this function is the one
10541054 // used for error reporting. We need to keep the stat fields stale so that
......@@ -2845,34 +2845,21 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F
28452845 undefined;
28462846 defer if (data_has_safety_tag) gpa.free(safety_buffer);
28472847
2848 const data_ptr = if (data_has_safety_tag)
2849 @as([*]u8, @ptrCast(safety_buffer.ptr))
2850 else
2851 @as([*]u8, @ptrCast(zir.instructions.items(.data).ptr));
2852
2853 var iovecs = [_]std.posix.iovec{
2854 .{
2855 .base = @as([*]u8, @ptrCast(zir.instructions.items(.tag).ptr)),
2856 .len = header.instructions_len,
2857 },
2858 .{
2859 .base = data_ptr,
2860 .len = header.instructions_len * 8,
2861 },
2862 .{
2863 .base = zir.string_bytes.ptr,
2864 .len = header.string_bytes_len,
2865 },
2866 .{
2867 .base = @as([*]u8, @ptrCast(zir.extra.ptr)),
2868 .len = header.extra_len * 4,
2869 },
2848 var vecs = [_][]u8{
2849 @ptrCast(zir.instructions.items(.tag)),
2850 if (data_has_safety_tag)
2851 @ptrCast(safety_buffer)
2852 else
2853 zir.instructions.items(.data),
2854 zir.string_bytes,
2855 @ptrCast(zir.extra),
2856 };
2857 var cache_fr = cache_file.reader();
2858 var cache_br = cache_fr.interface().unbuffered();
2859 cache_br.readVecAll(&vecs) catch |err| switch (err) {
2860 error.ReadFailed => if (cache_fr.err) |_| unreachable else |e| return e,
2861 error.EndOfStream => return error.UnexpectedFileSize,
28702862 };
2871 const amt_read = try cache_file.readvAll(&iovecs);
2872 const amt_expected = zir.instructions.len * 9 +
2873 zir.string_bytes.len +
2874 zir.extra.len * 4;
2875 if (amt_read != amt_expected) return error.UnexpectedFileSize;
28762863 if (data_has_safety_tag) {
28772864 const tags = zir.instructions.items(.tag);
28782865 for (zir.instructions.items(.data), 0..) |*data, i| {
......@@ -2895,14 +2882,6 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S
28952882 undefined;
28962883 defer if (data_has_safety_tag) gpa.free(safety_buffer);
28972884
2898 const data_ptr: [*]const u8 = if (data_has_safety_tag)
2899 if (zir.instructions.len == 0)
2900 undefined
2901 else
2902 @ptrCast(safety_buffer.ptr)
2903 else
2904 @ptrCast(zir.instructions.items(.data).ptr);
2905
29062885 if (data_has_safety_tag) {
29072886 // The `Data` union has a safety tag but in the file format we store it without.
29082887 for (zir.instructions.items(.data), 0..) |*data, i| {
......@@ -2920,29 +2899,21 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S
29202899 .stat_inode = stat.inode,
29212900 .stat_mtime = stat.mtime,
29222901 };
2923 var iovecs: [5]std.posix.iovec_const = .{
2924 .{
2925 .base = @ptrCast(&header),
2926 .len = @sizeOf(Zir.Header),
2927 },
2928 .{
2929 .base = @ptrCast(zir.instructions.items(.tag).ptr),
2930 .len = zir.instructions.len,
2931 },
2932 .{
2933 .base = data_ptr,
2934 .len = zir.instructions.len * 8,
2935 },
2936 .{
2937 .base = zir.string_bytes.ptr,
2938 .len = zir.string_bytes.len,
2939 },
2940 .{
2941 .base = @ptrCast(zir.extra.ptr),
2942 .len = zir.extra.len * 4,
2943 },
2902 var vecs = [_][]const u8{
2903 @ptrCast((&header)[0..1]),
2904 @ptrCast(zir.instructions.items(.tag)),
2905 if (data_has_safety_tag)
2906 @ptrCast(safety_buffer)
2907 else
2908 @ptrCast(zir.instructions.items(.data)),
2909 zir.string_bytes,
2910 @ptrCast(zir.extra),
2911 };
2912 var cache_fw = cache_file.writer();
2913 var cache_bw = cache_fw.interface().unbuffered();
2914 cache_bw.writeVecAll(&vecs) catch |err| switch (err) {
2915 error.WriteFailed => if (cache_fw.err) |_| unreachable else |e| return e,
29442916 };
2945 try cache_file.writevAll(&iovecs);
29462917}
29472918
29482919pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir) std.fs.File.WriteError!void {
......@@ -2958,45 +2929,22 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir
29582929 .stat_inode = stat.inode,
29592930 .stat_mtime = stat.mtime,
29602931 };
2961 var iovecs: [9]std.posix.iovec_const = .{
2962 .{
2963 .base = @ptrCast(&header),
2964 .len = @sizeOf(Zoir.Header),
2965 },
2966 .{
2967 .base = @ptrCast(zoir.nodes.items(.tag)),
2968 .len = zoir.nodes.len * @sizeOf(Zoir.Node.Repr.Tag),
2969 },
2970 .{
2971 .base = @ptrCast(zoir.nodes.items(.data)),
2972 .len = zoir.nodes.len * 4,
2973 },
2974 .{
2975 .base = @ptrCast(zoir.nodes.items(.ast_node)),
2976 .len = zoir.nodes.len * 4,
2977 },
2978 .{
2979 .base = @ptrCast(zoir.extra),
2980 .len = zoir.extra.len * 4,
2981 },
2982 .{
2983 .base = @ptrCast(zoir.limbs),
2984 .len = zoir.limbs.len * @sizeOf(std.math.big.Limb),
2985 },
2986 .{
2987 .base = zoir.string_bytes.ptr,
2988 .len = zoir.string_bytes.len,
2989 },
2990 .{
2991 .base = @ptrCast(zoir.compile_errors),
2992 .len = zoir.compile_errors.len * @sizeOf(Zoir.CompileError),
2993 },
2994 .{
2995 .base = @ptrCast(zoir.error_notes),
2996 .len = zoir.error_notes.len * @sizeOf(Zoir.CompileError.Note),
2997 },
2932 var vecs = [_][]const u8{
2933 @ptrCast((&header)[0..1]),
2934 @ptrCast(zoir.nodes.items(.tag)),
2935 @ptrCast(zoir.nodes.items(.data)),
2936 @ptrCast(zoir.nodes.items(.ast_node)),
2937 @ptrCast(zoir.extra),
2938 @ptrCast(zoir.limbs),
2939 zoir.string_bytes,
2940 @ptrCast(zoir.compile_errors),
2941 @ptrCast(zoir.error_notes),
2942 };
2943 var cache_fw = cache_file.writer();
2944 var cache_bw = cache_fw.interface().unbuffered();
2945 cache_bw.writeVecAll(&vecs) catch |err| switch (err) {
2946 error.WriteFailed => if (cache_fw.err) |_| unreachable else |e| return e,
29982947 };
2999 try cache_file.writevAll(&iovecs);
30002948}
30012949
30022950pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs.File) !Zoir {
......@@ -3025,49 +2973,22 @@ pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs
30252973 zoir.compile_errors = try gpa.alloc(Zoir.CompileError, header.compile_errors_len);
30262974 zoir.error_notes = try gpa.alloc(Zoir.CompileError.Note, header.error_notes_len);
30272975
3028 var iovecs: [8]std.posix.iovec = .{
3029 .{
3030 .base = @ptrCast(zoir.nodes.items(.tag)),
3031 .len = header.nodes_len * @sizeOf(Zoir.Node.Repr.Tag),
3032 },
3033 .{
3034 .base = @ptrCast(zoir.nodes.items(.data)),
3035 .len = header.nodes_len * 4,
3036 },
3037 .{
3038 .base = @ptrCast(zoir.nodes.items(.ast_node)),
3039 .len = header.nodes_len * 4,
3040 },
3041 .{
3042 .base = @ptrCast(zoir.extra),
3043 .len = header.extra_len * 4,
3044 },
3045 .{
3046 .base = @ptrCast(zoir.limbs),
3047 .len = header.limbs_len * @sizeOf(std.math.big.Limb),
3048 },
3049 .{
3050 .base = zoir.string_bytes.ptr,
3051 .len = header.string_bytes_len,
3052 },
3053 .{
3054 .base = @ptrCast(zoir.compile_errors),
3055 .len = header.compile_errors_len * @sizeOf(Zoir.CompileError),
3056 },
3057 .{
3058 .base = @ptrCast(zoir.error_notes),
3059 .len = header.error_notes_len * @sizeOf(Zoir.CompileError.Note),
3060 },
2976 var vecs = [_][]u8{
2977 @ptrCast(zoir.nodes.items(.tag)),
2978 @ptrCast(zoir.nodes.items(.data)),
2979 @ptrCast(zoir.nodes.items(.ast_node)),
2980 @ptrCast(zoir.extra),
2981 @ptrCast(zoir.limbs),
2982 zoir.string_bytes,
2983 @ptrCast(zoir.compile_errors),
2984 @ptrCast(zoir.error_notes),
30612985 };
3062
3063 const bytes_expected = expected: {
3064 var n: usize = 0;
3065 for (iovecs) |v| n += v.len;
3066 break :expected n;
2986 var cache_fr = cache_file.reader();
2987 var cache_br = cache_fr.interface().unbuffered();
2988 cache_br.readVecAll(&vecs) catch |err| switch (err) {
2989 error.ReadFailed => if (cache_fr.err) |_| unreachable else |e| return e,
2990 error.EndOfStream => return error.UnexpectedFileSize,
30672991 };
3068
3069 const bytes_read = try cache_file.readvAll(&iovecs);
3070 if (bytes_read != bytes_expected) return error.UnexpectedFileSize;
30712992 return zoir;
30722993}
30732994
src/Zcu/PerThread.zig+19-8
......@@ -249,11 +249,14 @@ pub fn updateFile(
249249 if (stat.size > std.math.maxInt(u32))
250250 return error.FileTooBig;
251251
252 const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);
252 const source = try gpa.allocSentinel(u8, @intCast(stat.size), 0);
253253 defer if (file.source == null) gpa.free(source);
254 const amt = try source_file.readAll(source);
255 if (amt != stat.size)
256 return error.UnexpectedEndOfFile;
254 var source_fr = source_file.reader();
255 var source_br = source_fr.interface().unbuffered();
256 source_br.readSlice(source) catch |err| switch (err) {
257 error.ReadFailed => if (source_fr.err) |_| unreachable else |e| return e,
258 error.EndOfStream => return error.UnexpectedEndOfFile,
259 };
257260
258261 file.source = source;
259262
......@@ -340,13 +343,17 @@ fn loadZirZoirCache(
340343 .zon => Zoir.Header,
341344 };
342345
346 var buffer: [@sizeOf(Header)]u8 = undefined;
347 var cache_fr = cache_file.reader();
348 var cache_br = cache_fr.interface().buffered(&buffer);
349
343350 // First we read the header to determine the lengths of arrays.
344 const header = cache_file.reader().readStruct(Header) catch |err| switch (err) {
351 const header = (cache_br.takeStruct(Header) catch |err| switch (err) {
345352 // This can happen if Zig bails out of this function between creating
346353 // the cached file and writing it.
347354 error.EndOfStream => return .invalid,
348355 else => |e| return e,
349 };
356 }).*;
350357
351358 const unchanged_metadata =
352359 stat.size == header.stat_size and
......@@ -2433,8 +2440,12 @@ fn updateEmbedFileInner(
24332440 const old_len = strings.mutate.len;
24342441 errdefer strings.shrinkRetainingCapacity(old_len);
24352442 const bytes = (try strings.addManyAsSlice(size_plus_one))[0];
2436 const actual_read = try file.readAll(bytes[0..size]);
2437 if (actual_read != size) return error.UnexpectedEof;
2443 var fr = file.reader();
2444 var br = fr.interface().unbuffered();
2445 br.readSlice(bytes[0..size]) catch |err| switch (err) {
2446 error.ReadFailed => if (fr.err) |_| unreachable else |e| return e,
2447 error.EndOfStream => return error.UnexpectedEof,
2448 };
24382449 bytes[size] = 0;
24392450 break :str try ip.getOrPutTrailingString(gpa, tid, @intCast(bytes.len), .maybe_embedded_nulls);
24402451 };
src/crash_report.zig+40-33
......@@ -80,18 +80,19 @@ fn dumpStatusReport() !void {
8080 var fba = std.heap.FixedBufferAllocator.init(&crash_heap);
8181 const allocator = fba.allocator();
8282
83 var stderr = std.fs.File.stderr().writer().unbuffered();
83 var stderr_fw = std.fs.File.stderr().writer();
84 var stderr_bw = stderr_fw.interface().unbuffered();
8485 const block: *Sema.Block = anal.block;
8586 const zcu = anal.sema.pt.zcu;
8687
8788 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {
8889 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));
89 try stderr.print("Analyzing lost instruction in file '{f}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});
90 try stderr_bw.print("Analyzing lost instruction in file '{f}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});
9091 return;
9192 };
9293
93 try stderr.writeAll("Analyzing ");
94 try stderr.print("Analyzing '{f}'\n", .{file.path.fmt(zcu.comp)});
94 try stderr_bw.writeAll("Analyzing ");
95 try stderr_bw.print("Analyzing '{f}'\n", .{file.path.fmt(zcu.comp)});
9596
9697 print_zir.renderInstructionContext(
9798 allocator,
......@@ -100,12 +101,12 @@ fn dumpStatusReport() !void {
100101 file,
101102 src_base_node,
102103 6, // indent
103 &stderr,
104 &stderr_bw,
104105 ) catch |err| switch (err) {
105 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),
106 error.OutOfMemory => try stderr_bw.writeAll(" <out of memory dumping zir>\n"),
106107 else => |e| return e,
107108 };
108 try stderr.print(
109 try stderr_bw.print(
109110 \\ For full context, use the command
110111 \\ zig ast-check -t {f}
111112 \\
......@@ -116,30 +117,30 @@ fn dumpStatusReport() !void {
116117 while (parent) |curr| {
117118 fba.reset();
118119 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));
119 try stderr.print(" in {f}\n", .{cur_block_file.path.fmt(zcu.comp)});
120 try stderr_bw.print(" in {f}\n", .{cur_block_file.path.fmt(zcu.comp)});
120121 _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {
121 try stderr.writeAll(" > [lost instruction; this should not happen]\n");
122 try stderr_bw.writeAll(" > [lost instruction; this should not happen]\n");
122123 parent = curr.parent;
123124 continue;
124125 };
125 try stderr.writeAll(" > ");
126 try stderr_bw.writeAll(" > ");
126127 print_zir.renderSingleInstruction(
127128 allocator,
128129 curr.body[curr.body_index],
129130 cur_block_file,
130131 cur_block_src_base_node,
131132 6, // indent
132 &stderr,
133 &stderr_bw,
133134 ) catch |err| switch (err) {
134 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),
135 error.OutOfMemory => try stderr_bw.writeAll(" <out of memory dumping zir>\n"),
135136 else => |e| return e,
136137 };
137 try stderr.writeAll("\n");
138 try stderr_bw.writeAll("\n");
138139
139140 parent = curr.parent;
140141 }
141142
142 try stderr.writeByte('\n');
143 try stderr_bw.writeByte('\n');
143144}
144145
145146var crash_heap: [16 * 4096]u8 = undefined;
......@@ -268,8 +269,9 @@ const StackContext = union(enum) {
268269 debug.dumpCurrentStackTrace(ct.ret_addr);
269270 },
270271 .exception => |context| {
271 var stderr = std.fs.File.stderr().writer().unbuffered();
272 debug.dumpStackTraceFromBase(context, &stderr);
272 var stderr_fw = std.fs.File.stderr().writer();
273 var stderr_bw = stderr_fw.interface().unbuffered();
274 debug.dumpStackTraceFromBase(context, &stderr_bw);
273275 },
274276 .not_supported => {
275277 std.fs.File.stderr().writeAll("Stack trace not supported on this platform.\n") catch {};
......@@ -379,19 +381,20 @@ const PanicSwitch = struct {
379381
380382 state.recover_stage = .release_mutex;
381383
382 var stderr = std.fs.File.stderr().writer().unbuffered();
384 var stderr_fw = std.fs.File.stderr().writer();
385 var stderr_bw = stderr_fw.interface().unbuffered();
383386 if (builtin.single_threaded) {
384 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});
387 stderr_bw.print("panic: ", .{}) catch goTo(releaseMutex, .{state});
385388 } else {
386389 const current_thread_id = std.Thread.getCurrentId();
387 stderr.print("thread {} panic: ", .{current_thread_id}) catch goTo(releaseMutex, .{state});
390 stderr_bw.print("thread {} panic: ", .{current_thread_id}) catch goTo(releaseMutex, .{state});
388391 }
389 stderr.print("{s}\n", .{msg}) catch goTo(releaseMutex, .{state});
392 stderr_bw.print("{s}\n", .{msg}) catch goTo(releaseMutex, .{state});
390393
391394 state.recover_stage = .report_stack;
392395
393396 dumpStatusReport() catch |err| {
394 stderr.print("\nIntercepted error.{} while dumping current state. Continuing...\n", .{err}) catch {};
397 stderr_bw.print("\nIntercepted error.{} while dumping current state. Continuing...\n", .{err}) catch {};
395398 };
396399
397400 goTo(reportStack, .{state});
......@@ -406,8 +409,9 @@ const PanicSwitch = struct {
406409 recover(state, trace, stack, msg);
407410
408411 state.recover_stage = .release_mutex;
409 var stderr = std.fs.File.stderr().writer().unbuffered();
410 stderr.writeAll("\nOriginal Error:\n") catch {};
412 var stderr_fw = std.fs.File.stderr().writer();
413 var stderr_bw = stderr_fw.interface().unbuffered();
414 stderr_bw.writeAll("\nOriginal Error:\n") catch {};
411415 goTo(reportStack, .{state});
412416 }
413417
......@@ -477,8 +481,9 @@ const PanicSwitch = struct {
477481 recover(state, trace, stack, msg);
478482
479483 state.recover_stage = .silent_abort;
480 var stderr = std.fs.File.stderr().writer().unbuffered();
481 stderr.writeAll("Aborting...\n") catch {};
484 var stderr_fw = std.fs.File.stderr().writer();
485 var stderr_bw = stderr_fw.interface().unbuffered();
486 stderr_bw.writeAll("Aborting...\n") catch {};
482487 goTo(abort, .{});
483488 }
484489
......@@ -505,10 +510,11 @@ const PanicSwitch = struct {
505510 // lower the verbosity, and restore it at the end if we don't panic.
506511 state.recover_verbosity = .message_only;
507512
508 var stderr = std.fs.File.stderr().writer().unbuffered();
509 stderr.writeAll("\nPanicked during a panic: ") catch {};
510 stderr.writeAll(msg) catch {};
511 stderr.writeAll("\nInner panic stack:\n") catch {};
513 var stderr_fw = std.fs.File.stderr().writer();
514 var stderr_bw = stderr_fw.interface().unbuffered();
515 stderr_bw.writeAll("\nPanicked during a panic: ") catch {};
516 stderr_bw.writeAll(msg) catch {};
517 stderr_bw.writeAll("\nInner panic stack:\n") catch {};
512518 if (trace) |t| {
513519 debug.dumpStackTrace(t.*);
514520 }
......@@ -519,10 +525,11 @@ const PanicSwitch = struct {
519525 .message_only => {
520526 state.recover_verbosity = .silent;
521527
522 var stderr = std.fs.File.stderr().writer().unbuffered();
523 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
524 stderr.writeAll(msg) catch {};
525 stderr.writeByte('\n') catch {};
528 var stderr_fw = std.fs.File.stderr().writer();
529 var stderr_bw = stderr_fw.interface().unbuffered();
530 stderr_bw.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
531 stderr_bw.writeAll(msg) catch {};
532 stderr_bw.writeByte('\n') catch {};
526533
527534 // If we succeed, restore all the way to dumping the stack.
528535 state.recover_verbosity = .message_and_stack;
src/print_value.zig+4-4
......@@ -47,7 +47,7 @@ pub fn print(
4747 level: u8,
4848 pt: Zcu.PerThread,
4949 opt_sema: ?*Sema,
50) std.io.Writer.Error!void {
50) (std.io.Writer.Error || Zcu.CompileError)!void {
5151 const zcu = pt.zcu;
5252 const ip = &zcu.intern_pool;
5353 switch (ip.indexToKey(val.toIntern())) {
......@@ -190,7 +190,7 @@ fn printAggregate(
190190 level: u8,
191191 pt: Zcu.PerThread,
192192 opt_sema: ?*Sema,
193) std.io.Writer.Error!void {
193) (std.io.Writer.Error || Zcu.CompileError)!void {
194194 if (level == 0) {
195195 if (is_ref) try bw.writeByte('&');
196196 return bw.writeAll(".{ ... }");
......@@ -276,7 +276,7 @@ fn printPtr(
276276 level: u8,
277277 pt: Zcu.PerThread,
278278 opt_sema: ?*Sema,
279) std.io.Writer.Error!void {
279) (std.io.Writer.Error || Zcu.CompileError)!void {
280280 const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) {
281281 .undef => return bw.writeAll("undefined"),
282282 .ptr => |ptr| ptr,
......@@ -336,7 +336,7 @@ pub fn printPtrDerivation(
336336 /// The maximum recursion depth. We can never recurse infinitely here, but the depth can be arbitrary,
337337 /// so at this depth we just write "..." to prevent stack overflow.
338338 ptr_depth: u8,
339) std.io.Writer.Error!Value.PointerDeriveStep {
339) (std.io.Writer.Error || Zcu.CompileError)!Value.PointerDeriveStep {
340340 const zcu = pt.zcu;
341341 const ip = &zcu.intern_pool;
342342
src/print_zir.zig+1-1
......@@ -176,7 +176,7 @@ const Writer = struct {
176176 }
177177 } = .{},
178178
179 const Error = std.io.Writer.Error;
179 const Error = std.io.Writer.Error || std.mem.Allocator.Error;
180180
181181 fn writeInstToStream(
182182 self: *Writer,