authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-20 11:24:41+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-20 11:24:41+02:00
log8373788c4c5fecac940ce5b86e35d803f9f14a21
tree4b7ffda8c011e93e3b04af1fd0d26ed56690738e
parent4780cc50cf7e42f6af3eb71ef3897f4b341215b4
parentc40fb96ca358e2ef28aecc2b7ebc5ffab43ccac8
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24488 from ziglang/more

std.zig: finish updating to new I/O API

23 files changed, 275 insertions(+), 595 deletions(-)

lib/compiler/objcopy.zig+9-9
...@@ -10,6 +10,9 @@ const assert = std.debug.assert;...@@ -10,6 +10,9 @@ const assert = std.debug.assert;
10const fatal = std.process.fatal;10const fatal = std.process.fatal;
11const Server = std.zig.Server;11const Server = std.zig.Server;
1212
13var stdin_buffer: [1024]u8 = undefined;
14var stdout_buffer: [1024]u8 = undefined;
15
13pub fn main() !void {16pub fn main() !void {
14 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);17 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
15 defer arena_instance.deinit();18 defer arena_instance.deinit();
...@@ -22,11 +25,8 @@ pub fn main() !void {...@@ -22,11 +25,8 @@ pub fn main() !void {
22 return cmdObjCopy(gpa, arena, args[1..]);25 return cmdObjCopy(gpa, arena, args[1..]);
23}26}
2427
25fn cmdObjCopy(28fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
26 gpa: Allocator,29 _ = gpa;
27 arena: Allocator,
28 args: []const []const u8,
29) !void {
30 var i: usize = 0;30 var i: usize = 0;
31 var opt_out_fmt: ?std.Target.ObjectFormat = null;31 var opt_out_fmt: ?std.Target.ObjectFormat = null;
32 var opt_input: ?[]const u8 = null;32 var opt_input: ?[]const u8 = null;
...@@ -225,13 +225,13 @@ fn cmdObjCopy(...@@ -225,13 +225,13 @@ fn cmdObjCopy(
225 }225 }
226226
227 if (listen) {227 if (listen) {
228 var stdin_reader = fs.File.stdin().reader(&stdin_buffer);
229 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
228 var server = try Server.init(.{230 var server = try Server.init(.{
229 .gpa = gpa,231 .in = &stdin_reader.interface,
230 .in = .stdin(),232 .out = &stdout_writer.interface,
231 .out = .stdout(),
232 .zig_version = builtin.zig_version_string,233 .zig_version = builtin.zig_version_string,
233 });234 });
234 defer server.deinit();
235235
236 var seen_update = false;236 var seen_update = false;
237 while (true) {237 while (true) {
lib/compiler/resinator/main.zig+4-2
...@@ -13,6 +13,8 @@ const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePag...@@ -13,6 +13,8 @@ const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePag
13const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;13const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
14const aro = @import("aro");14const aro = @import("aro");
1515
16var stdout_buffer: [1024]u8 = undefined;
17
16pub fn main() !void {18pub fn main() !void {
17 var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;19 var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
18 defer std.debug.assert(gpa.deinit() == .ok);20 defer std.debug.assert(gpa.deinit() == .ok);
...@@ -41,12 +43,12 @@ pub fn main() !void {...@@ -41,12 +43,12 @@ pub fn main() !void {
41 cli_args = args[3..];43 cli_args = args[3..];
42 }44 }
4345
46 var stdout_writer2 = std.fs.File.stdout().writer(&stdout_buffer);
44 var error_handler: ErrorHandler = switch (zig_integration) {47 var error_handler: ErrorHandler = switch (zig_integration) {
45 true => .{48 true => .{
46 .server = .{49 .server = .{
47 .out = std.fs.File.stdout(),50 .out = &stdout_writer2.interface,
48 .in = undefined, // won't be receiving messages51 .in = undefined, // won't be receiving messages
49 .receive_fifo = undefined, // won't be receiving messages
50 },52 },
51 },53 },
52 false => .{54 false => .{
lib/compiler/test_runner.zig+8-7
...@@ -2,7 +2,6 @@...@@ -2,7 +2,6 @@
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4const std = @import("std");4const std = @import("std");
5const io = std.io;
6const testing = std.testing;5const testing = std.testing;
7const assert = std.debug.assert;6const assert = std.debug.assert;
87
...@@ -11,8 +10,10 @@ pub const std_options: std.Options = .{...@@ -11,8 +10,10 @@ pub const std_options: std.Options = .{
11};10};
1211
13var log_err_count: usize = 0;12var log_err_count: usize = 0;
14var fba_buffer: [8192]u8 = undefined;
15var fba = std.heap.FixedBufferAllocator.init(&fba_buffer);13var fba = std.heap.FixedBufferAllocator.init(&fba_buffer);
14var fba_buffer: [8192]u8 = undefined;
15var stdin_buffer: [4096]u8 = undefined;
16var stdout_buffer: [4096]u8 = undefined;
1617
17const crippled = switch (builtin.zig_backend) {18const crippled = switch (builtin.zig_backend) {
18 .stage2_powerpc,19 .stage2_powerpc,
...@@ -67,13 +68,13 @@ pub fn main() void {...@@ -67,13 +68,13 @@ pub fn main() void {
6768
68fn mainServer() !void {69fn mainServer() !void {
69 @disableInstrumentation();70 @disableInstrumentation();
71 var stdin_reader = std.fs.File.stdin().readerStreaming(&stdin_buffer);
72 var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
70 var server = try std.zig.Server.init(.{73 var server = try std.zig.Server.init(.{
71 .gpa = fba.allocator(),74 .in = &stdin_reader.interface,
72 .in = .stdin(),75 .out = &stdout_writer.interface,
73 .out = .stdout(),
74 .zig_version = builtin.zig_version_string,76 .zig_version = builtin.zig_version_string,
75 });77 });
76 defer server.deinit();
7778
78 if (builtin.fuzz) {79 if (builtin.fuzz) {
79 const coverage_id = fuzzer_coverage_id();80 const coverage_id = fuzzer_coverage_id();
...@@ -103,7 +104,7 @@ fn mainServer() !void {...@@ -103,7 +104,7 @@ fn mainServer() !void {
103 defer testing.allocator.free(expected_panic_msgs);104 defer testing.allocator.free(expected_panic_msgs);
104105
105 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {106 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {
106 name.* = @as(u32, @intCast(string_bytes.items.len));107 name.* = @intCast(string_bytes.items.len);
107 try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1);108 try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1);
108 string_bytes.appendSliceAssumeCapacity(test_fn.name);109 string_bytes.appendSliceAssumeCapacity(test_fn.name);
109 string_bytes.appendAssumeCapacity(0);110 string_bytes.appendAssumeCapacity(0);
lib/std/Build/Step/Run.zig+1-1
...@@ -1744,7 +1744,7 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {...@@ -1744,7 +1744,7 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
1744 .tag = tag,1744 .tag = tag,
1745 .bytes_len = 0,1745 .bytes_len = 0,
1746 };1746 };
1747 try file.writeAll(std.mem.asBytes(&header));1747 try file.writeAll(@ptrCast(&header));
1748}1748}
17491749
1750fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: u32) !void {1750fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: u32) !void {
lib/std/Io/Reader.zig+17-17
...@@ -1108,9 +1108,9 @@ pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n:...@@ -1108,9 +1108,9 @@ pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n:
1108/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.1108/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
1109///1109///
1110/// See also:1110/// See also:
1111/// * `peekStructReference`1111/// * `peekStructPointer`
1112/// * `takeStruct`1112/// * `takeStruct`
1113pub fn takeStructReference(r: *Reader, comptime T: type) Error!*align(1) T {1113pub fn takeStructPointer(r: *Reader, comptime T: type) Error!*align(1) T {
1114 // Only extern and packed structs have defined in-memory layout.1114 // Only extern and packed structs have defined in-memory layout.
1115 comptime assert(@typeInfo(T).@"struct".layout != .auto);1115 comptime assert(@typeInfo(T).@"struct".layout != .auto);
1116 return @ptrCast(try r.takeArray(@sizeOf(T)));1116 return @ptrCast(try r.takeArray(@sizeOf(T)));
...@@ -1122,9 +1122,9 @@ pub fn takeStructReference(r: *Reader, comptime T: type) Error!*align(1) T {...@@ -1122,9 +1122,9 @@ pub fn takeStructReference(r: *Reader, comptime T: type) Error!*align(1) T {
1122/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.1122/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
1123///1123///
1124/// See also:1124/// See also:
1125/// * `takeStructReference`1125/// * `takeStructPointer`
1126/// * `peekStruct`1126/// * `peekStruct`
1127pub fn peekStructReference(r: *Reader, comptime T: type) Error!*align(1) T {1127pub fn peekStructPointer(r: *Reader, comptime T: type) Error!*align(1) T {
1128 // Only extern and packed structs have defined in-memory layout.1128 // Only extern and packed structs have defined in-memory layout.
1129 comptime assert(@typeInfo(T).@"struct".layout != .auto);1129 comptime assert(@typeInfo(T).@"struct".layout != .auto);
1130 return @ptrCast(try r.peekArray(@sizeOf(T)));1130 return @ptrCast(try r.peekArray(@sizeOf(T)));
...@@ -1136,14 +1136,14 @@ pub fn peekStructReference(r: *Reader, comptime T: type) Error!*align(1) T {...@@ -1136,14 +1136,14 @@ pub fn peekStructReference(r: *Reader, comptime T: type) Error!*align(1) T {
1136/// when `endian` is comptime-known and matches the host endianness.1136/// when `endian` is comptime-known and matches the host endianness.
1137///1137///
1138/// See also:1138/// See also:
1139/// * `takeStructReference`1139/// * `takeStructPointer`
1140/// * `peekStruct`1140/// * `peekStruct`
1141pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {1141pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
1142 switch (@typeInfo(T)) {1142 switch (@typeInfo(T)) {
1143 .@"struct" => |info| switch (info.layout) {1143 .@"struct" => |info| switch (info.layout) {
1144 .auto => @compileError("ill-defined memory layout"),1144 .auto => @compileError("ill-defined memory layout"),
1145 .@"extern" => {1145 .@"extern" => {
1146 var res = (try r.takeStructReference(T)).*;1146 var res = (try r.takeStructPointer(T)).*;
1147 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);1147 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
1148 return res;1148 return res;
1149 },1149 },
...@@ -1162,13 +1162,13 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia...@@ -1162,13 +1162,13 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia
1162///1162///
1163/// See also:1163/// See also:
1164/// * `takeStruct`1164/// * `takeStruct`
1165/// * `peekStructReference`1165/// * `peekStructPointer`
1166pub inline fn peekStruct(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {1166pub inline fn peekStruct(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
1167 switch (@typeInfo(T)) {1167 switch (@typeInfo(T)) {
1168 .@"struct" => |info| switch (info.layout) {1168 .@"struct" => |info| switch (info.layout) {
1169 .auto => @compileError("ill-defined memory layout"),1169 .auto => @compileError("ill-defined memory layout"),
1170 .@"extern" => {1170 .@"extern" => {
1171 var res = (try r.peekStructReference(T)).*;1171 var res = (try r.peekStructPointer(T)).*;
1172 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);1172 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
1173 return res;1173 return res;
1174 },1174 },
...@@ -1557,27 +1557,27 @@ test takeVarInt {...@@ -1557,27 +1557,27 @@ test takeVarInt {
1557 try testing.expectError(error.EndOfStream, r.takeVarInt(u16, .little, 1));1557 try testing.expectError(error.EndOfStream, r.takeVarInt(u16, .little, 1));
1558}1558}
15591559
1560test takeStructReference {1560test takeStructPointer {
1561 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });1561 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
1562 const S = extern struct { a: u8, b: u16 };1562 const S = extern struct { a: u8, b: u16 };
1563 switch (native_endian) {1563 switch (native_endian) {
1564 .little => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.takeStructReference(S)).*),1564 .little => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.takeStructPointer(S)).*),
1565 .big => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.takeStructReference(S)).*),1565 .big => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.takeStructPointer(S)).*),
1566 }1566 }
1567 try testing.expectError(error.EndOfStream, r.takeStructReference(S));1567 try testing.expectError(error.EndOfStream, r.takeStructPointer(S));
1568}1568}
15691569
1570test peekStructReference {1570test peekStructPointer {
1571 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });1571 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
1572 const S = extern struct { a: u8, b: u16 };1572 const S = extern struct { a: u8, b: u16 };
1573 switch (native_endian) {1573 switch (native_endian) {
1574 .little => {1574 .little => {
1575 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructReference(S)).*);1575 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructPointer(S)).*);
1576 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructReference(S)).*);1576 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructPointer(S)).*);
1577 },1577 },
1578 .big => {1578 .big => {
1579 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructReference(S)).*);1579 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructPointer(S)).*);
1580 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructReference(S)).*);1580 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructPointer(S)).*);
1581 },1581 },
1582 }1582 }
1583}1583}
lib/std/Io/Writer.zig+18-1
...@@ -860,7 +860,15 @@ pub inline fn writeSliceEndian(...@@ -860,7 +860,15 @@ pub inline fn writeSliceEndian(
860 if (native_endian == endian) {860 if (native_endian == endian) {
861 return writeAll(w, @ptrCast(slice));861 return writeAll(w, @ptrCast(slice));
862 } else {862 } else {
863 return w.writeArraySwap(w, Elem, slice);863 return writeSliceSwap(w, Elem, slice);
864 }
865}
866
867pub fn writeSliceSwap(w: *Writer, Elem: type, slice: []const Elem) Error!void {
868 for (slice) |elem| {
869 var tmp = elem;
870 std.mem.byteSwapAllFields(Elem, &tmp);
871 try w.writeAll(@ptrCast(&tmp));
864 }872 }
865}873}
866874
...@@ -2638,3 +2646,12 @@ test writeStruct {...@@ -2638,3 +2646,12 @@ test writeStruct {
2638 }, &buffer);2646 }, &buffer);
2639 }2647 }
2640}2648}
2649
2650test writeSliceEndian {
2651 var buffer: [5]u8 align(2) = undefined;
2652 var w: Writer = .fixed(&buffer);
2653 try w.writeByte('x');
2654 const array: [2]u16 = .{ 0x1234, 0x5678 };
2655 try writeSliceEndian(&w, u16, &array, .big);
2656 try testing.expectEqualSlices(u8, &.{ 'x', 0x12, 0x34, 0x56, 0x78 }, &buffer);
2657}
lib/std/debug.zig+7
...@@ -566,6 +566,13 @@ pub fn assertReadable(slice: []const volatile u8) void {...@@ -566,6 +566,13 @@ pub fn assertReadable(slice: []const volatile u8) void {
566 for (slice) |*byte| _ = byte.*;566 for (slice) |*byte| _ = byte.*;
567}567}
568568
569/// Invokes detectable illegal behavior when the provided array is not aligned
570/// to the provided amount.
571pub fn assertAligned(ptr: anytype, comptime alignment: std.mem.Alignment) void {
572 const aligned_ptr: *align(alignment.toByteUnits()) anyopaque = @alignCast(@ptrCast(ptr));
573 _ = aligned_ptr;
574}
575
569/// Equivalent to `@panic` but with a formatted message.576/// Equivalent to `@panic` but with a formatted message.
570pub fn panic(comptime format: []const u8, args: anytype) noreturn {577pub fn panic(comptime format: []const u8, args: anytype) noreturn {
571 @branchHint(.cold);578 @branchHint(.cold);
lib/std/mem.zig+20-16
...@@ -2179,22 +2179,8 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {...@@ -2179,22 +2179,8 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
2179 const BackingInt = std.meta.Int(.unsigned, @bitSizeOf(S));2179 const BackingInt = std.meta.Int(.unsigned, @bitSizeOf(S));
2180 ptr.* = @bitCast(@byteSwap(@as(BackingInt, @bitCast(ptr.*))));2180 ptr.* = @bitCast(@byteSwap(@as(BackingInt, @bitCast(ptr.*))));
2181 },2181 },
2182 .array => {2182 .array => |info| {
2183 for (ptr) |*item| {2183 byteSwapAllElements(info.child, ptr);
2184 switch (@typeInfo(@TypeOf(item.*))) {
2185 .@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(item.*), item),
2186 .@"enum" => {
2187 item.* = @enumFromInt(@byteSwap(@intFromEnum(item.*)));
2188 },
2189 .bool => {},
2190 .float => |float_info| {
2191 item.* = @bitCast(@byteSwap(@as(std.meta.Int(.unsigned, float_info.bits), @bitCast(item.*))));
2192 },
2193 else => {
2194 item.* = @byteSwap(item.*);
2195 },
2196 }
2197 }
2198 },2184 },
2199 else => {2185 else => {
2200 ptr.* = @byteSwap(ptr.*);2186 ptr.* = @byteSwap(ptr.*);
...@@ -2258,6 +2244,24 @@ test byteSwapAllFields {...@@ -2258,6 +2244,24 @@ test byteSwapAllFields {
2258 }, k);2244 }, k);
2259}2245}
22602246
2247pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
2248 for (slice) |*elem| {
2249 switch (@typeInfo(@TypeOf(elem.*))) {
2250 .@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(elem.*), elem),
2251 .@"enum" => {
2252 elem.* = @enumFromInt(@byteSwap(@intFromEnum(elem.*)));
2253 },
2254 .bool => {},
2255 .float => |float_info| {
2256 elem.* = @bitCast(@byteSwap(@as(std.meta.Int(.unsigned, float_info.bits), @bitCast(elem.*))));
2257 },
2258 else => {
2259 elem.* = @byteSwap(elem.*);
2260 },
2261 }
2262 }
2263}
2264
2261/// Returns an iterator that iterates over the slices of `buffer` that are not2265/// Returns an iterator that iterates over the slices of `buffer` that are not
2262/// any of the items in `delimiters`.2266/// any of the items in `delimiters`.
2263///2267///
lib/std/zig.zig+1
...@@ -908,4 +908,5 @@ test {...@@ -908,4 +908,5 @@ test {
908 _ = system;908 _ = system;
909 _ = target;909 _ = target;
910 _ = c_translation;910 _ = c_translation;
911 _ = llvm;
911}912}
lib/std/zig/LibCInstallation.zig+3-4
...@@ -370,7 +370,7 @@ fn findNativeIncludeDirWindows(...@@ -370,7 +370,7 @@ fn findNativeIncludeDirWindows(
370370
371 for (installs) |install| {371 for (installs) |install| {
372 result_buf.shrinkAndFree(0);372 result_buf.shrinkAndFree(0);
373 try result_buf.writer().print("{s}\\Include\\{s}\\ucrt", .{ install.path, install.version });373 try result_buf.print("{s}\\Include\\{s}\\ucrt", .{ install.path, install.version });
374374
375 var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {375 var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {
376 error.FileNotFound,376 error.FileNotFound,
...@@ -417,7 +417,7 @@ fn findNativeCrtDirWindows(...@@ -417,7 +417,7 @@ fn findNativeCrtDirWindows(
417417
418 for (installs) |install| {418 for (installs) |install| {
419 result_buf.shrinkAndFree(0);419 result_buf.shrinkAndFree(0);
420 try result_buf.writer().print("{s}\\Lib\\{s}\\ucrt\\{s}", .{ install.path, install.version, arch_sub_dir });420 try result_buf.print("{s}\\Lib\\{s}\\ucrt\\{s}", .{ install.path, install.version, arch_sub_dir });
421421
422 var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {422 var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {
423 error.FileNotFound,423 error.FileNotFound,
...@@ -484,8 +484,7 @@ fn findNativeKernel32LibDir(...@@ -484,8 +484,7 @@ fn findNativeKernel32LibDir(
484484
485 for (installs) |install| {485 for (installs) |install| {
486 result_buf.shrinkAndFree(0);486 result_buf.shrinkAndFree(0);
487 const stream = result_buf.writer();487 try result_buf.print("{s}\\Lib\\{s}\\um\\{s}", .{ install.path, install.version, arch_sub_dir });
488 try stream.print("{s}\\Lib\\{s}\\um\\{s}", .{ install.path, install.version, arch_sub_dir });
489488
490 var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {489 var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {
491 error.FileNotFound,490 error.FileNotFound,
lib/std/zig/Server.zig+57-157
...@@ -1,6 +1,20 @@...@@ -1,6 +1,20 @@
1in: std.fs.File,1const Server = @This();
2out: std.fs.File,2
3receive_fifo: std.fifo.LinearFifo(u8, .Dynamic),3const builtin = @import("builtin");
4
5const std = @import("std");
6const Allocator = std.mem.Allocator;
7const assert = std.debug.assert;
8const native_endian = builtin.target.cpu.arch.endian();
9const need_bswap = native_endian != .little;
10const Cache = std.Build.Cache;
11const OutMessage = std.zig.Server.Message;
12const InMessage = std.zig.Client.Message;
13const Reader = std.Io.Reader;
14const Writer = std.Io.Writer;
15
16in: *Reader,
17out: *Writer,
418
5pub const Message = struct {19pub const Message = struct {
6 pub const Header = extern struct {20 pub const Header = extern struct {
...@@ -94,9 +108,8 @@ pub const Message = struct {...@@ -94,9 +108,8 @@ pub const Message = struct {
94};108};
95109
96pub const Options = struct {110pub const Options = struct {
97 gpa: Allocator,111 in: *Reader,
98 in: std.fs.File,112 out: *Writer,
99 out: std.fs.File,
100 zig_version: []const u8,113 zig_version: []const u8,
101};114};
102115
...@@ -104,96 +117,40 @@ pub fn init(options: Options) !Server {...@@ -104,96 +117,40 @@ pub fn init(options: Options) !Server {
104 var s: Server = .{117 var s: Server = .{
105 .in = options.in,118 .in = options.in,
106 .out = options.out,119 .out = options.out,
107 .receive_fifo = std.fifo.LinearFifo(u8, .Dynamic).init(options.gpa),
108 };120 };
109 try s.serveStringMessage(.zig_version, options.zig_version);121 try s.serveStringMessage(.zig_version, options.zig_version);
110 return s;122 return s;
111}123}
112124
113pub fn deinit(s: *Server) void {
114 s.receive_fifo.deinit();
115 s.* = undefined;
116}
117
118pub fn receiveMessage(s: *Server) !InMessage.Header {125pub fn receiveMessage(s: *Server) !InMessage.Header {
119 const Header = InMessage.Header;126 return s.in.takeStruct(InMessage.Header, .little);
120 const fifo = &s.receive_fifo;
121 var last_amt_zero = false;
122
123 while (true) {
124 const buf = fifo.readableSlice(0);
125 assert(fifo.readableLength() == buf.len);
126 if (buf.len >= @sizeOf(Header)) {
127 const header: *align(1) const Header = @ptrCast(buf[0..@sizeOf(Header)]);
128 const bytes_len = bswap(header.bytes_len);
129 const tag = bswap(header.tag);
130
131 if (buf.len - @sizeOf(Header) >= bytes_len) {
132 fifo.discard(@sizeOf(Header));
133 return .{
134 .tag = tag,
135 .bytes_len = bytes_len,
136 };
137 } else {
138 const needed = bytes_len - (buf.len - @sizeOf(Header));
139 const write_buffer = try fifo.writableWithSize(needed);
140 const amt = try s.in.read(write_buffer);
141 fifo.update(amt);
142 continue;
143 }
144 }
145
146 const write_buffer = try fifo.writableWithSize(256);
147 const amt = try s.in.read(write_buffer);
148 fifo.update(amt);
149 if (amt == 0) {
150 if (last_amt_zero) return error.BrokenPipe;
151 last_amt_zero = true;
152 }
153 }
154}127}
155128
156pub fn receiveBody_u32(s: *Server) !u32 {129pub fn receiveBody_u32(s: *Server) !u32 {
157 const fifo = &s.receive_fifo;130 return s.in.takeInt(u32, .little);
158 const buf = fifo.readableSlice(0);
159 const result = @as(*align(1) const u32, @ptrCast(buf[0..4])).*;
160 fifo.discard(4);
161 return bswap(result);
162}131}
163132
164pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !void {133pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !void {
165 return s.serveMessage(.{134 try s.serveMessageHeader(.{
166 .tag = tag,135 .tag = tag,
167 .bytes_len = @as(u32, @intCast(msg.len)),136 .bytes_len = @intCast(msg.len),
168 }, &.{msg});137 });
138 try s.out.writeAll(msg);
139 try s.out.flush();
169}140}
170141
171pub fn serveMessage(142/// Don't forget to flush!
172 s: *const Server,143pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {
173 header: OutMessage.Header,144 try s.out.writeStruct(header, .little);
174 bufs: []const []const u8,
175) !void {
176 var iovecs: [10]std.posix.iovec_const = undefined;
177 const header_le = bswap(header);
178 iovecs[0] = .{
179 .base = @as([*]const u8, @ptrCast(&header_le)),
180 .len = @sizeOf(OutMessage.Header),
181 };
182 for (bufs, iovecs[1 .. bufs.len + 1]) |buf, *iovec| {
183 iovec.* = .{
184 .base = buf.ptr,
185 .len = buf.len,
186 };
187 }
188 try s.out.writevAll(iovecs[0 .. bufs.len + 1]);
189}145}
190146
191pub fn serveU64Message(s: *Server, tag: OutMessage.Tag, int: u64) !void {147pub fn serveU64Message(s: *const Server, tag: OutMessage.Tag, int: u64) !void {
192 const msg_le = bswap(int);148 try serveMessageHeader(s, .{
193 return s.serveMessage(.{
194 .tag = tag,149 .tag = tag,
195 .bytes_len = @sizeOf(u64),150 .bytes_len = @sizeOf(u64),
196 }, &.{std.mem.asBytes(&msg_le)});151 });
152 try s.out.writeInt(u64, int, .little);
153 try s.out.flush();
197}154}
198155
199pub fn serveEmitDigest(156pub fn serveEmitDigest(
...@@ -201,26 +158,22 @@ pub fn serveEmitDigest(...@@ -201,26 +158,22 @@ pub fn serveEmitDigest(
201 digest: *const [Cache.bin_digest_len]u8,158 digest: *const [Cache.bin_digest_len]u8,
202 header: OutMessage.EmitDigest,159 header: OutMessage.EmitDigest,
203) !void {160) !void {
204 try s.serveMessage(.{161 try s.serveMessageHeader(.{
205 .tag = .emit_digest,162 .tag = .emit_digest,
206 .bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)),163 .bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)),
207 }, &.{
208 std.mem.asBytes(&header),
209 digest,
210 });164 });
165 try s.out.writeStruct(header, .little);
166 try s.out.writeAll(digest);
167 try s.out.flush();
211}168}
212169
213pub fn serveTestResults(170pub fn serveTestResults(s: *Server, msg: OutMessage.TestResults) !void {
214 s: *Server,171 try s.serveMessageHeader(.{
215 msg: OutMessage.TestResults,
216) !void {
217 const msg_le = bswap(msg);
218 try s.serveMessage(.{
219 .tag = .test_results,172 .tag = .test_results,
220 .bytes_len = @intCast(@sizeOf(OutMessage.TestResults)),173 .bytes_len = @intCast(@sizeOf(OutMessage.TestResults)),
221 }, &.{
222 std.mem.asBytes(&msg_le),
223 });174 });
175 try s.out.writeStruct(msg, .little);
176 try s.out.flush();
224}177}
225178
226pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {179pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
...@@ -230,91 +183,38 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {...@@ -230,91 +183,38 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
230 };183 };
231 const bytes_len = @sizeOf(OutMessage.ErrorBundle) +184 const bytes_len = @sizeOf(OutMessage.ErrorBundle) +
232 4 * error_bundle.extra.len + error_bundle.string_bytes.len;185 4 * error_bundle.extra.len + error_bundle.string_bytes.len;
233 try s.serveMessage(.{186 try s.serveMessageHeader(.{
234 .tag = .error_bundle,187 .tag = .error_bundle,
235 .bytes_len = @intCast(bytes_len),188 .bytes_len = @intCast(bytes_len),
236 }, &.{
237 std.mem.asBytes(&eb_hdr),
238 // TODO: implement @ptrCast between slices changing the length
239 std.mem.sliceAsBytes(error_bundle.extra),
240 error_bundle.string_bytes,
241 });189 });
190 try s.out.writeStruct(eb_hdr, .little);
191 try s.out.writeSliceEndian(u32, error_bundle.extra, .little);
192 try s.out.writeAll(error_bundle.string_bytes);
193 try s.out.flush();
242}194}
243195
244pub const TestMetadata = struct {196pub const TestMetadata = struct {
245 names: []u32,197 names: []const u32,
246 expected_panic_msgs: []u32,198 expected_panic_msgs: []const u32,
247 string_bytes: []const u8,199 string_bytes: []const u8,
248};200};
249201
250pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {202pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
251 const header: OutMessage.TestMetadata = .{203 const header: OutMessage.TestMetadata = .{
252 .tests_len = bswap(@as(u32, @intCast(test_metadata.names.len))),204 .tests_len = @intCast(test_metadata.names.len),
253 .string_bytes_len = bswap(@as(u32, @intCast(test_metadata.string_bytes.len))),205 .string_bytes_len = @intCast(test_metadata.string_bytes.len),
254 };206 };
255 const trailing = 2;207 const trailing = 2;
256 const bytes_len = @sizeOf(OutMessage.TestMetadata) +208 const bytes_len = @sizeOf(OutMessage.TestMetadata) +
257 trailing * @sizeOf(u32) * test_metadata.names.len + test_metadata.string_bytes.len;209 trailing * @sizeOf(u32) * test_metadata.names.len + test_metadata.string_bytes.len;
258210
259 if (need_bswap) {211 try s.serveMessageHeader(.{
260 bswap_u32_array(test_metadata.names);
261 bswap_u32_array(test_metadata.expected_panic_msgs);
262 }
263 defer if (need_bswap) {
264 bswap_u32_array(test_metadata.names);
265 bswap_u32_array(test_metadata.expected_panic_msgs);
266 };
267
268 return s.serveMessage(.{
269 .tag = .test_metadata,212 .tag = .test_metadata,
270 .bytes_len = @intCast(bytes_len),213 .bytes_len = @intCast(bytes_len),
271 }, &.{
272 std.mem.asBytes(&header),
273 // TODO: implement @ptrCast between slices changing the length
274 std.mem.sliceAsBytes(test_metadata.names),
275 std.mem.sliceAsBytes(test_metadata.expected_panic_msgs),
276 test_metadata.string_bytes,
277 });214 });
215 try s.out.writeStruct(header, .little);
216 try s.out.writeSliceEndian(u32, test_metadata.names, .little);
217 try s.out.writeSliceEndian(u32, test_metadata.expected_panic_msgs, .little);
218 try s.out.writeAll(test_metadata.string_bytes);
219 try s.out.flush();
278}220}
279
280fn bswap(x: anytype) @TypeOf(x) {
281 if (!need_bswap) return x;
282
283 const T = @TypeOf(x);
284 switch (@typeInfo(T)) {
285 .@"enum" => return @as(T, @enumFromInt(@byteSwap(@intFromEnum(x)))),
286 .int => return @byteSwap(x),
287 .@"struct" => |info| switch (info.layout) {
288 .@"extern" => {
289 var result: T = undefined;
290 inline for (info.fields) |field| {
291 @field(result, field.name) = bswap(@field(x, field.name));
292 }
293 return result;
294 },
295 .@"packed" => {
296 const I = info.backing_integer.?;
297 return @as(T, @bitCast(@byteSwap(@as(I, @bitCast(x)))));
298 },
299 .auto => @compileError("auto layout struct"),
300 },
301 else => @compileError("bswap on type " ++ @typeName(T)),
302 }
303}
304
305fn bswap_u32_array(slice: []u32) void {
306 comptime assert(need_bswap);
307 for (slice) |*elem| elem.* = @byteSwap(elem.*);
308}
309
310const OutMessage = std.zig.Server.Message;
311const InMessage = std.zig.Client.Message;
312
313const Server = @This();
314const builtin = @import("builtin");
315const std = @import("std");
316const Allocator = std.mem.Allocator;
317const assert = std.debug.assert;
318const native_endian = builtin.target.cpu.arch.endian();
319const need_bswap = native_endian != .little;
320const Cache = std.Build.Cache;
lib/std/zig/WindowsSdk.zig+7-7
...@@ -1,11 +1,12 @@...@@ -1,11 +1,12 @@
1const WindowsSdk = @This();
2const builtin = @import("builtin");
3const std = @import("std");
4const Writer = std.Io.Writer;
5
1windows10sdk: ?Installation,6windows10sdk: ?Installation,
2windows81sdk: ?Installation,7windows81sdk: ?Installation,
3msvc_lib_dir: ?[]const u8,8msvc_lib_dir: ?[]const u8,
49
5const WindowsSdk = @This();
6const std = @import("std");
7const builtin = @import("builtin");
8
9const windows = std.os.windows;10const windows = std.os.windows;
10const RRF = windows.advapi32.RRF;11const RRF = windows.advapi32.RRF;
1112
...@@ -759,14 +760,13 @@ const MsvcLibDir = struct {...@@ -759,14 +760,13 @@ const MsvcLibDir = struct {
759 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {760 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {
760 if (entry.kind != .directory) continue;761 if (entry.kind != .directory) continue;
761762
762 var fbs = std.io.fixedBufferStream(&state_subpath_buf);763 var writer: Writer = .fixed(&state_subpath_buf);
763 const writer = fbs.writer();
764764
765 writer.writeAll(entry.name) catch unreachable;765 writer.writeAll(entry.name) catch unreachable;
766 writer.writeByte(std.fs.path.sep) catch unreachable;766 writer.writeByte(std.fs.path.sep) catch unreachable;
767 writer.writeAll("state.json") catch unreachable;767 writer.writeAll("state.json") catch unreachable;
768768
769 const json_contents = instances_dir.readFileAlloc(allocator, fbs.getWritten(), std.math.maxInt(usize)) catch continue;769 const json_contents = instances_dir.readFileAlloc(allocator, writer.buffered(), std.math.maxInt(usize)) catch continue;
770 defer allocator.free(json_contents);770 defer allocator.free(json_contents);
771771
772 var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue;772 var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue;
lib/std/zig/llvm.zig+6
...@@ -1,3 +1,9 @@...@@ -1,3 +1,9 @@
1pub const BitcodeReader = @import("llvm/BitcodeReader.zig");1pub const BitcodeReader = @import("llvm/BitcodeReader.zig");
2pub const bitcode_writer = @import("llvm/bitcode_writer.zig");2pub const bitcode_writer = @import("llvm/bitcode_writer.zig");
3pub const Builder = @import("llvm/Builder.zig");3pub const Builder = @import("llvm/Builder.zig");
4
5test {
6 _ = BitcodeReader;
7 _ = bitcode_writer;
8 _ = Builder;
9}
lib/std/zig/llvm/BitcodeReader.zig+16-12
...@@ -1,6 +1,11 @@...@@ -1,6 +1,11 @@
1const BitcodeReader = @This();
2
3const std = @import("../../std.zig");
4const assert = std.debug.assert;
5
1allocator: std.mem.Allocator,6allocator: std.mem.Allocator,
2record_arena: std.heap.ArenaAllocator.State,7record_arena: std.heap.ArenaAllocator.State,
3reader: std.io.AnyReader,8reader: *std.Io.Reader,
4keep_names: bool,9keep_names: bool,
5bit_buffer: u32,10bit_buffer: u32,
6bit_offset: u5,11bit_offset: u5,
...@@ -93,7 +98,7 @@ pub const Record = struct {...@@ -93,7 +98,7 @@ pub const Record = struct {
93};98};
9499
95pub const InitOptions = struct {100pub const InitOptions = struct {
96 reader: std.io.AnyReader,101 reader: *std.Io.Reader,
97 keep_names: bool = false,102 keep_names: bool = false,
98};103};
99pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {104pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {
...@@ -172,7 +177,7 @@ pub fn next(bc: *BitcodeReader) !?Item {...@@ -172,7 +177,7 @@ pub fn next(bc: *BitcodeReader) !?Item {
172177
173pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {178pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {
174 assert(bc.bit_offset == 0);179 assert(bc.bit_offset == 0);
175 try bc.reader.skipBytes(@as(u34, block.len) * 4, .{});180 try bc.reader.discardAll(4 * @as(usize, block.len));
176 try bc.endBlock();181 try bc.endBlock();
177}182}
178183
...@@ -371,19 +376,19 @@ fn align32Bits(bc: *BitcodeReader) void {...@@ -371,19 +376,19 @@ fn align32Bits(bc: *BitcodeReader) void {
371376
372fn read32Bits(bc: *BitcodeReader) !u32 {377fn read32Bits(bc: *BitcodeReader) !u32 {
373 assert(bc.bit_offset == 0);378 assert(bc.bit_offset == 0);
374 return bc.reader.readInt(u32, .little);379 return bc.reader.takeInt(u32, .little);
375}380}
376381
377fn readBytes(bc: *BitcodeReader, bytes: []u8) !void {382fn readBytes(bc: *BitcodeReader, bytes: []u8) !void {
378 assert(bc.bit_offset == 0);383 assert(bc.bit_offset == 0);
379 try bc.reader.readNoEof(bytes);384 try bc.reader.readSliceAll(bytes);
380385
381 const trailing_bytes = bytes.len % 4;386 const trailing_bytes = bytes.len % 4;
382 if (trailing_bytes > 0) {387 if (trailing_bytes > 0) {
383 var bit_buffer = [1]u8{0} ** 4;388 var bit_buffer: [4]u8 = @splat(0);
384 try bc.reader.readNoEof(bit_buffer[trailing_bytes..]);389 try bc.reader.readSliceAll(bit_buffer[trailing_bytes..]);
385 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);390 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);
386 bc.bit_offset = @intCast(trailing_bytes * 8);391 bc.bit_offset = @intCast(8 * trailing_bytes);
387 }392 }
388}393}
389394
...@@ -509,7 +514,6 @@ const Abbrev = struct {...@@ -509,7 +514,6 @@ const Abbrev = struct {
509 };514 };
510};515};
511516
512const assert = std.debug.assert;517test {
513const std = @import("../../std.zig");518 _ = &skipBlock;
514519}
515const BitcodeReader = @This();
lib/std/zig/perf_test.zig+6-8
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const Tokenizer = std.zig.Tokenizer;3const Tokenizer = std.zig.Tokenizer;
4const io = std.io;
5const fmtIntSizeBin = std.fmt.fmtIntSizeBin;4const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
65
7const source = @embedFile("../os.zig");6const source = @embedFile("../os.zig");
...@@ -22,16 +21,15 @@ pub fn main() !void {...@@ -22,16 +21,15 @@ pub fn main() !void {
22 const bytes_per_sec_float = @as(f64, @floatFromInt(source.len * iterations)) / elapsed_s;21 const bytes_per_sec_float = @as(f64, @floatFromInt(source.len * iterations)) / elapsed_s;
23 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));22 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));
2423
25 var stdout_file: std.fs.File = .stdout();24 var stdout_buffer: [1024]u8 = undefined;
26 const stdout = stdout_file.deprecatedWriter();25 var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
27 try stdout.print("parsing speed: {:.2}/s, {:.2} used \n", .{26 const stdout = &stdout_writer.interface;
28 fmtIntSizeBin(bytes_per_sec),27 try stdout.print("parsing speed: {Bi:.2}/s, {Bi:.2} used \n", .{ bytes_per_sec, memory_used });
29 fmtIntSizeBin(memory_used),28 try stdout.flush();
30 });
31}29}
3230
33fn testOnce() usize {31fn testOnce() usize {
34 var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);32 var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(&fixed_buffer_mem);
35 const allocator = fixed_buf_alloc.allocator();33 const allocator = fixed_buf_alloc.allocator();
36 _ = std.zig.Ast.parse(allocator, source, .zig) catch @panic("parse failure");34 _ = std.zig.Ast.parse(allocator, source, .zig) catch @panic("parse failure");
37 return fixed_buf_alloc.end_index;35 return fixed_buf_alloc.end_index;
lib/std/zig/system/linux.zig+17-18
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const mem = std.mem;3const mem = std.mem;
4const io = std.io;
5const fs = std.fs;4const fs = std.fs;
6const fmt = std.fmt;5const fmt = std.fmt;
7const testing = std.testing;6const testing = std.testing;
...@@ -344,8 +343,8 @@ fn testParser(...@@ -344,8 +343,8 @@ fn testParser(
344 expected_model: *const Target.Cpu.Model,343 expected_model: *const Target.Cpu.Model,
345 input: []const u8,344 input: []const u8,
346) !void {345) !void {
347 var fbs = io.fixedBufferStream(input);346 var r: std.Io.Reader = .fixed(input);
348 const result = try parser.parse(arch, fbs.reader());347 const result = try parser.parse(arch, &r);
349 try testing.expectEqual(expected_model, result.?.model);348 try testing.expectEqual(expected_model, result.?.model);
350 try testing.expect(expected_model.features.eql(result.?.features));349 try testing.expect(expected_model.features.eql(result.?.features));
351}350}
...@@ -357,20 +356,17 @@ fn testParser(...@@ -357,20 +356,17 @@ fn testParser(
357// When all the lines have been analyzed the finalize method is called.356// When all the lines have been analyzed the finalize method is called.
358fn CpuinfoParser(comptime impl: anytype) type {357fn CpuinfoParser(comptime impl: anytype) type {
359 return struct {358 return struct {
360 fn parse(arch: Target.Cpu.Arch, reader: anytype) anyerror!?Target.Cpu {359 fn parse(arch: Target.Cpu.Arch, reader: *std.Io.Reader) !?Target.Cpu {
361 var line_buf: [1024]u8 = undefined;
362 var obj: impl = .{};360 var obj: impl = .{};
363361 while (reader.takeDelimiterExclusive('\n')) |line| {
364 while (true) {
365 const line = (try reader.readUntilDelimiterOrEof(&line_buf, '\n')) orelse break;
366 const colon_pos = mem.indexOfScalar(u8, line, ':') orelse continue;362 const colon_pos = mem.indexOfScalar(u8, line, ':') orelse continue;
367 const key = mem.trimEnd(u8, line[0..colon_pos], " \t");363 const key = mem.trimEnd(u8, line[0..colon_pos], " \t");
368 const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t");364 const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t");
369365 if (!try obj.line_hook(key, value)) break;
370 if (!try obj.line_hook(key, value))366 } else |err| switch (err) {
371 break;367 error.EndOfStream => {},
368 else => |e| return e,
372 }369 }
373
374 return obj.finalize(arch);370 return obj.finalize(arch);
375 }371 }
376 };372 };
...@@ -383,15 +379,18 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {...@@ -383,15 +379,18 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {
383}379}
384380
385pub fn detectNativeCpuAndFeatures() ?Target.Cpu {381pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
386 var f = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {382 var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
387 else => return null,383 else => return null,
388 };384 };
389 defer f.close();385 defer file.close();
386
387 var buffer: [4096]u8 = undefined; // "flags" lines can get pretty long.
388 var file_reader = file.reader(&buffer);
390389
391 const current_arch = builtin.cpu.arch;390 const current_arch = builtin.cpu.arch;
392 switch (current_arch) {391 switch (current_arch) {
393 .arm, .armeb, .thumb, .thumbeb => {392 .arm, .armeb, .thumb, .thumbeb => {
394 return ArmCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;393 return ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
395 },394 },
396 .aarch64, .aarch64_be => {395 .aarch64, .aarch64_be => {
397 const registers = [12]u64{396 const registers = [12]u64{
...@@ -413,13 +412,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {...@@ -413,13 +412,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
413 return core;412 return core;
414 },413 },
415 .sparc64 => {414 .sparc64 => {
416 return SparcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;415 return SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
417 },416 },
418 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {417 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
419 return PowerpcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;418 return PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
420 },419 },
421 .riscv64, .riscv32 => {420 .riscv64, .riscv32 => {
422 return RiscvCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;421 return RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
423 },422 },
424 else => {},423 else => {},
425 }424 }
src/Compilation.zig+41-40
...@@ -12,6 +12,7 @@ const ThreadPool = std.Thread.Pool;...@@ -12,6 +12,7 @@ const ThreadPool = std.Thread.Pool;
12const WaitGroup = std.Thread.WaitGroup;12const WaitGroup = std.Thread.WaitGroup;
13const ErrorBundle = std.zig.ErrorBundle;13const ErrorBundle = std.zig.ErrorBundle;
14const fatal = std.process.fatal;14const fatal = std.process.fatal;
15const Writer = std.io.Writer;
1516
16const Value = @import("Value.zig");17const Value = @import("Value.zig");
17const Type = @import("Type.zig");18const Type = @import("Type.zig");
...@@ -44,6 +45,8 @@ const Builtin = @import("Builtin.zig");...@@ -44,6 +45,8 @@ const Builtin = @import("Builtin.zig");
44const LlvmObject = @import("codegen/llvm.zig").Object;45const LlvmObject = @import("codegen/llvm.zig").Object;
45const dev = @import("dev.zig");46const dev = @import("dev.zig");
4647
48const DeprecatedLinearFifo = @import("deprecated.zig").LinearFifo;
49
47pub const Config = @import("Compilation/Config.zig");50pub const Config = @import("Compilation/Config.zig");
4851
49/// General-purpose allocator. Used for both temporary and long-term storage.52/// General-purpose allocator. Used for both temporary and long-term storage.
...@@ -121,15 +124,15 @@ work_queues: [...@@ -121,15 +124,15 @@ work_queues: [
121 }124 }
122 break :len len;125 break :len len;
123 }126 }
124]std.fifo.LinearFifo(Job, .Dynamic),127]DeprecatedLinearFifo(Job),
125128
126/// These jobs are to invoke the Clang compiler to create an object file, which129/// These jobs are to invoke the Clang compiler to create an object file, which
127/// gets linked with the Compilation.130/// gets linked with the Compilation.
128c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),131c_object_work_queue: DeprecatedLinearFifo(*CObject),
129132
130/// These jobs are to invoke the RC compiler to create a compiled resource file (.res), which133/// These jobs are to invoke the RC compiler to create a compiled resource file (.res), which
131/// gets linked with the Compilation.134/// gets linked with the Compilation.
132win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic) else struct {135win32_resource_work_queue: if (dev.env.supports(.win32_resource)) DeprecatedLinearFifo(*Win32Resource) else struct {
133 pub fn ensureUnusedCapacity(_: @This(), _: u0) error{}!void {}136 pub fn ensureUnusedCapacity(_: @This(), _: u0) error{}!void {}
134 pub fn readItem(_: @This()) ?noreturn {137 pub fn readItem(_: @This()) ?noreturn {
135 return null;138 return null;
...@@ -995,13 +998,13 @@ pub const CObject = struct {...@@ -995,13 +998,13 @@ pub const CObject = struct {
995998
996 const file = fs.cwd().openFile(file_name, .{}) catch break :source_line 0;999 const file = fs.cwd().openFile(file_name, .{}) catch break :source_line 0;
997 defer file.close();1000 defer file.close();
998 file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;1001 var buffer: [1024]u8 = undefined;
9991002 var file_reader = file.reader(&buffer);
1000 var line = std.ArrayList(u8).init(eb.gpa);1003 file_reader.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
1001 defer line.deinit();1004 var aw: Writer.Allocating = .init(eb.gpa);
1002 file.deprecatedReader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;1005 defer aw.deinit();
10031006 _ = file_reader.interface.streamDelimiterEnding(&aw.writer, '\n') catch break :source_line 0;
1004 break :source_line try eb.addString(line.items);1007 break :source_line try eb.addString(aw.getWritten());
1005 };1008 };
10061009
1007 return .{1010 return .{
...@@ -1067,11 +1070,11 @@ pub const CObject = struct {...@@ -1067,11 +1070,11 @@ pub const CObject = struct {
1067 }1070 }
1068 };1071 };
10691072
1073 var buffer: [1024]u8 = undefined;
1070 const file = try fs.cwd().openFile(path, .{});1074 const file = try fs.cwd().openFile(path, .{});
1071 defer file.close();1075 defer file.close();
1072 var br = std.io.bufferedReader(file.deprecatedReader());1076 var file_reader = file.reader(&buffer);
1073 const reader = br.reader();1077 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface });
1074 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });
1075 defer bc.deinit();1078 defer bc.deinit();
10761079
1077 var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;1080 var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;
...@@ -1873,15 +1876,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1873,15 +1876,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18731876
1874 if (options.verbose_llvm_cpu_features) {1877 if (options.verbose_llvm_cpu_features) {
1875 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {1878 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
1876 std.debug.lockStdErr();1879 const stderr_w = std.debug.lockStderrWriter(&.{});
1877 defer std.debug.unlockStdErr();1880 defer std.debug.unlockStderrWriter();
1878 const stderr = fs.File.stderr().deprecatedWriter();1881 stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1879 nosuspend {1882 stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
1880 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;1883 stderr_w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
1881 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;1884 stderr_w.print(" features: {s}\n", .{cf}) catch {};
1882 stderr.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
1883 stderr.print(" features: {s}\n", .{cf}) catch {};
1884 }
1885 }1885 }
1886 }1886 }
18871887
...@@ -2483,7 +2483,7 @@ pub fn destroy(comp: *Compilation) void {...@@ -2483,7 +2483,7 @@ pub fn destroy(comp: *Compilation) void {
2483 if (comp.zcu) |zcu| zcu.deinit();2483 if (comp.zcu) |zcu| zcu.deinit();
2484 comp.cache_use.deinit();2484 comp.cache_use.deinit();
24852485
2486 for (comp.work_queues) |work_queue| work_queue.deinit();2486 for (&comp.work_queues) |*work_queue| work_queue.deinit();
2487 comp.c_object_work_queue.deinit();2487 comp.c_object_work_queue.deinit();
2488 comp.win32_resource_work_queue.deinit();2488 comp.win32_resource_work_queue.deinit();
24892489
...@@ -3931,11 +3931,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3931,11 +3931,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3931 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.3931 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
3932 // However, we haven't reported any such error.3932 // However, we haven't reported any such error.
3933 // This is a compiler bug.3933 // This is a compiler bug.
3934 const stderr = fs.File.stderr().deprecatedWriter();3934 var stderr_w = std.debug.lockStderrWriter(&.{});
3935 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");3935 defer std.debug.unlockStderrWriter();
3936 try stderr.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});3936 try stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3937 try stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
3937 while (ref) |r| {3938 while (ref) |r| {
3938 try stderr.print("referenced by: {f}{s}\n", .{3939 try stderr_w.print("referenced by: {f}{s}\n", .{
3939 zcu.fmtAnalUnit(r.referencer),3940 zcu.fmtAnalUnit(r.referencer),
3940 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",3941 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
3941 });3942 });
...@@ -6213,13 +6214,10 @@ fn spawnZigRc(...@@ -6213,13 +6214,10 @@ fn spawnZigRc(
6213 const stdout = poller.fifo(.stdout);6214 const stdout = poller.fifo(.stdout);
62146215
6215 poll: while (true) {6216 poll: while (true) {
6216 while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) {6217 while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) if (!try poller.poll()) break :poll;
6217 if (!(try poller.poll())) break :poll;6218 var header: std.zig.Server.Message.Header = undefined;
6218 }6219 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(std.zig.Server.Message.Header));
6219 const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable;6220 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll;
6220 while (stdout.readableLength() < header.bytes_len) {
6221 if (!(try poller.poll())) break :poll;
6222 }
6223 const body = stdout.readableSliceOfLen(header.bytes_len);6221 const body = stdout.readableSliceOfLen(header.bytes_len);
62246222
6225 switch (header.tag) {6223 switch (header.tag) {
...@@ -7209,13 +7207,16 @@ pub fn lockAndSetMiscFailure(...@@ -7209,13 +7207,16 @@ pub fn lockAndSetMiscFailure(
7209}7207}
72107208
7211pub fn dump_argv(argv: []const []const u8) void {7209pub fn dump_argv(argv: []const []const u8) void {
7212 std.debug.lockStdErr();7210 var buffer: [64]u8 = undefined;
7213 defer std.debug.unlockStdErr();7211 const stderr = std.debug.lockStderrWriter(&buffer);
7214 const stderr = fs.File.stderr().deprecatedWriter();7212 defer std.debug.unlockStderrWriter();
7215 for (argv[0 .. argv.len - 1]) |arg| {7213 nosuspend {
7216 nosuspend stderr.print("{s} ", .{arg}) catch return;7214 for (argv) |arg| {
7215 stderr.writeAll(arg) catch return;
7216 (stderr.writableArray(1) catch return)[0] = ' ';
7217 }
7218 stderr.buffer[stderr.end - 1] = '\n';
7217 }7219 }
7218 nosuspend stderr.print("{s}\n", .{argv[argv.len - 1]}) catch {};
7219}7220}
72207221
7221pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {7222pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
src/Zcu.zig+1-1
...@@ -2821,7 +2821,7 @@ pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {...@@ -2821,7 +2821,7 @@ pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
2821 var buffer: [2000]u8 = undefined;2821 var buffer: [2000]u8 = undefined;
2822 var file_reader = cache_file.reader(&buffer);2822 var file_reader = cache_file.reader(&buffer);
2823 return result: {2823 return result: {
2824 const header = file_reader.interface.takeStructReference(Zir.Header) catch |err| break :result err;2824 const header = file_reader.interface.takeStructPointer(Zir.Header) catch |err| break :result err;
2825 break :result loadZirCacheBody(gpa, header.*, &file_reader.interface);2825 break :result loadZirCacheBody(gpa, header.*, &file_reader.interface);
2826 } catch |err| switch (err) {2826 } catch |err| switch (err) {
2827 error.ReadFailed => return file_reader.err.?,2827 error.ReadFailed => return file_reader.err.?,
src/Zcu/PerThread.zig+1-1
...@@ -349,7 +349,7 @@ fn loadZirZoirCache(...@@ -349,7 +349,7 @@ fn loadZirZoirCache(
349 const cache_br = &cache_fr.interface;349 const cache_br = &cache_fr.interface;
350350
351 // First we read the header to determine the lengths of arrays.351 // First we read the header to determine the lengths of arrays.
352 const header = (cache_br.takeStructReference(Header) catch |err| switch (err) {352 const header = (cache_br.takeStructPointer(Header) catch |err| switch (err) {
353 error.ReadFailed => return cache_fr.err.?,353 error.ReadFailed => return cache_fr.err.?,
354 // This can happen if Zig bails out of this function between creating354 // This can happen if Zig bails out of this function between creating
355 // the cached file and writing it.355 // the cached file and writing it.
src/deprecated.zig-262
...@@ -52,15 +52,6 @@ pub fn LinearFifo(comptime T: type) type {...@@ -52,15 +52,6 @@ pub fn LinearFifo(comptime T: type) type {
52 }52 }
53 }53 }
5454
55 /// Reduce allocated capacity to `size`.
56 pub fn shrink(self: *Self, size: usize) void {
57 assert(size >= self.count);
58 self.realign();
59 self.buf = self.allocator.realloc(self.buf, size) catch |e| switch (e) {
60 error.OutOfMemory => return, // no problem, capacity is still correct then.
61 };
62 }
63
64 /// Ensure that the buffer can fit at least `size` items55 /// Ensure that the buffer can fit at least `size` items
65 pub fn ensureTotalCapacity(self: *Self, size: usize) !void {56 pub fn ensureTotalCapacity(self: *Self, size: usize) !void {
66 if (self.buf.len >= size) return;57 if (self.buf.len >= size) return;
...@@ -76,11 +67,6 @@ pub fn LinearFifo(comptime T: type) type {...@@ -76,11 +67,6 @@ pub fn LinearFifo(comptime T: type) type {
76 return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory);67 return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory);
77 }68 }
7869
79 /// Returns number of items currently in fifo
80 pub fn readableLength(self: Self) usize {
81 return self.count;
82 }
83
84 /// Returns a writable slice from the 'read' end of the fifo70 /// Returns a writable slice from the 'read' end of the fifo
85 fn readableSliceMut(self: Self, offset: usize) []T {71 fn readableSliceMut(self: Self, offset: usize) []T {
86 if (offset > self.count) return &[_]T{};72 if (offset > self.count) return &[_]T{};
...@@ -95,22 +81,6 @@ pub fn LinearFifo(comptime T: type) type {...@@ -95,22 +81,6 @@ pub fn LinearFifo(comptime T: type) type {
95 }81 }
96 }82 }
9783
98 /// Returns a readable slice from `offset`
99 pub fn readableSlice(self: Self, offset: usize) []const T {
100 return self.readableSliceMut(offset);
101 }
102
103 pub fn readableSliceOfLen(self: *Self, len: usize) []const T {
104 assert(len <= self.count);
105 const buf = self.readableSlice(0);
106 if (buf.len >= len) {
107 return buf[0..len];
108 } else {
109 self.realign();
110 return self.readableSlice(0)[0..len];
111 }
112 }
113
114 /// Discard first `count` items in the fifo84 /// Discard first `count` items in the fifo
115 pub fn discard(self: *Self, count: usize) void {85 pub fn discard(self: *Self, count: usize) void {
116 assert(count <= self.count);86 assert(count <= self.count);
...@@ -143,28 +113,6 @@ pub fn LinearFifo(comptime T: type) type {...@@ -143,28 +113,6 @@ pub fn LinearFifo(comptime T: type) type {
143 return c;113 return c;
144 }114 }
145115
146 /// Read data from the fifo into `dst`, returns number of items copied.
147 pub fn read(self: *Self, dst: []T) usize {
148 var dst_left = dst;
149
150 while (dst_left.len > 0) {
151 const slice = self.readableSlice(0);
152 if (slice.len == 0) break;
153 const n = @min(slice.len, dst_left.len);
154 @memcpy(dst_left[0..n], slice[0..n]);
155 self.discard(n);
156 dst_left = dst_left[n..];
157 }
158
159 return dst.len - dst_left.len;
160 }
161
162 /// Same as `read` except it returns an error union
163 /// The purpose of this function existing is to match `std.io.Reader` API.
164 fn readFn(self: *Self, dest: []u8) error{}!usize {
165 return self.read(dest);
166 }
167
168 /// Returns number of items available in fifo116 /// Returns number of items available in fifo
169 pub fn writableLength(self: Self) usize {117 pub fn writableLength(self: Self) usize {
170 return self.buf.len - self.count;118 return self.buf.len - self.count;
...@@ -183,20 +131,6 @@ pub fn LinearFifo(comptime T: type) type {...@@ -183,20 +131,6 @@ pub fn LinearFifo(comptime T: type) type {
183 }131 }
184 }132 }
185133
186 /// Returns a writable buffer of at least `size` items, allocating memory as needed.
187 /// Use `fifo.update` once you've written data to it.
188 pub fn writableWithSize(self: *Self, size: usize) ![]T {
189 try self.ensureUnusedCapacity(size);
190
191 // try to avoid realigning buffer
192 var slice = self.writableSlice(0);
193 if (slice.len < size) {
194 self.realign();
195 slice = self.writableSlice(0);
196 }
197 return slice;
198 }
199
200 /// Update the tail location of the buffer (usually follows use of writable/writableWithSize)134 /// Update the tail location of the buffer (usually follows use of writable/writableWithSize)
201 pub fn update(self: *Self, count: usize) void {135 pub fn update(self: *Self, count: usize) void {
202 assert(self.count + count <= self.buf.len);136 assert(self.count + count <= self.buf.len);
...@@ -231,201 +165,5 @@ pub fn LinearFifo(comptime T: type) type {...@@ -231,201 +165,5 @@ pub fn LinearFifo(comptime T: type) type {
231 self.buf[tail] = item;165 self.buf[tail] = item;
232 self.update(1);166 self.update(1);
233 }167 }
234
235 /// Appends the data in `src` to the fifo.
236 /// Allocates more memory as necessary
237 pub fn write(self: *Self, src: []const T) !void {
238 try self.ensureUnusedCapacity(src.len);
239
240 return self.writeAssumeCapacity(src);
241 }
242
243 /// Same as `write` except it returns the number of bytes written, which is always the same
244 /// as `bytes.len`. The purpose of this function existing is to match `std.io.Writer` API.
245 fn appendWrite(self: *Self, bytes: []const u8) error{OutOfMemory}!usize {
246 try self.write(bytes);
247 return bytes.len;
248 }
249
250 /// Make `count` items available before the current read location
251 fn rewind(self: *Self, count: usize) void {
252 assert(self.writableLength() >= count);
253
254 var head = self.head + (self.buf.len - count);
255 head &= self.buf.len - 1;
256 self.head = head;
257 self.count += count;
258 }
259
260 /// Place data back into the read stream
261 pub fn unget(self: *Self, src: []const T) !void {
262 try self.ensureUnusedCapacity(src.len);
263
264 self.rewind(src.len);
265
266 const slice = self.readableSliceMut(0);
267 if (src.len < slice.len) {
268 @memcpy(slice[0..src.len], src);
269 } else {
270 @memcpy(slice, src[0..slice.len]);
271 const slice2 = self.readableSliceMut(slice.len);
272 @memcpy(slice2[0 .. src.len - slice.len], src[slice.len..]);
273 }
274 }
275
276 /// Returns the item at `offset`.
277 /// Asserts offset is within bounds.
278 pub fn peekItem(self: Self, offset: usize) T {
279 assert(offset < self.count);
280
281 var index = self.head + offset;
282 index &= self.buf.len - 1;
283 return self.buf[index];
284 }
285
286 pub fn toOwnedSlice(self: *Self) Allocator.Error![]T {
287 if (self.head != 0) self.realign();
288 assert(self.head == 0);
289 assert(self.count <= self.buf.len);
290 const allocator = self.allocator;
291 if (allocator.resize(self.buf, self.count)) {
292 const result = self.buf[0..self.count];
293 self.* = Self.init(allocator);
294 return result;
295 }
296 const new_memory = try allocator.dupe(T, self.buf[0..self.count]);
297 allocator.free(self.buf);
298 self.* = Self.init(allocator);
299 return new_memory;
300 }
301 };168 };
302}169}
303
304test "LinearFifo(u8, .Dynamic) discard(0) from empty buffer should not error on overflow" {
305 var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
306 defer fifo.deinit();
307
308 // If overflow is not explicitly allowed this will crash in debug / safe mode
309 fifo.discard(0);
310}
311
312test "LinearFifo(u8, .Dynamic)" {
313 var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
314 defer fifo.deinit();
315
316 try fifo.write("HELLO");
317 try testing.expectEqual(@as(usize, 5), fifo.readableLength());
318 try testing.expectEqualSlices(u8, "HELLO", fifo.readableSlice(0));
319
320 {
321 var i: usize = 0;
322 while (i < 5) : (i += 1) {
323 try fifo.write(&[_]u8{fifo.peekItem(i)});
324 }
325 try testing.expectEqual(@as(usize, 10), fifo.readableLength());
326 try testing.expectEqualSlices(u8, "HELLOHELLO", fifo.readableSlice(0));
327 }
328
329 {
330 try testing.expectEqual(@as(u8, 'H'), fifo.readItem().?);
331 try testing.expectEqual(@as(u8, 'E'), fifo.readItem().?);
332 try testing.expectEqual(@as(u8, 'L'), fifo.readItem().?);
333 try testing.expectEqual(@as(u8, 'L'), fifo.readItem().?);
334 try testing.expectEqual(@as(u8, 'O'), fifo.readItem().?);
335 }
336 try testing.expectEqual(@as(usize, 5), fifo.readableLength());
337
338 { // Writes that wrap around
339 try testing.expectEqual(@as(usize, 11), fifo.writableLength());
340 try testing.expectEqual(@as(usize, 6), fifo.writableSlice(0).len);
341 fifo.writeAssumeCapacity("6<chars<11");
342 try testing.expectEqualSlices(u8, "HELLO6<char", fifo.readableSlice(0));
343 try testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(11));
344 try testing.expectEqualSlices(u8, "11", fifo.readableSlice(13));
345 try testing.expectEqualSlices(u8, "", fifo.readableSlice(15));
346 fifo.discard(11);
347 try testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(0));
348 fifo.discard(4);
349 try testing.expectEqual(@as(usize, 0), fifo.readableLength());
350 }
351
352 {
353 const buf = try fifo.writableWithSize(12);
354 try testing.expectEqual(@as(usize, 12), buf.len);
355 var i: u8 = 0;
356 while (i < 10) : (i += 1) {
357 buf[i] = i + 'a';
358 }
359 fifo.update(10);
360 try testing.expectEqualSlices(u8, "abcdefghij", fifo.readableSlice(0));
361 }
362
363 {
364 try fifo.unget("prependedstring");
365 var result: [30]u8 = undefined;
366 try testing.expectEqualSlices(u8, "prependedstringabcdefghij", result[0..fifo.read(&result)]);
367 try fifo.unget("b");
368 try fifo.unget("a");
369 try testing.expectEqualSlices(u8, "ab", result[0..fifo.read(&result)]);
370 }
371
372 fifo.shrink(0);
373
374 {
375 try fifo.writer().print("{s}, {s}!", .{ "Hello", "World" });
376 var result: [30]u8 = undefined;
377 try testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);
378 try testing.expectEqual(@as(usize, 0), fifo.readableLength());
379 }
380
381 {
382 try fifo.writer().writeAll("This is a test");
383 var result: [30]u8 = undefined;
384 try testing.expectEqualSlices(u8, "This", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
385 try testing.expectEqualSlices(u8, "is", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
386 try testing.expectEqualSlices(u8, "a", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
387 try testing.expectEqualSlices(u8, "test", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
388 }
389
390 {
391 try fifo.ensureTotalCapacity(1);
392 var in_fbs = std.io.fixedBufferStream("pump test");
393 var out_buf: [50]u8 = undefined;
394 var out_fbs = std.io.fixedBufferStream(&out_buf);
395 try fifo.pump(in_fbs.reader(), out_fbs.writer());
396 try testing.expectEqualSlices(u8, in_fbs.buffer, out_fbs.getWritten());
397 }
398}
399
400test LinearFifo {
401 inline for ([_]type{ u1, u8, u16, u64 }) |T| {
402 const FifoType = LinearFifo(T);
403 var fifo: FifoType = .init(testing.allocator);
404 defer fifo.deinit();
405
406 try fifo.write(&[_]T{ 0, 1, 1, 0, 1 });
407 try testing.expectEqual(@as(usize, 5), fifo.readableLength());
408
409 {
410 try testing.expectEqual(@as(T, 0), fifo.readItem().?);
411 try testing.expectEqual(@as(T, 1), fifo.readItem().?);
412 try testing.expectEqual(@as(T, 1), fifo.readItem().?);
413 try testing.expectEqual(@as(T, 0), fifo.readItem().?);
414 try testing.expectEqual(@as(T, 1), fifo.readItem().?);
415 try testing.expectEqual(@as(usize, 0), fifo.readableLength());
416 }
417
418 {
419 try fifo.writeItem(1);
420 try fifo.writeItem(1);
421 try fifo.writeItem(1);
422 try testing.expectEqual(@as(usize, 3), fifo.readableLength());
423 }
424
425 {
426 var readBuf: [3]T = undefined;
427 const n = fifo.read(&readBuf);
428 try testing.expectEqual(@as(usize, 3), n); // NOTE: It should be the number of items.
429 }
430 }
431}
src/main.zig+25-21
...@@ -65,8 +65,10 @@ pub fn wasi_cwd() std.os.wasi.fd_t {...@@ -65,8 +65,10 @@ pub fn wasi_cwd() std.os.wasi.fd_t {
6565
66const fatal = std.process.fatal;66const fatal = std.process.fatal;
6767
68/// This can be global since stdin is a singleton.
69var stdin_buffer: [4096]u8 align(std.heap.page_size_min) = undefined;
68/// This can be global since stdout is a singleton.70/// This can be global since stdout is a singleton.
69var stdio_buffer: [4096]u8 = undefined;71var stdout_buffer: [4096]u8 align(std.heap.page_size_min) = undefined;
7072
71/// Shaming all the locations that inappropriately use an O(N) search algorithm.73/// Shaming all the locations that inappropriately use an O(N) search algorithm.
72/// Please delete this and fix the compilation errors!74/// Please delete this and fix the compilation errors!
...@@ -3564,10 +3566,12 @@ fn buildOutputType(...@@ -3564,10 +3566,12 @@ fn buildOutputType(
3564 switch (listen) {3566 switch (listen) {
3565 .none => {},3567 .none => {},
3566 .stdio => {3568 .stdio => {
3569 var stdin_reader = fs.File.stdin().reader(&stdin_buffer);
3570 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
3567 try serve(3571 try serve(
3568 comp,3572 comp,
3569 .stdin(),3573 &stdin_reader.interface,
3570 .stdout(),3574 &stdout_writer.interface,
3571 test_exec_args.items,3575 test_exec_args.items,
3572 self_exe_path,3576 self_exe_path,
3573 arg_mode,3577 arg_mode,
...@@ -3587,10 +3591,13 @@ fn buildOutputType(...@@ -3587,10 +3591,13 @@ fn buildOutputType(
3587 const conn = try server.accept();3591 const conn = try server.accept();
3588 defer conn.stream.close();3592 defer conn.stream.close();
35893593
3594 var input = conn.stream.reader(&stdin_buffer);
3595 var output = conn.stream.writer(&stdout_buffer);
3596
3590 try serve(3597 try serve(
3591 comp,3598 comp,
3592 .{ .handle = conn.stream.handle },3599 input.interface(),
3593 .{ .handle = conn.stream.handle },3600 &output.interface,
3594 test_exec_args.items,3601 test_exec_args.items,
3595 self_exe_path,3602 self_exe_path,
3596 arg_mode,3603 arg_mode,
...@@ -4056,8 +4063,8 @@ fn saveState(comp: *Compilation, incremental: bool) void {...@@ -4056,8 +4063,8 @@ fn saveState(comp: *Compilation, incremental: bool) void {
40564063
4057fn serve(4064fn serve(
4058 comp: *Compilation,4065 comp: *Compilation,
4059 in: fs.File,4066 in: *std.Io.Reader,
4060 out: fs.File,4067 out: *std.Io.Writer,
4061 test_exec_args: []const ?[]const u8,4068 test_exec_args: []const ?[]const u8,
4062 self_exe_path: ?[]const u8,4069 self_exe_path: ?[]const u8,
4063 arg_mode: ArgMode,4070 arg_mode: ArgMode,
...@@ -4067,12 +4074,10 @@ fn serve(...@@ -4067,12 +4074,10 @@ fn serve(
4067 const gpa = comp.gpa;4074 const gpa = comp.gpa;
40684075
4069 var server = try Server.init(.{4076 var server = try Server.init(.{
4070 .gpa = gpa,
4071 .in = in,4077 .in = in,
4072 .out = out,4078 .out = out,
4073 .zig_version = build_options.version,4079 .zig_version = build_options.version,
4074 });4080 });
4075 defer server.deinit();
40764081
4077 var child_pid: ?std.process.Child.Id = null;4082 var child_pid: ?std.process.Child.Id = null;
40784083
...@@ -5494,10 +5499,10 @@ fn jitCmd(...@@ -5494,10 +5499,10 @@ fn jitCmd(
5494 defer comp.destroy();5499 defer comp.destroy();
54955500
5496 if (options.server) {5501 if (options.server) {
5502 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
5497 var server: std.zig.Server = .{5503 var server: std.zig.Server = .{
5498 .out = fs.File.stdout(),5504 .out = &stdout_writer.interface,
5499 .in = undefined, // won't be receiving messages5505 .in = undefined, // won't be receiving messages
5500 .receive_fifo = undefined, // won't be receiving messages
5501 };5506 };
55025507
5503 try comp.update(root_prog_node);5508 try comp.update(root_prog_node);
...@@ -6061,7 +6066,7 @@ fn cmdAstCheck(...@@ -6061,7 +6066,7 @@ fn cmdAstCheck(
6061 };6066 };
6062 } else fs.File.stdin();6067 } else fs.File.stdin();
6063 defer if (zig_source_path != null) f.close();6068 defer if (zig_source_path != null) f.close();
6064 var file_reader: fs.File.Reader = f.reader(&stdio_buffer);6069 var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
6065 break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| {6070 break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| {
6066 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });6071 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
6067 };6072 };
...@@ -6079,7 +6084,7 @@ fn cmdAstCheck(...@@ -6079,7 +6084,7 @@ fn cmdAstCheck(
60796084
6080 const tree = try Ast.parse(arena, source, mode);6085 const tree = try Ast.parse(arena, source, mode);
60816086
6082 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6087 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6083 const stdout_bw = &stdout_writer.interface;6088 const stdout_bw = &stdout_writer.interface;
6084 switch (mode) {6089 switch (mode) {
6085 .zig => {6090 .zig => {
...@@ -6294,7 +6299,7 @@ fn detectNativeCpuWithLLVM(...@@ -6294,7 +6299,7 @@ fn detectNativeCpuWithLLVM(
6294}6299}
62956300
6296fn printCpu(cpu: std.Target.Cpu) !void {6301fn printCpu(cpu: std.Target.Cpu) !void {
6297 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6302 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6298 const stdout_bw = &stdout_writer.interface;6303 const stdout_bw = &stdout_writer.interface;
62996304
6300 if (cpu.model.llvm_name) |llvm_name| {6305 if (cpu.model.llvm_name) |llvm_name| {
...@@ -6343,7 +6348,7 @@ fn cmdDumpLlvmInts(...@@ -6343,7 +6348,7 @@ fn cmdDumpLlvmInts(
6343 const dl = tm.createTargetDataLayout();6348 const dl = tm.createTargetDataLayout();
6344 const context = llvm.Context.create();6349 const context = llvm.Context.create();
63456350
6346 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6351 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6347 const stdout_bw = &stdout_writer.interface;6352 const stdout_bw = &stdout_writer.interface;
6348 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {6353 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
6349 const int_type = context.intType(bits);6354 const int_type = context.intType(bits);
...@@ -6372,9 +6377,8 @@ fn cmdDumpZir(...@@ -6372,9 +6377,8 @@ fn cmdDumpZir(
6372 defer f.close();6377 defer f.close();
63736378
6374 const zir = try Zcu.loadZirCache(arena, f);6379 const zir = try Zcu.loadZirCache(arena, f);
6375 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6380 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6376 const stdout_bw = &stdout_writer.interface;6381 const stdout_bw = &stdout_writer.interface;
6377
6378 {6382 {
6379 const instruction_bytes = zir.instructions.len *6383 const instruction_bytes = zir.instructions.len *
6380 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include6384 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
...@@ -6420,7 +6424,7 @@ fn cmdChangelist(...@@ -6420,7 +6424,7 @@ fn cmdChangelist(
6420 var f = fs.cwd().openFile(old_source_path, .{}) catch |err|6424 var f = fs.cwd().openFile(old_source_path, .{}) catch |err|
6421 fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) });6425 fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
6422 defer f.close();6426 defer f.close();
6423 var file_reader: fs.File.Reader = f.reader(&stdio_buffer);6427 var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
6424 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|6428 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|
6425 fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) });6429 fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
6426 };6430 };
...@@ -6428,7 +6432,7 @@ fn cmdChangelist(...@@ -6428,7 +6432,7 @@ fn cmdChangelist(
6428 var f = fs.cwd().openFile(new_source_path, .{}) catch |err|6432 var f = fs.cwd().openFile(new_source_path, .{}) catch |err|
6429 fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) });6433 fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
6430 defer f.close();6434 defer f.close();
6431 var file_reader: fs.File.Reader = f.reader(&stdio_buffer);6435 var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
6432 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|6436 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|
6433 fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) });6437 fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
6434 };6438 };
...@@ -6460,7 +6464,7 @@ fn cmdChangelist(...@@ -6460,7 +6464,7 @@ fn cmdChangelist(
6460 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;6464 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
6461 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);6465 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
64626466
6463 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6467 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6464 const stdout_bw = &stdout_writer.interface;6468 const stdout_bw = &stdout_writer.interface;
6465 {6469 {
6466 try stdout_bw.print("Instruction mappings:\n", .{});6470 try stdout_bw.print("Instruction mappings:\n", .{});
...@@ -6920,7 +6924,7 @@ fn cmdFetch(...@@ -6920,7 +6924,7 @@ fn cmdFetch(
69206924
6921 const name = switch (save) {6925 const name = switch (save) {
6922 .no => {6926 .no => {
6923 var stdout = fs.File.stdout().writerStreaming(&stdio_buffer);6927 var stdout = fs.File.stdout().writerStreaming(&stdout_buffer);
6924 try stdout.interface.print("{s}\n", .{package_hash_slice});6928 try stdout.interface.print("{s}\n", .{package_hash_slice});
6925 try stdout.interface.flush();6929 try stdout.interface.flush();
6926 return cleanExit();6930 return cleanExit();
test/src/Cases.zig-2
...@@ -800,8 +800,6 @@ const TestManifestConfigDefaults = struct {...@@ -800,8 +800,6 @@ const TestManifestConfigDefaults = struct {
800 }800 }
801 // Windows801 // Windows
802 defaults = defaults ++ "x86_64-windows" ++ ",";802 defaults = defaults ++ "x86_64-windows" ++ ",";
803 // Wasm
804 defaults = defaults ++ "wasm32-wasi";
805 break :blk defaults;803 break :blk defaults;
806 };804 };
807 } else if (std.mem.eql(u8, key, "output_mode")) {805 } else if (std.mem.eql(u8, key, "output_mode")) {
test/tests.zig+10-9
...@@ -1335,15 +1335,16 @@ const test_targets = blk: {...@@ -1335,15 +1335,16 @@ const test_targets = blk: {
13351335
1336 // WASI Targets1336 // WASI Targets
13371337
1338 .{1338 // TODO: lowerTry for pointers
1339 .target = .{1339 //.{
1340 .cpu_arch = .wasm32,1340 // .target = .{
1341 .os_tag = .wasi,1341 // .cpu_arch = .wasm32,
1342 .abi = .none,1342 // .os_tag = .wasi,
1343 },1343 // .abi = .none,
1344 .use_llvm = false,1344 // },
1345 .use_lld = false,1345 // .use_llvm = false,
1346 },1346 // .use_lld = false,
1347 //},
1347 .{1348 .{
1348 .target = .{1349 .target = .{
1349 .cpu_arch = .wasm32,1350 .cpu_arch = .wasm32,