authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-18 18:22:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-18 18:22:14-07:00
log5d2faeb8f3acbcf28e08f1bd126e1cd8191afd07
treea7fd512629ec4da8dea465e1bf43c1f6cba891ff
parent64e2551b3ae521d17468f92a50f98c397eca1fd5
parent7c7e081cb2f0df87c314a6d7a9b2d10bf140d591

Merge remote-tracking branch 'origin/more' into wrangle-writer-buffering


47 files changed, 1234 insertions(+), 840 deletions(-)

ci/riscv64-linux-debug.sh+5-2
...@@ -49,10 +49,13 @@ unset CXX...@@ -49,10 +49,13 @@ unset CXX
49ninja install49ninja install
5050
51# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.51# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
52stage3-debug/bin/zig build test-cases test-modules test-unit test-standalone test-c-abi test-link test-stack-traces test-asm-link test-llvm-ir docs \52stage3-debug/bin/zig build test-cases test-modules test-unit test-standalone test-c-abi test-link test-stack-traces test-asm-link test-llvm-ir \
53 --maxrss 34359738368 \53 --maxrss 68719476736 \
54 -Dstatic-llvm \54 -Dstatic-llvm \
55 -Dskip-non-native \55 -Dskip-non-native \
56 -Dskip-single-threaded \
57 -Dskip-translate-c \
58 -Dskip-run-translated-c \
56 -Dtarget=native-native-musl \59 -Dtarget=native-native-musl \
57 --search-prefix "$PREFIX" \60 --search-prefix "$PREFIX" \
58 --zig-lib-dir "$PWD/../lib"61 --zig-lib-dir "$PWD/../lib"
ci/riscv64-linux-release.sh+5-2
...@@ -49,10 +49,13 @@ unset CXX...@@ -49,10 +49,13 @@ unset CXX
49ninja install49ninja install
5050
51# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.51# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
52stage3-release/bin/zig build test-cases test-modules test-unit test-standalone test-c-abi test-link test-stack-traces test-asm-link test-llvm-ir docs \52stage3-release/bin/zig build test-cases test-modules test-unit test-standalone test-c-abi test-link test-stack-traces test-asm-link test-llvm-ir \
53 --maxrss 34359738368 \53 --maxrss 68719476736 \
54 -Dstatic-llvm \54 -Dstatic-llvm \
55 -Dskip-non-native \55 -Dskip-non-native \
56 -Dskip-single-threaded \
57 -Dskip-translate-c \
58 -Dskip-run-translated-c \
56 -Dtarget=native-native-musl \59 -Dtarget=native-native-musl \
57 --search-prefix "$PREFIX" \60 --search-prefix "$PREFIX" \
58 --zig-lib-dir "$PWD/../lib"61 --zig-lib-dir "$PWD/../lib"
lib/compiler/aro_translate_c.zig+1-1
...@@ -1824,7 +1824,7 @@ pub fn main() !void {...@@ -1824,7 +1824,7 @@ pub fn main() !void {
1824 };1824 };
1825 defer tree.deinit(gpa);1825 defer tree.deinit(gpa);
18261826
1827 const formatted = try tree.render(arena);1827 const formatted = try tree.renderAlloc(arena);
1828 try std.fs.File.stdout().writeAll(formatted);1828 try std.fs.File.stdout().writeAll(formatted);
1829 return std.process.cleanExit();1829 return std.process.cleanExit();
1830}1830}
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_rt/exp.zig+89-20
...@@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;...@@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const expect = std.testing.expect;12const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
13const common = @import("common.zig");14const common = @import("common.zig");
1415
15pub const panic = common.panic;16pub const panic = common.panic;
...@@ -211,32 +212,100 @@ pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {...@@ -211,32 +212,100 @@ pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {
211 }212 }
212}213}
213214
214test "exp32" {215test "expf() special" {
215 const epsilon = 0.000001;216 try expectEqual(expf(0.0), 1.0);
217 try expectEqual(expf(-0.0), 1.0);
218 try expectEqual(expf(1.0), math.e);
219 try expectEqual(expf(math.ln2), 2.0);
220 try expectEqual(expf(math.inf(f32)), math.inf(f32));
221 try expect(math.isPositiveZero(expf(-math.inf(f32))));
222 try expect(math.isNan(expf(math.nan(f32))));
223 try expect(math.isNan(expf(math.snan(f32))));
224}
216225
217 try expect(expf(0.0) == 1.0);226test "expf() sanity" {
218 try expect(math.approxEqAbs(f32, expf(0.0), 1.0, epsilon));227 try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12);
219 try expect(math.approxEqAbs(f32, expf(0.2), 1.221403, epsilon));228 try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6);
220 try expect(math.approxEqAbs(f32, expf(0.8923), 2.440737, epsilon));229 try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
221 try expect(math.approxEqAbs(f32, expf(1.5), 4.481689, epsilon));230 try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10);
231 try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13);
232 try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0);
233 try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
234 try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0);
235 try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1);
236 try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1);
237 try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8);
238 try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20);
239 try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25);
240 try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20);
241 try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8);
242 try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2);
243 try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16);
244 try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24);
245 try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
246 try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28);
222}247}
223248
224test "exp64" {249test "expf() boundary" {
225 const epsilon = 0.000001;250 try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite
251 try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
252 try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value
253 try expectEqual(expf(0x1p-149), 1.0); // Min positive input value
254 try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value
255 try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input
256 try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input
257 try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero
258 try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero
259 try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal
260 try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
226261
227 try expect(exp(0.0) == 1.0);
228 try expect(math.approxEqAbs(f64, exp(0.0), 1.0, epsilon));
229 try expect(math.approxEqAbs(f64, exp(0.2), 1.221403, epsilon));
230 try expect(math.approxEqAbs(f64, exp(0.8923), 2.440737, epsilon));
231 try expect(math.approxEqAbs(f64, exp(1.5), 4.481689, epsilon));
232}262}
233263
234test "exp32.special" {264test "exp() special" {
235 try expect(math.isPositiveInf(expf(math.inf(f32))));265 try expectEqual(exp(0.0), 1.0);
236 try expect(math.isNan(expf(math.nan(f32))));266 try expectEqual(exp(-0.0), 1.0);
267 // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC
268 // try expectEqual(exp(1.0), math.e);
269 try expectEqual(exp(math.ln2), 2.0);
270 try expectEqual(exp(math.inf(f64)), math.inf(f64));
271 try expect(math.isPositiveZero(exp(-math.inf(f64))));
272 try expect(math.isNan(exp(math.nan(f64))));
273 try expect(math.isNan(exp(math.snan(f64))));
237}274}
238275
239test "exp64.special" {276test "exp() sanity" {
240 try expect(math.isPositiveInf(exp(math.inf(f64))));277 try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
241 try expect(math.isNan(exp(math.nan(f64))));278 try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
279 try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
280 try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
281 try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
282 try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
283 try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
284 try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
285 try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
286 try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
287 try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
288 try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
289 try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
290 try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
291 try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
292 try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
293 try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
294 try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
295 try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
296 try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
297}
298
299test "exp() boundary" {
300 try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite
301 try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
302 try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
303 try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value
304 try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value
305 try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input
306 try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input
307 try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero
308 try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero
309 try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal
310 try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
242}311}
lib/compiler_rt/exp2.zig+68-23
...@@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;...@@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const expect = std.testing.expect;12const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
13const common = @import("common.zig");14const common = @import("common.zig");
1415
15pub const panic = common.panic;16pub const panic = common.panic;
...@@ -58,7 +59,7 @@ pub fn exp2f(x: f32) callconv(.c) f32 {...@@ -58,7 +59,7 @@ pub fn exp2f(x: f32) callconv(.c) f32 {
58 if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x1.0p-149 / x);59 if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x1.0p-149 / x);
59 }60 }
60 // x <= -15061 // x <= -150
61 if (u >= 0x3160000) {62 if (u >= 0xC3160000) {
62 return 0;63 return 0;
63 }64 }
64 }65 }
...@@ -457,34 +458,78 @@ const exp2dt = [_]f64{...@@ -457,34 +458,78 @@ const exp2dt = [_]f64{
457 0x1.690f4b19e9471p+0, -0x1.9780p-45,458 0x1.690f4b19e9471p+0, -0x1.9780p-45,
458};459};
459460
460test "exp2_32" {461test "exp2f() special" {
461 const epsilon = 0.000001;462 try expectEqual(exp2f(0.0), 1.0);
463 try expectEqual(exp2f(-0.0), 1.0);
464 try expectEqual(exp2f(1.0), 2.0);
465 try expectEqual(exp2f(-1.0), 0.5);
466 try expectEqual(exp2f(math.inf(f32)), math.inf(f32));
467 try expect(math.isPositiveZero(exp2f(-math.inf(f32))));
468 try expect(math.isNan(exp2f(math.nan(f32))));
469 try expect(math.isNan(exp2f(math.snan(f32))));
470}
462471
463 try expect(exp2f(0.0) == 1.0);472test "exp2f() sanity" {
464 try expect(math.approxEqAbs(f32, exp2f(0.2), 1.148698, epsilon));473 try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9);
465 try expect(math.approxEqAbs(f32, exp2f(0.8923), 1.856133, epsilon));474 try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4);
466 try expect(math.approxEqAbs(f32, exp2f(1.5), 2.828427, epsilon));475 try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9);
467 try expect(math.approxEqAbs(f32, exp2f(37.45), 187747237888, epsilon));476 try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7);
468 try expect(math.approxEqAbs(f32, exp2f(-1), 0.5, epsilon));477 try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9);
478 try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0);
479 try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1);
480 try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0);
481 try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0);
482 try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1);
469}483}
470484
471test "exp2_64" {485test "exp2f() boundary" {
472 const epsilon = 0.000001;486 try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
487 try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result
488 try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
489 try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
490 try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
491 try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
492 try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value
493 try expectEqual(exp2f(0x1p-149), 1); // Min positive input value
494 try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value
495 try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input
496 try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input
497}
473498
474 try expect(exp2(0.0) == 1.0);499test "exp2() special" {
475 try expect(math.approxEqAbs(f64, exp2(0.2), 1.148698, epsilon));500 try expectEqual(exp2(0.0), 1.0);
476 try expect(math.approxEqAbs(f64, exp2(0.8923), 1.856133, epsilon));501 try expectEqual(exp2(-0.0), 1.0);
477 try expect(math.approxEqAbs(f64, exp2(1.5), 2.828427, epsilon));502 try expectEqual(exp2(1.0), 2.0);
478 try expect(math.approxEqAbs(f64, exp2(-1), 0.5, epsilon));503 try expectEqual(exp2(-1.0), 0.5);
479 try expect(math.approxEqAbs(f64, exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1, epsilon));504 try expectEqual(exp2(math.inf(f64)), math.inf(f64));
505 try expect(math.isPositiveZero(exp2(-math.inf(f64))));
506 try expect(math.isNan(exp2(math.nan(f64))));
507 try expect(math.isNan(exp2(math.snan(f64))));
480}508}
481509
482test "exp2_32.special" {510test "exp2() sanity" {
483 try expect(math.isPositiveInf(exp2f(math.inf(f32))));511 try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
484 try expect(math.isNan(exp2f(math.nan(f32))));512 try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
513 try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
514 try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
515 try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
516 try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
517 try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
518 try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
519 try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
520 try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
485}521}
486522
487test "exp2_64.special" {523test "exp2() boundary" {
488 try expect(math.isPositiveInf(exp2(math.inf(f64))));524 try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
489 try expect(math.isNan(exp2(math.nan(f64))));525 try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result
526 try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
527 try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
528 try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
529 try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
530 try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
531 try expectEqual(exp2(0x1p-1074), 1); // Min positive input value
532 try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value
533 try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input
534 try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input
490}535}
lib/compiler_rt/log.zig+64-29
...@@ -7,7 +7,8 @@...@@ -7,7 +7,8 @@
7const std = @import("std");7const std = @import("std");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const math = std.math;9const math = std.math;
10const testing = std.testing;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
11const arch = builtin.cpu.arch;12const arch = builtin.cpu.arch;
12const common = @import("common.zig");13const common = @import("common.zig");
1314
...@@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 {...@@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 {
110111
111 // subnormal, scale x112 // subnormal, scale x
112 k -= 54;113 k -= 54;
113 x *= 0x1.0p54;114 x *= 0x1p54;
114 hx = @intCast(@as(u64, @bitCast(ix)) >> 32);115 hx = @intCast(@as(u64, @bitCast(x)) >> 32);
115 } else if (hx >= 0x7FF00000) {116 } else if (hx >= 0x7FF00000) {
116 return x;117 return x;
117 } else if (hx == 0x3FF00000 and ix << 32 == 0) {118 } else if (hx == 0x3FF00000 and ix << 32 == 0) {
...@@ -159,38 +160,72 @@ pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {...@@ -159,38 +160,72 @@ pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {
159 }160 }
160}161}
161162
162test "ln32" {163test "logf() special" {
163 const epsilon = 0.000001;164 try expectEqual(logf(0.0), -math.inf(f32));
165 try expectEqual(logf(-0.0), -math.inf(f32));
166 try expect(math.isPositiveZero(logf(1.0)));
167 try expectEqual(logf(math.e), 1.0);
168 try expectEqual(logf(math.inf(f32)), math.inf(f32));
169 try expect(math.isNan(logf(-1.0)));
170 try expect(math.isNan(logf(-math.inf(f32))));
171 try expect(math.isNan(logf(math.nan(f32))));
172 try expect(math.isNan(logf(math.snan(f32))));
173}
164174
165 try testing.expect(math.approxEqAbs(f32, logf(0.2), -1.609438, epsilon));175test "logf() sanity" {
166 try testing.expect(math.approxEqAbs(f32, logf(0.8923), -0.113953, epsilon));176 try expect(math.isNan(logf(-0x1.0223a0p+3)));
167 try testing.expect(math.approxEqAbs(f32, logf(1.5), 0.405465, epsilon));177 try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0);
168 try testing.expect(math.approxEqAbs(f32, logf(37.45), 3.623007, epsilon));178 try expect(math.isNan(logf(-0x1.0c34b4p+3)));
169 try testing.expect(math.approxEqAbs(f32, logf(89.123), 4.490017, epsilon));179 try expect(math.isNan(logf(-0x1.a206f0p+2)));
170 try testing.expect(math.approxEqAbs(f32, logf(123123.234375), 11.720941, epsilon));180 try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1);
181 try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2);
182 try expect(math.isNan(logf(-0x1.a05cc8p-2)));
183 try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1);
184 try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2);
185 try expect(math.isNan(logf(-0x1.5b86eap-1)));
171}186}
172187
173test "ln64" {188test "logf() boundary" {
174 const epsilon = 0.000001;189 try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
190 try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
191 try expect(math.isNan(logf(-0x1p-149))); // Min negative input value
192 try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0
193 try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
194 try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal
195 try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal
196}
175197
176 try testing.expect(math.approxEqAbs(f64, log(0.2), -1.609438, epsilon));198test "log() special" {
177 try testing.expect(math.approxEqAbs(f64, log(0.8923), -0.113953, epsilon));199 try expectEqual(log(0.0), -math.inf(f64));
178 try testing.expect(math.approxEqAbs(f64, log(1.5), 0.405465, epsilon));200 try expectEqual(log(-0.0), -math.inf(f64));
179 try testing.expect(math.approxEqAbs(f64, log(37.45), 3.623007, epsilon));201 try expect(math.isPositiveZero(log(1.0)));
180 try testing.expect(math.approxEqAbs(f64, log(89.123), 4.490017, epsilon));202 try expectEqual(log(math.e), 1.0);
181 try testing.expect(math.approxEqAbs(f64, log(123123.234375), 11.720941, epsilon));203 try expectEqual(log(math.inf(f64)), math.inf(f64));
204 try expect(math.isNan(log(-1.0)));
205 try expect(math.isNan(log(-math.inf(f64))));
206 try expect(math.isNan(log(math.nan(f64))));
207 try expect(math.isNan(log(math.snan(f64))));
182}208}
183209
184test "ln32.special" {210test "log() sanity" {
185 try testing.expect(math.isPositiveInf(logf(math.inf(f32))));211 try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3)));
186 try testing.expect(math.isNegativeInf(logf(0.0)));212 try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
187 try testing.expect(math.isNan(logf(-1.0)));213 try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3)));
188 try testing.expect(math.isNan(logf(math.nan(f32))));214 try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2)));
215 try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
216 try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
217 try expect(math.isNan(log(-0x1.a05cc754481d1p-2)));
218 try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
219 try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
220 try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1)));
189}221}
190222
191test "ln64.special" {223test "log() boundary" {
192 try testing.expect(math.isPositiveInf(log(math.inf(f64))));224 try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
193 try testing.expect(math.isNegativeInf(log(0.0)));225 try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
194 try testing.expect(math.isNan(log(-1.0)));226 try expect(math.isNan(log(-0x1p-1074))); // Min negative input value
195 try testing.expect(math.isNan(log(math.nan(f64))));227 try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0
228 try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
229 try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
230 try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal
196}231}
lib/compiler_rt/log10.zig+64-27
...@@ -7,7 +7,8 @@...@@ -7,7 +7,8 @@
7const std = @import("std");7const std = @import("std");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const math = std.math;9const math = std.math;
10const testing = std.testing;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
11const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
12const arch = builtin.cpu.arch;13const arch = builtin.cpu.arch;
13const common = @import("common.zig");14const common = @import("common.zig");
...@@ -187,38 +188,74 @@ pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {...@@ -187,38 +188,74 @@ pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {
187 }188 }
188}189}
189190
190test "log10_32" {191test "log10f() special" {
191 const epsilon = 0.000001;192 try expectEqual(log10f(0.0), -math.inf(f32));
193 try expectEqual(log10f(-0.0), -math.inf(f32));
194 try expect(math.isPositiveZero(log10f(1.0)));
195 try expectEqual(log10f(10.0), 1.0);
196 try expectEqual(log10f(0.1), -1.0);
197 try expectEqual(log10f(math.inf(f32)), math.inf(f32));
198 try expect(math.isNan(log10f(-1.0)));
199 try expect(math.isNan(log10f(-math.inf(f32))));
200 try expect(math.isNan(log10f(math.nan(f32))));
201 try expect(math.isNan(log10f(math.snan(f32))));
202}
192203
193 try testing.expect(math.approxEqAbs(f32, log10f(0.2), -0.698970, epsilon));204test "log10f() sanity" {
194 try testing.expect(math.approxEqAbs(f32, log10f(0.8923), -0.049489, epsilon));205 try expect(math.isNan(log10f(-0x1.0223a0p+3)));
195 try testing.expect(math.approxEqAbs(f32, log10f(1.5), 0.176091, epsilon));206 try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1);
196 try testing.expect(math.approxEqAbs(f32, log10f(37.45), 1.573452, epsilon));207 try expect(math.isNan(log10f(-0x1.0c34b4p+3)));
197 try testing.expect(math.approxEqAbs(f32, log10f(89.123), 1.94999, epsilon));208 try expect(math.isNan(log10f(-0x1.a206f0p+2)));
198 try testing.expect(math.approxEqAbs(f32, log10f(123123.234375), 5.09034, epsilon));209 try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1);
210 try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
211 try expect(math.isNan(log10f(-0x1.a05cc8p-2)));
212 try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2);
213 try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4);
214 try expect(math.isNan(log10f(-0x1.5b86eap-1)));
199}215}
200216
201test "log10_64" {217test "log10f() boundary" {
202 const epsilon = 0.000001;218 try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value
219 try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
220 try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value
221 try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0
222 try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
223 try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal
224 try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal
225}
203226
204 try testing.expect(math.approxEqAbs(f64, log10(0.2), -0.698970, epsilon));227test "log10() special" {
205 try testing.expect(math.approxEqAbs(f64, log10(0.8923), -0.049489, epsilon));228 try expectEqual(log10(0.0), -math.inf(f64));
206 try testing.expect(math.approxEqAbs(f64, log10(1.5), 0.176091, epsilon));229 try expectEqual(log10(-0.0), -math.inf(f64));
207 try testing.expect(math.approxEqAbs(f64, log10(37.45), 1.573452, epsilon));230 try expect(math.isPositiveZero(log10(1.0)));
208 try testing.expect(math.approxEqAbs(f64, log10(89.123), 1.94999, epsilon));231 try expectEqual(log10(10.0), 1.0);
209 try testing.expect(math.approxEqAbs(f64, log10(123123.234375), 5.09034, epsilon));232 try expectEqual(log10(0.1), -1.0);
233 try expectEqual(log10(math.inf(f64)), math.inf(f64));
234 try expect(math.isNan(log10(-1.0)));
235 try expect(math.isNan(log10(-math.inf(f64))));
236 try expect(math.isNan(log10(math.nan(f64))));
237 try expect(math.isNan(log10(math.snan(f64))));
210}238}
211239
212test "log10_32.special" {240test "log10() sanity" {
213 try testing.expect(math.isPositiveInf(log10f(math.inf(f32))));241 try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3)));
214 try testing.expect(math.isNegativeInf(log10f(0.0)));242 try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
215 try testing.expect(math.isNan(log10f(-1.0)));243 try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3)));
216 try testing.expect(math.isNan(log10f(math.nan(f32))));244 try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2)));
245 try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
246 try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
247 try expect(math.isNan(log10(-0x1.a05cc754481d1p-2)));
248 try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
249 try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
250 try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1)));
217}251}
218252
219test "log10_64.special" {253test "log10() boundary" {
220 try testing.expect(math.isPositiveInf(log10(math.inf(f64))));254 try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
221 try testing.expect(math.isNegativeInf(log10(0.0)));255 try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
222 try testing.expect(math.isNan(log10(-1.0)));256 try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value
223 try testing.expect(math.isNan(log10(math.nan(f64))));257 try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0
258 try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
259 try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
260 try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal
224}261}
lib/compiler_rt/log2.zig+62-24
...@@ -8,6 +8,7 @@ const std = @import("std");...@@ -8,6 +8,7 @@ const std = @import("std");
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const math = std.math;9const math = std.math;
10const expect = std.testing.expect;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
11const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
12const arch = builtin.cpu.arch;13const arch = builtin.cpu.arch;
13const common = @import("common.zig");14const common = @import("common.zig");
...@@ -179,36 +180,73 @@ pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {...@@ -179,36 +180,73 @@ pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {
179 }180 }
180}181}
181182
182test "log2_32" {183test "log2f() special" {
183 const epsilon = 0.000001;184 try expectEqual(log2f(0.0), -math.inf(f32));
184185 try expectEqual(log2f(-0.0), -math.inf(f32));
185 try expect(math.approxEqAbs(f32, log2f(0.2), -2.321928, epsilon));186 try expect(math.isPositiveZero(log2f(1.0)));
186 try expect(math.approxEqAbs(f32, log2f(0.8923), -0.164399, epsilon));187 try expectEqual(log2f(2.0), 1.0);
187 try expect(math.approxEqAbs(f32, log2f(1.5), 0.584962, epsilon));188 try expectEqual(log2f(math.inf(f32)), math.inf(f32));
188 try expect(math.approxEqAbs(f32, log2f(37.45), 5.226894, epsilon));189 try expect(math.isNan(log2f(-1.0)));
189 try expect(math.approxEqAbs(f32, log2f(123123.234375), 16.909744, epsilon));190 try expect(math.isNan(log2f(-math.inf(f32))));
191 try expect(math.isNan(log2f(math.nan(f32))));
192 try expect(math.isNan(log2f(math.snan(f32))));
190}193}
191194
192test "log2_64" {195test "log2f() sanity" {
193 const epsilon = 0.000001;196 try expect(math.isNan(log2f(-0x1.0223a0p+3)));
194197 try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1);
195 try expect(math.approxEqAbs(f64, log2(0.2), -2.321928, epsilon));198 try expect(math.isNan(log2f(-0x1.0c34b4p+3)));
196 try expect(math.approxEqAbs(f64, log2(0.8923), -0.164399, epsilon));199 try expect(math.isNan(log2f(-0x1.a206f0p+2)));
197 try expect(math.approxEqAbs(f64, log2(1.5), 0.584962, epsilon));200 try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1);
198 try expect(math.approxEqAbs(f64, log2(37.45), 5.226894, epsilon));201 try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
199 try expect(math.approxEqAbs(f64, log2(123123.234375), 16.909744, epsilon));202 try expect(math.isNan(log2f(-0x1.a05cc8p-2)));
203 try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1);
204 try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2);
205 try expect(math.isNan(log2f(-0x1.5b86eap-1)));
200}206}
201207
202test "log2_32.special" {208test "log2f() boundary" {
203 try expect(math.isPositiveInf(log2f(math.inf(f32))));209 try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value
204 try expect(math.isNegativeInf(log2f(0.0)));210 try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value
205 try expect(math.isNan(log2f(-1.0)));211 try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value
206 try expect(math.isNan(log2f(math.nan(f32))));212 try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0
213 try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
214 try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal
215 try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal
216
207}217}
208218
209test "log2_64.special" {219test "log2() special" {
210 try expect(math.isPositiveInf(log2(math.inf(f64))));220 try expectEqual(log2(0.0), -math.inf(f64));
211 try expect(math.isNegativeInf(log2(0.0)));221 try expectEqual(log2(-0.0), -math.inf(f64));
222 try expect(math.isPositiveZero(log2(1.0)));
223 try expectEqual(log2(2.0), 1.0);
224 try expectEqual(log2(math.inf(f64)), math.inf(f64));
212 try expect(math.isNan(log2(-1.0)));225 try expect(math.isNan(log2(-1.0)));
226 try expect(math.isNan(log2(-math.inf(f64))));
213 try expect(math.isNan(log2(math.nan(f64))));227 try expect(math.isNan(log2(math.nan(f64))));
228 try expect(math.isNan(log2(math.snan(f64))));
229}
230
231test "log2() sanity" {
232 try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3)));
233 try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
234 try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3)));
235 try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2)));
236 try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
237 try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
238 try expect(math.isNan(log2(-0x1.a05cc754481d1p-2)));
239 try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
240 try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
241 try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1)));
242}
243
244test "log2() boundary" {
245 try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
246 try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value
247 try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value
248 try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0
249 try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
250 try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal
251 try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal
214}252}
lib/compiler_rt/stack_probe.zig+4-4
...@@ -13,11 +13,11 @@ comptime {...@@ -13,11 +13,11 @@ comptime {
13 // Default stack-probe functions emitted by LLVM13 // Default stack-probe functions emitted by LLVM
14 if (builtin.target.isMinGW()) {14 if (builtin.target.isMinGW()) {
15 @export(&_chkstk, .{ .name = "_alloca", .linkage = common.linkage, .visibility = common.visibility });15 @export(&_chkstk, .{ .name = "_alloca", .linkage = common.linkage, .visibility = common.visibility });
16 @export(&__chkstk, .{ .name = "__chkstk", .linkage = common.linkage, .visibility = common.visibility });
17 @export(&___chkstk, .{ .name = "__alloca", .linkage = common.linkage, .visibility = common.visibility });
18 @export(&___chkstk, .{ .name = "___chkstk", .linkage = common.linkage, .visibility = common.visibility });
19 @export(&__chkstk_ms, .{ .name = "__chkstk_ms", .linkage = common.linkage, .visibility = common.visibility });
16 @export(&___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = common.linkage, .visibility = common.visibility });20 @export(&___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = common.linkage, .visibility = common.visibility });
17
18 if (arch == .thumb or arch == .aarch64) {
19 @export(&__chkstk, .{ .name = "__chkstk", .linkage = common.linkage, .visibility = common.visibility });
20 }
21 } else if (!builtin.link_libc) {21 } else if (!builtin.link_libc) {
22 // This symbols are otherwise exported by MSVCRT.lib22 // This symbols are otherwise exported by MSVCRT.lib
23 @export(&_chkstk, .{ .name = "_chkstk", .linkage = common.linkage, .visibility = common.visibility });23 @export(&_chkstk, .{ .name = "_chkstk", .linkage = common.linkage, .visibility = common.visibility });
lib/docs/wasm/Walk.zig+8-10
...@@ -433,20 +433,18 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {...@@ -433,20 +433,18 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {
433 defer ast.deinit(gpa);433 defer ast.deinit(gpa);
434434
435 const token_offsets = ast.tokens.items(.start);435 const token_offsets = ast.tokens.items(.start);
436 var rendered_err: std.ArrayListUnmanaged(u8) = .{};436 var rendered_err: std.Io.Writer.Allocating = .init(gpa);
437 defer rendered_err.deinit(gpa);437 defer rendered_err.deinit();
438 for (ast.errors) |err| {438 for (ast.errors) |err| {
439 const err_offset = token_offsets[err.token] + ast.errorOffset(err);439 const err_offset = token_offsets[err.token] + ast.errorOffset(err);
440 const err_loc = std.zig.findLineColumn(ast.source, err_offset);440 const err_loc = std.zig.findLineColumn(ast.source, err_offset);
441 rendered_err.clearRetainingCapacity();441 rendered_err.clearRetainingCapacity();
442 {442 ast.renderError(err, &rendered_err.writer) catch |e| switch (e) {
443 var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &rendered_err);443 error.WriteFailed => return error.OutOfMemory,
444 defer rendered_err = aw.toArrayList();444 };
445 ast.renderError(err, &aw.interface) catch |e| switch (e) {445 log.err("{s}:{d}:{d}: {s}", .{
446 error.WriteFailed => return error.OutOfMemory,446 file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.getWritten(),
447 };447 });
448 }
449 log.err("{s}:{d}:{d}: {s}", .{ file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.items });
450 }448 }
451 return Ast.parse(gpa, "", .zig);449 return Ast.parse(gpa, "", .zig);
452 }450 }
lib/std/Build/Step/ConfigHeader.zig+3
...@@ -101,6 +101,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -101,6 +101,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
101 .generated_dir = .{ .step = &config_header.step },101 .generated_dir = .{ .step = &config_header.step },
102 };102 };
103103
104 if (options.style.getPath()) |s| {
105 s.addStepDependencies(&config_header.step);
106 }
104 return config_header;107 return config_header;
105}108}
106109
lib/std/Io/DeprecatedReader.zig+28
...@@ -372,6 +372,34 @@ pub fn discard(self: Self) anyerror!u64 {...@@ -372,6 +372,34 @@ pub fn discard(self: Self) anyerror!u64 {
372 }372 }
373}373}
374374
375/// Helper for bridging to the new `Reader` API while upgrading.
376pub fn adaptToNewApi(self: *const Self) Adapter {
377 return .{
378 .derp_reader = self.*,
379 .new_interface = .{
380 .buffer = &.{},
381 .vtable = &.{ .stream = Adapter.stream },
382 .seek = 0,
383 .end = 0,
384 },
385 };
386}
387
388pub const Adapter = struct {
389 derp_reader: Self,
390 new_interface: std.io.Reader,
391 err: ?Error = null,
392
393 fn stream(r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
394 const a: *@This() = @alignCast(@fieldParentPtr("new_interface", r));
395 const buf = limit.slice(try w.writableSliceGreedy(1));
396 return a.derp_reader.read(buf) catch |err| {
397 a.err = err;
398 return error.ReadFailed;
399 };
400 }
401};
402
375const std = @import("../std.zig");403const std = @import("../std.zig");
376const Self = @This();404const Self = @This();
377const math = std.math;405const math = std.math;
lib/std/Io/Reader.zig+118-131
...@@ -246,33 +246,40 @@ pub fn appendRemaining(...@@ -246,33 +246,40 @@ pub fn appendRemaining(
246 limit: Limit,246 limit: Limit,
247) LimitedAllocError!void {247) LimitedAllocError!void {
248 assert(r.buffer.len != 0); // Needed to detect limit exceeded without losing data.248 assert(r.buffer.len != 0); // Needed to detect limit exceeded without losing data.
249 const buffer = r.buffer;249 const buffer_contents = r.buffer[r.seek..r.end];
250 const buffer_contents = buffer[r.seek..r.end];
251 const copy_len = limit.minInt(buffer_contents.len);250 const copy_len = limit.minInt(buffer_contents.len);
252 try list.ensureUnusedCapacity(gpa, copy_len);251 try list.appendSlice(gpa, r.buffer[0..copy_len]);
253 @memcpy(list.unusedCapacitySlice()[0..copy_len], buffer[0..copy_len]);
254 list.items.len += copy_len;
255 r.seek += copy_len;252 r.seek += copy_len;
256 if (copy_len == buffer_contents.len) {253 if (buffer_contents.len - copy_len != 0) return error.StreamTooLong;
257 r.seek = 0;254 r.seek = 0;
258 r.end = 0;255 r.end = 0;
259 }256 var remaining = @intFromEnum(limit) - copy_len;
260 var remaining = limit.subtract(copy_len).?;
261 while (true) {257 while (true) {
262 try list.ensureUnusedCapacity(gpa, 1);258 try list.ensureUnusedCapacity(gpa, 1);
263 const dest = remaining.slice(list.unusedCapacitySlice());259 const cap = list.unusedCapacitySlice();
264 const additional_buffer: []u8 = if (@intFromEnum(remaining) == dest.len) buffer else &.{};260 const dest = cap[0..@min(cap.len, remaining)];
265 const n = readVec(r, &.{ dest, additional_buffer }) catch |err| switch (err) {261 if (remaining - dest.len == 0) {
266 error.EndOfStream => break,262 // Additionally provides `buffer` to detect end.
267 error.ReadFailed => return error.ReadFailed,263 const new_remaining = readVecInner(r, &.{}, dest, remaining) catch |err| switch (err) {
268 };264 error.EndOfStream => {
269 if (n > dest.len) {265 if (r.bufferedLen() != 0) return error.StreamTooLong;
270 r.end = n - dest.len;266 return;
271 list.items.len += dest.len;267 },
272 return error.StreamTooLong;268 error.ReadFailed => return error.ReadFailed,
269 };
270 list.items.len += remaining - new_remaining;
271 remaining = new_remaining;
272 } else {
273 // Leave `buffer` empty, appending directly to `list`.
274 var dest_w: Writer = .fixed(dest);
275 const n = r.vtable.stream(r, &dest_w, .limited(dest.len)) catch |err| switch (err) {
276 error.WriteFailed => unreachable, // Prevented by the limit.
277 error.EndOfStream => return,
278 error.ReadFailed => return error.ReadFailed,
279 };
280 list.items.len += n;
281 remaining -= n;
273 }282 }
274 list.items.len += n;
275 remaining = remaining.subtract(n).?;
276 }283 }
277}284}
278285
...@@ -313,60 +320,66 @@ pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {...@@ -313,60 +320,66 @@ pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {
313 // buffer capacity requirements met.320 // buffer capacity requirements met.
314 r.seek = 0;321 r.seek = 0;
315 r.end = 0;322 r.end = 0;
316 const first = buf[copy_len..];323 remaining = try readVecInner(r, data[i + 1 ..], buf[copy_len..], remaining);
317 const middle = data[i + 1 ..];324 break;
318 var wrapper: Writer.VectorWrapper = .{325 }
319 .it = .{326 return @intFromEnum(limit) - remaining;
320 .first = first,327}
321 .middle = middle,328
322 .last = r.buffer,329fn readVecInner(r: *Reader, middle: []const []u8, first: []u8, remaining: usize) Error!usize {
323 },330 var wrapper: Writer.VectorWrapper = .{
324 .writer = .{331 .it = .{
325 .buffer = if (first.len >= r.buffer.len) first else r.buffer,332 .first = first,
326 .vtable = Writer.VectorWrapper.vtable,333 .middle = middle,
327 },334 .last = r.buffer,
328 };335 },
329 var n = r.vtable.stream(r, &wrapper.writer, .limited(remaining)) catch |err| switch (err) {336 .writer = .{
330 error.WriteFailed => {337 .buffer = if (first.len >= r.buffer.len) first else r.buffer,
331 assert(!wrapper.used);338 .vtable = Writer.VectorWrapper.vtable,
332 if (wrapper.writer.buffer.ptr == first.ptr) {339 },
333 remaining -= wrapper.writer.end;340 };
334 } else {341 // If the limit may pass beyond user buffer into Reader buffer, use
335 assert(wrapper.writer.end <= r.buffer.len);342 // unlimited, allowing the Reader buffer to fill.
336 r.end = wrapper.writer.end;343 const limit: Limit = l: {
337 }344 var n: usize = first.len;
338 break;345 for (middle) |m| n += m.len;
339 },346 break :l if (remaining >= n) .unlimited else .limited(remaining);
340 else => |e| return e,347 };
341 };348 var n = r.vtable.stream(r, &wrapper.writer, limit) catch |err| switch (err) {
342 if (!wrapper.used) {349 error.WriteFailed => {
350 assert(!wrapper.used);
343 if (wrapper.writer.buffer.ptr == first.ptr) {351 if (wrapper.writer.buffer.ptr == first.ptr) {
344 remaining -= n;352 return remaining - wrapper.writer.end;
345 } else {353 } else {
346 assert(n <= r.buffer.len);354 assert(wrapper.writer.end <= r.buffer.len);
347 r.end = n;355 r.end = wrapper.writer.end;
356 return remaining;
348 }357 }
349 break;358 },
350 }359 else => |e| return e,
351 if (n < first.len) {360 };
352 remaining -= n;361 if (!wrapper.used) {
353 break;362 if (wrapper.writer.buffer.ptr == first.ptr) {
363 return remaining - n;
364 } else {
365 assert(n <= r.buffer.len);
366 r.end = n;
367 return remaining;
354 }368 }
355 remaining -= first.len;369 }
356 n -= first.len;370 if (n < first.len) return remaining - n;
357 for (middle) |mid| {371 var result = remaining - first.len;
358 if (n < mid.len) {372 n -= first.len;
359 remaining -= n;373 for (middle) |mid| {
360 break;374 if (n < mid.len) {
361 }375 return result - n;
362 remaining -= mid.len;
363 n -= mid.len;
364 }376 }
365 assert(n <= r.buffer.len);377 result -= mid.len;
366 r.end = n;378 n -= mid.len;
367 break;
368 }379 }
369 return @intFromEnum(limit) - remaining;380 assert(n <= r.buffer.len);
381 r.end = n;
382 return result;
370}383}
371384
372pub fn buffered(r: *Reader) []u8 {385pub fn buffered(r: *Reader) []u8 {
...@@ -580,48 +593,29 @@ pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void {...@@ -580,48 +593,29 @@ pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void {
580/// See also:593/// See also:
581/// * `readSliceAll`594/// * `readSliceAll`
582pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize {595pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize {
583 const in_buffer = r.buffer[r.seek..r.end];596 var i: usize = 0;
584 const copy_len = @min(buffer.len, in_buffer.len);
585 @memcpy(buffer[0..copy_len], in_buffer[0..copy_len]);
586 if (buffer.len - copy_len == 0) {
587 r.seek += copy_len;
588 return buffer.len;
589 }
590 var i: usize = copy_len;
591 r.end = 0;
592 r.seek = 0;
593 while (true) {597 while (true) {
598 const buffer_contents = r.buffer[r.seek..r.end];
599 const dest = buffer[i..];
600 const copy_len = @min(dest.len, buffer_contents.len);
601 @memcpy(dest[0..copy_len], buffer_contents[0..copy_len]);
602 if (dest.len - copy_len == 0) {
603 @branchHint(.likely);
604 r.seek += copy_len;
605 return buffer.len;
606 }
607 i += copy_len;
608 r.end = 0;
609 r.seek = 0;
594 const remaining = buffer[i..];610 const remaining = buffer[i..];
595 var wrapper: Writer.VectorWrapper = .{611 const new_remaining_len = readVecInner(r, &.{}, remaining, remaining.len) catch |err| switch (err) {
596 .it = .{
597 .first = remaining,
598 .last = r.buffer,
599 },
600 .writer = .{
601 .buffer = if (remaining.len >= r.buffer.len) remaining else r.buffer,
602 .vtable = Writer.VectorWrapper.vtable,
603 },
604 };
605 const n = r.vtable.stream(r, &wrapper.writer, .unlimited) catch |err| switch (err) {
606 error.WriteFailed => {
607 if (!wrapper.used) {
608 assert(r.seek == 0);
609 r.seek = remaining.len;
610 r.end = wrapper.writer.end;
611 @memcpy(remaining, r.buffer[0..remaining.len]);
612 }
613 return buffer.len;
614 },
615 error.EndOfStream => return i,612 error.EndOfStream => return i,
616 error.ReadFailed => return error.ReadFailed,613 error.ReadFailed => return error.ReadFailed,
617 };614 };
618 if (n < remaining.len) {615 if (new_remaining_len == 0) return buffer.len;
619 i += n;616 i += remaining.len - new_remaining_len;
620 continue;
621 }
622 r.end = n - remaining.len;
623 return buffer.len;
624 }617 }
618 return buffer.len;
625}619}
626620
627/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing621/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
...@@ -1627,6 +1621,19 @@ test readSliceShort {...@@ -1627,6 +1621,19 @@ test readSliceShort {
1627 try testing.expectEqual(0, try r.readSliceShort(&buf));1621 try testing.expectEqual(0, try r.readSliceShort(&buf));
1628}1622}
16291623
1624test "readSliceShort with smaller buffer than Reader" {
1625 var reader_buf: [15]u8 = undefined;
1626 const str = "This is a test";
1627 var one_byte_stream: testing.Reader = .init(&reader_buf, &.{
1628 .{ .buffer = str },
1629 });
1630 one_byte_stream.artificial_limit = .limited(1);
1631
1632 var buf: [14]u8 = undefined;
1633 try testing.expectEqual(14, try one_byte_stream.interface.readSliceShort(&buf));
1634 try testing.expectEqualStrings(str, &buf);
1635}
1636
1630test readVec {1637test readVec {
1631 var r: Reader = .fixed(std.ascii.letters);1638 var r: Reader = .fixed(std.ascii.letters);
1632 var flat_buffer: [52]u8 = undefined;1639 var flat_buffer: [52]u8 = undefined;
...@@ -1689,33 +1696,13 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {...@@ -1689,33 +1696,13 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
1689}1696}
16901697
1691test "readAlloc when the backing reader provides one byte at a time" {1698test "readAlloc when the backing reader provides one byte at a time" {
1692 const OneByteReader = struct {
1693 str: []const u8,
1694 i: usize,
1695 reader: Reader,
1696
1697 fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1698 assert(@intFromEnum(limit) >= 1);
1699 const self: *@This() = @fieldParentPtr("reader", r);
1700 if (self.str.len - self.i == 0) return error.EndOfStream;
1701 try w.writeByte(self.str[self.i]);
1702 self.i += 1;
1703 return 1;
1704 }
1705 };
1706 const str = "This is a test";1699 const str = "This is a test";
1707 var tiny_buffer: [1]u8 = undefined;1700 var tiny_buffer: [1]u8 = undefined;
1708 var one_byte_stream: OneByteReader = .{1701 var one_byte_stream: testing.Reader = .init(&tiny_buffer, &.{
1709 .str = str,1702 .{ .buffer = str },
1710 .i = 0,1703 });
1711 .reader = .{1704 one_byte_stream.artificial_limit = .limited(1);
1712 .buffer = &tiny_buffer,1705 const res = try one_byte_stream.interface.allocRemaining(std.testing.allocator, .unlimited);
1713 .vtable = &.{ .stream = OneByteReader.stream },
1714 .seek = 0,
1715 .end = 0,
1716 },
1717 };
1718 const res = try one_byte_stream.reader.allocRemaining(std.testing.allocator, .unlimited);
1719 defer std.testing.allocator.free(res);1706 defer std.testing.allocator.free(res);
1720 try std.testing.expectEqualStrings(str, res);1707 try std.testing.expectEqualStrings(str, res);
1721}1708}
lib/std/Io/Writer.zig+69-12
...@@ -483,7 +483,7 @@ pub fn writeSplatAll(w: *Writer, data: [][]const u8, splat: usize) Error!void {...@@ -483,7 +483,7 @@ pub fn writeSplatAll(w: *Writer, data: [][]const u8, splat: usize) Error!void {
483483
484 // Deal with any left over splats484 // Deal with any left over splats
485 if (data.len != 0 and truncate < data[index].len * splat) {485 if (data.len != 0 and truncate < data[index].len * splat) {
486 std.debug.assert(index == data.len - 1);486 assert(index == data.len - 1);
487 var remaining_splat = splat;487 var remaining_splat = splat;
488 while (true) {488 while (true) {
489 remaining_splat -= truncate / data[index].len;489 remaining_splat -= truncate / data[index].len;
...@@ -618,10 +618,6 @@ pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) E...@@ -618,10 +618,6 @@ pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) E
618/// A user type may be a `struct`, `vector`, `union` or `enum` type.618/// A user type may be a `struct`, `vector`, `union` or `enum` type.
619///619///
620/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.620/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
621///
622/// Asserts `buffer` capacity of at least 2 if a union is printed. This
623/// requirement could be lifted by adjusting the code, but if you trigger that
624/// assertion it is a clue that you should probably be using a buffer.
625pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {621pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
626 const ArgsType = @TypeOf(args);622 const ArgsType = @TypeOf(args);
627 const args_type_info = @typeInfo(ArgsType);623 const args_type_info = @typeInfo(ArgsType);
...@@ -840,11 +836,11 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian...@@ -840,11 +836,11 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian
840 .auto => @compileError("ill-defined memory layout"),836 .auto => @compileError("ill-defined memory layout"),
841 .@"extern" => {837 .@"extern" => {
842 if (native_endian == endian) {838 if (native_endian == endian) {
843 return w.writeStruct(value);839 return w.writeAll(@ptrCast((&value)[0..1]));
844 } else {840 } else {
845 var copy = value;841 var copy = value;
846 std.mem.byteSwapAllFields(@TypeOf(value), &copy);842 std.mem.byteSwapAllFields(@TypeOf(value), &copy);
847 return w.writeStruct(copy);843 return w.writeAll(@ptrCast((&copy)[0..1]));
848 }844 }
849 },845 },
850 .@"packed" => {846 .@"packed" => {
...@@ -855,6 +851,9 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian...@@ -855,6 +851,9 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian
855 }851 }
856}852}
857853
854/// If, `endian` is not native,
855/// * Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
856/// * Asserts that the buffer is aligned enough for `@alignOf(Elem)`.
858pub inline fn writeSliceEndian(857pub inline fn writeSliceEndian(
859 w: *Writer,858 w: *Writer,
860 Elem: type,859 Elem: type,
...@@ -864,7 +863,22 @@ pub inline fn writeSliceEndian(...@@ -864,7 +863,22 @@ pub inline fn writeSliceEndian(
864 if (native_endian == endian) {863 if (native_endian == endian) {
865 return writeAll(w, @ptrCast(slice));864 return writeAll(w, @ptrCast(slice));
866 } else {865 } else {
867 return w.writeArraySwap(w, Elem, slice);866 return writeSliceSwap(w, Elem, slice);
867 }
868}
869
870/// Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
871///
872/// Asserts that the buffer is aligned enough for `@alignOf(Elem)`.
873pub fn writeSliceSwap(w: *Writer, Elem: type, slice: []const Elem) Error!void {
874 var i: usize = 0;
875 while (i < slice.len) {
876 const dest_bytes = try w.writableSliceGreedy(@sizeOf(Elem));
877 const dest: []Elem = @alignCast(@ptrCast(dest_bytes[0 .. dest_bytes.len - dest_bytes.len % @sizeOf(Elem)]));
878 const copy_len = @min(dest.len, slice.len - i);
879 @memcpy(dest[0..copy_len], slice[i..][0..copy_len]);
880 i += copy_len;
881 std.mem.byteSwapAllElements(Elem, dest);
868 }882 }
869}883}
870884
...@@ -1257,14 +1271,13 @@ pub fn printValue(...@@ -1257,14 +1271,13 @@ pub fn printValue(
1257 .@"extern", .@"packed" => {1271 .@"extern", .@"packed" => {
1258 if (info.fields.len == 0) return w.writeAll(".{}");1272 if (info.fields.len == 0) return w.writeAll(".{}");
1259 try w.writeAll(".{ ");1273 try w.writeAll(".{ ");
1260 inline for (info.fields) |field| {1274 inline for (info.fields, 1..) |field, i| {
1261 try w.writeByte('.');1275 try w.writeByte('.');
1262 try w.writeAll(field.name);1276 try w.writeAll(field.name);
1263 try w.writeAll(" = ");1277 try w.writeAll(" = ");
1264 try w.printValue(ANY, options, @field(value, field.name), max_depth - 1);1278 try w.printValue(ANY, options, @field(value, field.name), max_depth - 1);
1265 (try w.writableArray(2)).* = ", ".*;1279 try w.writeAll(if (i < info.fields.len) ", " else " }");
1266 }1280 }
1267 w.buffer[w.end - 2 ..][0..2].* = " }".*;
1268 },1281 },
1269 }1282 }
1270 },1283 },
...@@ -2475,6 +2488,18 @@ pub const Allocating = struct {...@@ -2475,6 +2488,18 @@ pub const Allocating = struct {
2475 return result;2488 return result;
2476 }2489 }
24772490
2491 pub fn ensureUnusedCapacity(a: *Allocating, additional_count: usize) Allocator.Error!void {
2492 var list = a.toArrayList();
2493 defer a.setArrayList(list);
2494 return list.ensureUnusedCapacity(a.allocator, additional_count);
2495 }
2496
2497 pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void {
2498 var list = a.toArrayList();
2499 defer a.setArrayList(list);
2500 return list.ensureTotalCapacity(a.allocator, new_capacity);
2501 }
2502
2478 pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 {2503 pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 {
2479 var list = a.toArrayList();2504 var list = a.toArrayList();
2480 defer a.setArrayList(list);2505 defer a.setArrayList(list);
...@@ -2594,8 +2619,40 @@ test "allocating sendFile" {...@@ -2594,8 +2619,40 @@ test "allocating sendFile" {
2594 var file_reader = file_writer.moveToReader();2619 var file_reader = file_writer.moveToReader();
2595 try file_reader.seekTo(0);2620 try file_reader.seekTo(0);
25962621
2597 var allocating: std.io.Writer.Allocating = .init(std.testing.allocator);2622 var allocating: std.io.Writer.Allocating = .init(testing.allocator);
2598 defer allocating.deinit();2623 defer allocating.deinit();
25992624
2600 _ = try file_reader.interface.streamRemaining(&allocating.writer);2625 _ = try file_reader.interface.streamRemaining(&allocating.writer);
2601}2626}
2627
2628test writeStruct {
2629 var buffer: [16]u8 = undefined;
2630 const S = extern struct { a: u64, b: u32, c: u32 };
2631 const s: S = .{ .a = 1, .b = 2, .c = 3 };
2632 {
2633 var w: Writer = .fixed(&buffer);
2634 try w.writeStruct(s, .little);
2635 try testing.expectEqualSlices(u8, &.{
2636 1, 0, 0, 0, 0, 0, 0, 0, //
2637 2, 0, 0, 0, //
2638 3, 0, 0, 0, //
2639 }, &buffer);
2640 }
2641 {
2642 var w: Writer = .fixed(&buffer);
2643 try w.writeStruct(s, .big);
2644 try testing.expectEqualSlices(u8, &.{
2645 0, 0, 0, 0, 0, 0, 0, 1, //
2646 0, 0, 0, 2, //
2647 0, 0, 0, 3, //
2648 }, &buffer);
2649 }
2650}
2651
2652test writeSliceEndian {
2653 var buffer: [4]u8 align(2) = undefined;
2654 var w: Writer = .fixed(&buffer);
2655 const array: [2]u16 = .{ 0x1234, 0x5678 };
2656 try writeSliceEndian(&w, u16, &array, .big);
2657 try testing.expectEqualSlices(u8, &.{ 0x12, 0x34, 0x56, 0x78 }, &buffer);
2658}
lib/std/Progress.zig+1
...@@ -633,6 +633,7 @@ pub fn lockStderrWriter(buffer: []u8) *Writer {...@@ -633,6 +633,7 @@ pub fn lockStderrWriter(buffer: []u8) *Writer {
633633
634pub fn unlockStderrWriter() void {634pub fn unlockStderrWriter() void {
635 stderr_writer.flush() catch {};635 stderr_writer.flush() catch {};
636 stderr_writer.end = 0;
636 stderr_writer.buffer = &.{};637 stderr_writer.buffer = &.{};
637 stderr_mutex.unlock();638 stderr_mutex.unlock();
638}639}
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/math/expm1.zig+67-28
...@@ -10,6 +10,7 @@ const std = @import("../std.zig");...@@ -10,6 +10,7 @@ const std = @import("../std.zig");
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const expect = std.testing.expect;12const expect = std.testing.expect;
13const expectEqual = std.testing.expectEqual;
1314
14/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 115/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1
15/// when x is near 0.16/// when x is near 0.
...@@ -39,9 +40,9 @@ fn expm1_32(x_: f32) f32 {...@@ -39,9 +40,9 @@ fn expm1_32(x_: f32) f32 {
39 const Q2: f32 = 1.5807170421e-3;40 const Q2: f32 = 1.5807170421e-3;
4041
41 var x = x_;42 var x = x_;
42 const ux = @as(u32, @bitCast(x));43 const ux: u32 = @bitCast(x);
43 const hx = ux & 0x7FFFFFFF;44 const hx = ux & 0x7FFFFFFF;
44 const sign = hx >> 31;45 const sign = ux >> 31;
4546
46 // TODO: Shouldn't need this check explicitly.47 // TODO: Shouldn't need this check explicitly.
47 if (math.isNegativeInf(x)) {48 if (math.isNegativeInf(x)) {
...@@ -147,7 +148,7 @@ fn expm1_32(x_: f32) f32 {...@@ -147,7 +148,7 @@ fn expm1_32(x_: f32) f32 {
147 return y - 1.0;148 return y - 1.0;
148 }149 }
149150
150 const uf = @as(f32, @bitCast(@as(u32, @intCast(0x7F -% k)) << 23));151 const uf: f32 = @bitCast(@as(u32, @intCast(0x7F -% k)) << 23);
151 if (k < 23) {152 if (k < 23) {
152 return (x - e + (1 - uf)) * twopk;153 return (x - e + (1 - uf)) * twopk;
153 } else {154 } else {
...@@ -286,39 +287,77 @@ fn expm1_64(x_: f64) f64 {...@@ -286,39 +287,77 @@ fn expm1_64(x_: f64) f64 {
286 }287 }
287}288}
288289
289test expm1 {290test "expm1_32() special" {
290 try expect(expm1(@as(f32, 0.0)) == expm1_32(0.0));291 try expect(math.isPositiveZero(expm1_32(0.0)));
291 try expect(expm1(@as(f64, 0.0)) == expm1_64(0.0));292 try expect(math.isNegativeZero(expm1_32(-0.0)));
293 try expectEqual(expm1_32(math.ln2), 1.0);
294 try expectEqual(expm1_32(math.inf(f32)), math.inf(f32));
295 try expectEqual(expm1_32(-math.inf(f32)), -1.0);
296 try expect(math.isNan(expm1_32(math.nan(f32))));
297 try expect(math.isNan(expm1_32(math.snan(f32))));
292}298}
293299
294test expm1_32 {300test "expm1_32() sanity" {
295 const epsilon = 0.000001;301 try expectEqual(expm1_32(-0x1.0223a0p+3), -0x1.ffd6e0p-1);
296302 try expectEqual(expm1_32(0x1.161868p+2), 0x1.30712ap+6);
297 try expect(math.isPositiveZero(expm1_32(0.0)));303 try expectEqual(expm1_32(-0x1.0c34b4p+3), -0x1.ffe1fap-1);
298 try expect(math.approxEqAbs(f32, expm1_32(0.0), 0.0, epsilon));304 try expectEqual(expm1_32(-0x1.a206f0p+2), -0x1.ff4116p-1);
299 try expect(math.approxEqAbs(f32, expm1_32(0.2), 0.221403, epsilon));305 try expectEqual(expm1_32(0x1.288bbcp+3), 0x1.4ab480p+13); // Disagrees with GCC in last bit
300 try expect(math.approxEqAbs(f32, expm1_32(0.8923), 1.440737, epsilon));306 try expectEqual(expm1_32(0x1.52efd0p-1), 0x1.e09536p-1);
301 try expect(math.approxEqAbs(f32, expm1_32(1.5), 3.481689, epsilon));307 try expectEqual(expm1_32(-0x1.a05cc8p-2), -0x1.561c3ep-2);
308 try expectEqual(expm1_32(0x1.1f9efap-1), 0x1.81ec4ep-1);
309 try expectEqual(expm1_32(0x1.8c5db0p-1), 0x1.2b3364p+0);
310 try expectEqual(expm1_32(-0x1.5b86eap-1), -0x1.f8951ap-2);
302}311}
303312
304test expm1_64 {313test "expm1_32() boundary" {
305 const epsilon = 0.000001;314 // TODO: The last value before inf is actually 0x1.62e300p+6 -> 0x1.ff681ep+127
315 // try expectEqual(expm1_32(0x1.62e42ep+6), 0x1.ffff08p+127); // Last value before result is inf
316 try expectEqual(expm1_32(0x1.62e430p+6), math.inf(f32)); // First value that gives inf
317 try expectEqual(expm1_32(0x1.fffffep+127), math.inf(f32)); // Max input value
318 try expectEqual(expm1_32(0x1p-149), 0x1p-149); // Min positive input value
319 try expectEqual(expm1_32(-0x1p-149), -0x1p-149); // Min negative input value
320 try expectEqual(expm1_32(0x1p-126), 0x1p-126); // First positive subnormal input
321 try expectEqual(expm1_32(-0x1p-126), -0x1p-126); // First negative subnormal input
322 try expectEqual(expm1_32(0x1.fffffep-125), 0x1.fffffep-125); // Last positive value before subnormal
323 try expectEqual(expm1_32(-0x1.fffffep-125), -0x1.fffffep-125); // Last negative value before subnormal
324 try expectEqual(expm1_32(-0x1.154244p+4), -0x1.fffffep-1); // Last value before result is -1
325 try expectEqual(expm1_32(-0x1.154246p+4), -1); // First value where result is -1
326}
306327
328test "expm1_64() special" {
307 try expect(math.isPositiveZero(expm1_64(0.0)));329 try expect(math.isPositiveZero(expm1_64(0.0)));
308 try expect(math.approxEqAbs(f64, expm1_64(0.0), 0.0, epsilon));330 try expect(math.isNegativeZero(expm1_64(-0.0)));
309 try expect(math.approxEqAbs(f64, expm1_64(0.2), 0.221403, epsilon));331 try expectEqual(expm1_64(math.ln2), 1.0);
310 try expect(math.approxEqAbs(f64, expm1_64(0.8923), 1.440737, epsilon));332 try expectEqual(expm1_64(math.inf(f64)), math.inf(f64));
311 try expect(math.approxEqAbs(f64, expm1_64(1.5), 3.481689, epsilon));333 try expectEqual(expm1_64(-math.inf(f64)), -1.0);
334 try expect(math.isNan(expm1_64(math.nan(f64))));
335 try expect(math.isNan(expm1_64(math.snan(f64))));
312}336}
313337
314test "expm1_32.special" {338test "expm1_64() sanity" {
315 try expect(math.isPositiveInf(expm1_32(math.inf(f32))));339 try expectEqual(expm1_64(-0x1.02239f3c6a8f1p+3), -0x1.ffd6df9b02b3ep-1);
316 try expect(expm1_32(-math.inf(f32)) == -1.0);340 try expectEqual(expm1_64(0x1.161868e18bc67p+2), 0x1.30712ed238c04p+6);
317 try expect(math.isNan(expm1_32(math.nan(f32))));341 try expectEqual(expm1_64(-0x1.0c34b3e01e6e7p+3), -0x1.ffe1f94e493e7p-1);
342 try expectEqual(expm1_64(-0x1.a206f0a19dcc4p+2), -0x1.ff4115c03f78dp-1);
343 try expectEqual(expm1_64(0x1.288bbb0d6a1e6p+3), 0x1.4ab477496e07ep+13);
344 try expectEqual(expm1_64(0x1.52efd0cd80497p-1), 0x1.e095382100a01p-1);
345 try expectEqual(expm1_64(-0x1.a05cc754481d1p-2), -0x1.561c3e0582be6p-2);
346 try expectEqual(expm1_64(0x1.1f9ef934745cbp-1), 0x1.81ec4cd4d4a8fp-1);
347 try expectEqual(expm1_64(0x1.8c5db097f7442p-1), 0x1.2b3363a944bf7p+0);
348 try expectEqual(expm1_64(-0x1.5b86ea8118a0ep-1), -0x1.f8951aebffbafp-2);
318}349}
319350
320test "expm1_64.special" {351test "expm1_64() boundary" {
321 try expect(math.isPositiveInf(expm1_64(math.inf(f64))));352 try expectEqual(expm1_64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // Last value before result is inf
322 try expect(expm1_64(-math.inf(f64)) == -1.0);353 try expectEqual(expm1_64(0x1.62e42fefa39f0p+9), math.inf(f64)); // First value that gives inf
323 try expect(math.isNan(expm1_64(math.nan(f64))));354 try expectEqual(expm1_64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
355 try expectEqual(expm1_64(0x1p-1074), 0x1p-1074); // Min positive input value
356 try expectEqual(expm1_64(-0x1p-1074), -0x1p-1074); // Min negative input value
357 try expectEqual(expm1_64(0x1p-1022), 0x1p-1022); // First positive subnormal input
358 try expectEqual(expm1_64(-0x1p-1022), -0x1p-1022); // First negative subnormal input
359 try expectEqual(expm1_64(0x1.fffffffffffffp-1021), 0x1.fffffffffffffp-1021); // Last positive value before subnormal
360 try expectEqual(expm1_64(-0x1.fffffffffffffp-1021), -0x1.fffffffffffffp-1021); // Last negative value before subnormal
361 try expectEqual(expm1_64(-0x1.2b708872320e1p+5), -0x1.fffffffffffffp-1); // Last value before result is -1
362 try expectEqual(expm1_64(-0x1.2b708872320e2p+5), -1); // First value where result is -1
324}363}
lib/std/math/log1p.zig+59-35
...@@ -8,6 +8,7 @@ const std = @import("../std.zig");...@@ -8,6 +8,7 @@ const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
9const mem = std.mem;9const mem = std.mem;
10const expect = std.testing.expect;10const expect = std.testing.expect;
11const expectEqual = std.testing.expectEqual;
1112
12/// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero.13/// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero.
13///14///
...@@ -182,49 +183,72 @@ fn log1p_64(x: f64) f64 {...@@ -182,49 +183,72 @@ fn log1p_64(x: f64) f64 {
182 return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;183 return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
183}184}
184185
185test log1p {186test "log1p_32() special" {
186 try expect(log1p(@as(f32, 0.0)) == log1p_32(0.0));
187 try expect(log1p(@as(f64, 0.0)) == log1p_64(0.0));
188}
189
190test log1p_32 {
191 const epsilon = 0.000001;
192
193 try expect(math.approxEqAbs(f32, log1p_32(0.0), 0.0, epsilon));
194 try expect(math.approxEqAbs(f32, log1p_32(0.2), 0.182322, epsilon));
195 try expect(math.approxEqAbs(f32, log1p_32(0.8923), 0.637793, epsilon));
196 try expect(math.approxEqAbs(f32, log1p_32(1.5), 0.916291, epsilon));
197 try expect(math.approxEqAbs(f32, log1p_32(37.45), 3.649359, epsilon));
198 try expect(math.approxEqAbs(f32, log1p_32(89.123), 4.501175, epsilon));
199 try expect(math.approxEqAbs(f32, log1p_32(123123.234375), 11.720949, epsilon));
200}
201
202test log1p_64 {
203 const epsilon = 0.000001;
204
205 try expect(math.approxEqAbs(f64, log1p_64(0.0), 0.0, epsilon));
206 try expect(math.approxEqAbs(f64, log1p_64(0.2), 0.182322, epsilon));
207 try expect(math.approxEqAbs(f64, log1p_64(0.8923), 0.637793, epsilon));
208 try expect(math.approxEqAbs(f64, log1p_64(1.5), 0.916291, epsilon));
209 try expect(math.approxEqAbs(f64, log1p_64(37.45), 3.649359, epsilon));
210 try expect(math.approxEqAbs(f64, log1p_64(89.123), 4.501175, epsilon));
211 try expect(math.approxEqAbs(f64, log1p_64(123123.234375), 11.720949, epsilon));
212}
213
214test "log1p_32.special" {
215 try expect(math.isPositiveInf(log1p_32(math.inf(f32))));
216 try expect(math.isPositiveZero(log1p_32(0.0)));187 try expect(math.isPositiveZero(log1p_32(0.0)));
217 try expect(math.isNegativeZero(log1p_32(-0.0)));188 try expect(math.isNegativeZero(log1p_32(-0.0)));
218 try expect(math.isNegativeInf(log1p_32(-1.0)));189 try expectEqual(log1p_32(-1.0), -math.inf(f32));
190 try expectEqual(log1p_32(1.0), math.ln2);
191 try expectEqual(log1p_32(math.inf(f32)), math.inf(f32));
219 try expect(math.isNan(log1p_32(-2.0)));192 try expect(math.isNan(log1p_32(-2.0)));
193 try expect(math.isNan(log1p_32(-math.inf(f32))));
220 try expect(math.isNan(log1p_32(math.nan(f32))));194 try expect(math.isNan(log1p_32(math.nan(f32))));
195 try expect(math.isNan(log1p_32(math.snan(f32))));
221}196}
222197
223test "log1p_64.special" {198test "log1p_32() sanity" {
224 try expect(math.isPositiveInf(log1p_64(math.inf(f64))));199 try expect(math.isNan(log1p_32(-0x1.0223a0p+3)));
200 try expectEqual(log1p_32(0x1.161868p+2), 0x1.ad1bdcp+0);
201 try expect(math.isNan(log1p_32(-0x1.0c34b4p+3)));
202 try expect(math.isNan(log1p_32(-0x1.a206f0p+2)));
203 try expectEqual(log1p_32(0x1.288bbcp+3), 0x1.2a1ab8p+1);
204 try expectEqual(log1p_32(0x1.52efd0p-1), 0x1.041a4ep-1);
205 try expectEqual(log1p_32(-0x1.a05cc8p-2), -0x1.0b3596p-1);
206 try expectEqual(log1p_32(0x1.1f9efap-1), 0x1.c88344p-2);
207 try expectEqual(log1p_32(0x1.8c5db0p-1), 0x1.258a8ep-1);
208 try expectEqual(log1p_32(-0x1.5b86eap-1), -0x1.22b542p+0);
209}
210
211test "log1p_32() boundary" {
212 try expectEqual(log1p_32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
213 try expectEqual(log1p_32(0x1p-149), 0x1p-149); // Min positive input value
214 try expectEqual(log1p_32(-0x1p-149), -0x1p-149); // Min negative input value
215 try expectEqual(log1p_32(0x1p-126), 0x1p-126); // First subnormal
216 try expectEqual(log1p_32(-0x1p-126), -0x1p-126); // First negative subnormal
217 try expectEqual(log1p_32(-0x1.fffffep-1), -0x1.0a2b24p+4); // Last value before result is -inf
218 try expect(math.isNan(log1p_32(-0x1.000002p+0))); // First value where result is nan
219}
220
221test "log1p_64() special" {
225 try expect(math.isPositiveZero(log1p_64(0.0)));222 try expect(math.isPositiveZero(log1p_64(0.0)));
226 try expect(math.isNegativeZero(log1p_64(-0.0)));223 try expect(math.isNegativeZero(log1p_64(-0.0)));
227 try expect(math.isNegativeInf(log1p_64(-1.0)));224 try expectEqual(log1p_64(-1.0), -math.inf(f64));
225 try expectEqual(log1p_64(1.0), math.ln2);
226 try expectEqual(log1p_64(math.inf(f64)), math.inf(f64));
228 try expect(math.isNan(log1p_64(-2.0)));227 try expect(math.isNan(log1p_64(-2.0)));
228 try expect(math.isNan(log1p_64(-math.inf(f64))));
229 try expect(math.isNan(log1p_64(math.nan(f64))));229 try expect(math.isNan(log1p_64(math.nan(f64))));
230 try expect(math.isNan(log1p_64(math.snan(f64))));
231}
232
233test "log1p_64() sanity" {
234 try expect(math.isNan(log1p_64(-0x1.02239f3c6a8f1p+3)));
235 try expectEqual(log1p_64(0x1.161868e18bc67p+2), 0x1.ad1bdd1e9e686p+0); // Disagrees with GCC in last bit
236 try expect(math.isNan(log1p_64(-0x1.0c34b3e01e6e7p+3)));
237 try expect(math.isNan(log1p_64(-0x1.a206f0a19dcc4p+2)));
238 try expectEqual(log1p_64(0x1.288bbb0d6a1e6p+3), 0x1.2a1ab8365b56fp+1);
239 try expectEqual(log1p_64(0x1.52efd0cd80497p-1), 0x1.041a4ec2a680ap-1);
240 try expectEqual(log1p_64(-0x1.a05cc754481d1p-2), -0x1.0b3595423aec1p-1);
241 try expectEqual(log1p_64(0x1.1f9ef934745cbp-1), 0x1.c8834348a846ep-2);
242 try expectEqual(log1p_64(0x1.8c5db097f7442p-1), 0x1.258a8e8a35bbfp-1);
243 try expectEqual(log1p_64(-0x1.5b86ea8118a0ep-1), -0x1.22b5426327502p+0);
244}
245
246test "log1p_64() boundary" {
247 try expectEqual(log1p_64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
248 try expectEqual(log1p_64(0x1p-1074), 0x1p-1074); // Min positive input value
249 try expectEqual(log1p_64(-0x1p-1074), -0x1p-1074); // Min negative input value
250 try expectEqual(log1p_64(0x1p-1022), 0x1p-1022); // First subnormal
251 try expectEqual(log1p_64(-0x1p-1022), -0x1p-1022); // First negative subnormal
252 try expectEqual(log1p_64(-0x1.fffffffffffffp-1), -0x1.25e4f7b2737fap+5); // Last value before result is -inf
253 try expect(math.isNan(log1p_64(-0x1.0000000000001p+0))); // First value where result is nan
230}254}
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/os/uefi/protocol/file.zig+1-1
...@@ -214,7 +214,7 @@ pub const File = extern struct {...@@ -214,7 +214,7 @@ pub const File = extern struct {
214 pub fn getInfo(214 pub fn getInfo(
215 self: *const File,215 self: *const File,
216 comptime info: std.meta.Tag(Info),216 comptime info: std.meta.Tag(Info),
217 buffer: []u8,217 buffer: []align(@alignOf(@FieldType(Info, @tagName(info)))) u8,
218 ) GetInfoError!*@FieldType(Info, @tagName(info)) {218 ) GetInfoError!*@FieldType(Info, @tagName(info)) {
219 const InfoType = @FieldType(Info, @tagName(info));219 const InfoType = @FieldType(Info, @tagName(info));
220220
lib/std/testing.zig+6-4
...@@ -1210,12 +1210,14 @@ pub inline fn fuzz(...@@ -1210,12 +1210,14 @@ pub inline fn fuzz(
1210 return @import("root").fuzz(context, testOne, options);1210 return @import("root").fuzz(context, testOne, options);
1211}1211}
12121212
1213/// A `std.io.Reader` that writes a predetermined list of buffers during `stream`.1213/// A `std.Io.Reader` that writes a predetermined list of buffers during `stream`.
1214pub const Reader = struct {1214pub const Reader = struct {
1215 calls: []const Call,1215 calls: []const Call,
1216 interface: std.io.Reader,1216 interface: std.Io.Reader,
1217 next_call_index: usize,1217 next_call_index: usize,
1218 next_offset: usize,1218 next_offset: usize,
1219 /// Further reduces how many bytes are written in each `stream` call.
1220 artificial_limit: std.Io.Limit = .unlimited,
12191221
1220 pub const Call = struct {1222 pub const Call = struct {
1221 buffer: []const u8,1223 buffer: []const u8,
...@@ -1235,11 +1237,11 @@ pub const Reader = struct {...@@ -1235,11 +1237,11 @@ pub const Reader = struct {
1235 };1237 };
1236 }1238 }
12371239
1238 fn stream(io_r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {1240 fn stream(io_r: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize {
1239 const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r));1241 const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r));
1240 if (r.calls.len - r.next_call_index == 0) return error.EndOfStream;1242 if (r.calls.len - r.next_call_index == 0) return error.EndOfStream;
1241 const call = r.calls[r.next_call_index];1243 const call = r.calls[r.next_call_index];
1242 const buffer = limit.sliceConst(call.buffer[r.next_offset..]);1244 const buffer = r.artificial_limit.sliceConst(limit.sliceConst(call.buffer[r.next_offset..]));
1243 const n = try w.write(buffer);1245 const n = try w.write(buffer);
1244 r.next_offset += n;1246 r.next_offset += n;
1245 if (call.buffer.len - r.next_offset == 0) {1247 if (call.buffer.len - r.next_offset == 0) {
lib/std/zig.zig+3-1
...@@ -536,7 +536,8 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *std.fs.File.Reader...@@ -536,7 +536,8 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *std.fs.File.Reader
536536
537 if (file_reader.getSize()) |size| {537 if (file_reader.getSize()) |size| {
538 const casted_size = std.math.cast(u32, size) orelse return error.StreamTooLong;538 const casted_size = std.math.cast(u32, size) orelse return error.StreamTooLong;
539 try buffer.ensureTotalCapacityPrecise(gpa, casted_size);539 // +1 to avoid resizing for the null byte added in toOwnedSliceSentinel below.
540 try buffer.ensureTotalCapacityPrecise(gpa, casted_size + 1);
540 } else |_| {}541 } else |_| {}
541542
542 try file_reader.interface.appendRemaining(gpa, .@"2", &buffer, .limited(max_src_size));543 try file_reader.interface.appendRemaining(gpa, .@"2", &buffer, .limited(max_src_size));
...@@ -904,4 +905,5 @@ test {...@@ -904,4 +905,5 @@ test {
904 _ = system;905 _ = system;
905 _ = target;906 _ = target;
906 _ = c_translation;907 _ = c_translation;
908 _ = llvm;
907}909}
lib/std/zig/LibCInstallation.zig+1-2
...@@ -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+7-5
...@@ -118,6 +118,8 @@ pub fn init(options: Options) !Server {...@@ -118,6 +118,8 @@ pub fn init(options: Options) !Server {
118 .in = options.in,118 .in = options.in,
119 .out = options.out,119 .out = options.out,
120 };120 };
121 assert(s.out.buffer.len >= 4);
122 std.debug.assertAligned(s.out.buffer.ptr, .@"4");
121 try s.serveStringMessage(.zig_version, options.zig_version);123 try s.serveStringMessage(.zig_version, options.zig_version);
122 return s;124 return s;
123}125}
...@@ -141,7 +143,7 @@ pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !voi...@@ -141,7 +143,7 @@ pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !voi
141143
142/// Don't forget to flush!144/// Don't forget to flush!
143pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {145pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {
144 try s.out.writeStructEndian(header, .little);146 try s.out.writeStruct(header, .little);
145}147}
146148
147pub fn serveU64Message(s: *const Server, tag: OutMessage.Tag, int: u64) !void {149pub fn serveU64Message(s: *const Server, tag: OutMessage.Tag, int: u64) !void {
...@@ -162,7 +164,7 @@ pub fn serveEmitDigest(...@@ -162,7 +164,7 @@ pub fn serveEmitDigest(
162 .tag = .emit_digest,164 .tag = .emit_digest,
163 .bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)),165 .bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)),
164 });166 });
165 try s.out.writeStructEndian(header, .little);167 try s.out.writeStruct(header, .little);
166 try s.out.writeAll(digest);168 try s.out.writeAll(digest);
167 try s.out.flush();169 try s.out.flush();
168}170}
...@@ -172,7 +174,7 @@ pub fn serveTestResults(s: *Server, msg: OutMessage.TestResults) !void {...@@ -172,7 +174,7 @@ pub fn serveTestResults(s: *Server, msg: OutMessage.TestResults) !void {
172 .tag = .test_results,174 .tag = .test_results,
173 .bytes_len = @intCast(@sizeOf(OutMessage.TestResults)),175 .bytes_len = @intCast(@sizeOf(OutMessage.TestResults)),
174 });176 });
175 try s.out.writeStructEndian(msg, .little);177 try s.out.writeStruct(msg, .little);
176 try s.out.flush();178 try s.out.flush();
177}179}
178180
...@@ -187,7 +189,7 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {...@@ -187,7 +189,7 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
187 .tag = .error_bundle,189 .tag = .error_bundle,
188 .bytes_len = @intCast(bytes_len),190 .bytes_len = @intCast(bytes_len),
189 });191 });
190 try s.out.writeStructEndian(eb_hdr, .little);192 try s.out.writeStruct(eb_hdr, .little);
191 try s.out.writeSliceEndian(u32, error_bundle.extra, .little);193 try s.out.writeSliceEndian(u32, error_bundle.extra, .little);
192 try s.out.writeAll(error_bundle.string_bytes);194 try s.out.writeAll(error_bundle.string_bytes);
193 try s.out.flush();195 try s.out.flush();
...@@ -212,7 +214,7 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {...@@ -212,7 +214,7 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
212 .tag = .test_metadata,214 .tag = .test_metadata,
213 .bytes_len = @intCast(bytes_len),215 .bytes_len = @intCast(bytes_len),
214 });216 });
215 try s.out.writeStructEndian(header, .little);217 try s.out.writeStruct(header, .little);
216 try s.out.writeSliceEndian(u32, test_metadata.names, .little);218 try s.out.writeSliceEndian(u32, test_metadata.names, .little);
217 try s.out.writeSliceEndian(u32, test_metadata.expected_panic_msgs, .little);219 try s.out.writeSliceEndian(u32, test_metadata.expected_panic_msgs, .little);
218 try s.out.writeAll(test_metadata.string_bytes);220 try s.out.writeAll(test_metadata.string_bytes);
lib/std/zig/WindowsSdk.zig+6-6
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const WindowsSdk = @This();1const WindowsSdk = @This();
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const std = @import("std");3const std = @import("std");
4const Writer = std.io.Writer;4const Writer = std.Io.Writer;
55
6windows10sdk: ?Installation,6windows10sdk: ?Installation,
7windows81sdk: ?Installation,7windows81sdk: ?Installation,
...@@ -760,13 +760,13 @@ const MsvcLibDir = struct {...@@ -760,13 +760,13 @@ const MsvcLibDir = struct {
760 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {760 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {
761 if (entry.kind != .directory) continue;761 if (entry.kind != .directory) continue;
762762
763 var bw: Writer = .fixed(&state_subpath_buf);763 var writer: Writer = .fixed(&state_subpath_buf);
764764
765 bw.writeAll(entry.name) catch unreachable;765 writer.writeAll(entry.name) catch unreachable;
766 bw.writeByte(std.fs.path.sep) catch unreachable;766 writer.writeByte(std.fs.path.sep) catch unreachable;
767 bw.writeAll("state.json") catch unreachable;767 writer.writeAll("state.json") catch unreachable;
768768
769 const json_contents = instances_dir.readFileAlloc(allocator, bw.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+5-1
...@@ -177,7 +177,7 @@ pub fn next(bc: *BitcodeReader) !?Item {...@@ -177,7 +177,7 @@ pub fn next(bc: *BitcodeReader) !?Item {
177177
178pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {178pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {
179 assert(bc.bit_offset == 0);179 assert(bc.bit_offset == 0);
180 try bc.reader.discard(4 * @as(u34, block.len));180 try bc.reader.discardAll(4 * @as(u34, block.len));
181 try bc.endBlock();181 try bc.endBlock();
182}182}
183183
...@@ -513,3 +513,7 @@ const Abbrev = struct {...@@ -513,3 +513,7 @@ const Abbrev = struct {
513 }513 }
514 };514 };
515};515};
516
517test {
518 _ = &skipBlock;
519}
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.writer();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+9-6
...@@ -379,15 +379,18 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {...@@ -379,15 +379,18 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {
379}379}
380380
381pub fn detectNativeCpuAndFeatures() ?Target.Cpu {381pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
382 var f = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {382 var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
383 else => return null,383 else => return null,
384 };384 };
385 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);
386389
387 const current_arch = builtin.cpu.arch;390 const current_arch = builtin.cpu.arch;
388 switch (current_arch) {391 switch (current_arch) {
389 .arm, .armeb, .thumb, .thumbeb => {392 .arm, .armeb, .thumb, .thumbeb => {
390 return ArmCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;393 return ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
391 },394 },
392 .aarch64, .aarch64_be => {395 .aarch64, .aarch64_be => {
393 const registers = [12]u64{396 const registers = [12]u64{
...@@ -409,13 +412,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {...@@ -409,13 +412,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
409 return core;412 return core;
410 },413 },
411 .sparc64 => {414 .sparc64 => {
412 return SparcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;415 return SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
413 },416 },
414 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {417 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
415 return PowerpcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;418 return PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
416 },419 },
417 .riscv64, .riscv32 => {420 .riscv64, .riscv32 => {
418 return RiscvCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;421 return RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
419 },422 },
420 else => {},423 else => {},
421 }424 }
lib/std/zon/parse.zig+15-11
...@@ -411,16 +411,22 @@ const Parser = struct {...@@ -411,16 +411,22 @@ const Parser = struct {
411 diag: ?*Diagnostics,411 diag: ?*Diagnostics,
412 options: Options,412 options: Options,
413413
414 fn parseExpr(self: *@This(), T: type, node: Zoir.Node.Index) error{ ParseZon, OutOfMemory }!T {414 const ParseExprError = error{ ParseZon, OutOfMemory };
415
416 fn parseExpr(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprError!T {
415 return self.parseExprInner(T, node) catch |err| switch (err) {417 return self.parseExprInner(T, node) catch |err| switch (err) {
416 error.WrongType => return self.failExpectedType(T, node),418 error.WrongType => return self.failExpectedType(T, node),
417 else => |e| return e,419 else => |e| return e,
418 };420 };
419 }421 }
420422
421 const InnerError = error{ ParseZon, OutOfMemory, WrongType };423 const ParseExprInnerError = error{ ParseZon, OutOfMemory, WrongType };
422424
423 fn parseExprInner(self: *@This(), T: type, node: Zoir.Node.Index) InnerError!T {425 fn parseExprInner(
426 self: *@This(),
427 T: type,
428 node: Zoir.Node.Index,
429 ) ParseExprInnerError!T {
424 if (T == Zoir.Node.Index) {430 if (T == Zoir.Node.Index) {
425 return node;431 return node;
426 }432 }
...@@ -600,7 +606,7 @@ const Parser = struct {...@@ -600,7 +606,7 @@ const Parser = struct {
600 }606 }
601 }607 }
602608
603 fn parseSlicePointer(self: *@This(), T: type, node: Zoir.Node.Index) InnerError!T {609 fn parseSlicePointer(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprInnerError!T {
604 switch (node.get(self.zoir)) {610 switch (node.get(self.zoir)) {
605 .string_literal => return self.parseString(T, node),611 .string_literal => return self.parseString(T, node),
606 .array_literal => |nodes| return self.parseSlice(T, nodes),612 .array_literal => |nodes| return self.parseSlice(T, nodes),
...@@ -609,19 +615,17 @@ const Parser = struct {...@@ -609,19 +615,17 @@ const Parser = struct {
609 }615 }
610 }616 }
611617
612 fn parseString(self: *@This(), T: type, node: Zoir.Node.Index) InnerError!T {618 fn parseString(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprInnerError!T {
613 const ast_node = node.getAstNode(self.zoir);619 const ast_node = node.getAstNode(self.zoir);
614 const pointer = @typeInfo(T).pointer;620 const pointer = @typeInfo(T).pointer;
615 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);621 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);
616 if (pointer.sentinel() != null) size_hint += 1;622 if (pointer.sentinel() != null) size_hint += 1;
617 const gpa = self.gpa;
618623
619 var aw = try std.io.Writer.Allocating.initCapacity(gpa, size_hint);624 var aw: std.Io.Writer.Allocating = .init(self.gpa);
625 try aw.ensureUnusedCapacity(size_hint);
620 defer aw.deinit();626 defer aw.deinit();
621 const parsed = ZonGen.parseStrLit(self.ast, ast_node, &aw.interface) catch |err| switch (err) {627 const result = ZonGen.parseStrLit(self.ast, ast_node, &aw.writer) catch return error.OutOfMemory;
622 error.WriteFailed => return error.OutOfMemory,628 switch (result) {
623 };
624 switch (parsed) {
625 .success => {},629 .success => {},
626 .failure => |err| {630 .failure => |err| {
627 const token = self.ast.nodeMainToken(ast_node);631 const token = self.ast.nodeMainToken(ast_node);
src/Compilation.zig+73-71
...@@ -687,7 +687,7 @@ pub const Directories = struct {...@@ -687,7 +687,7 @@ pub const Directories = struct {
687 global,687 global,
688 },688 },
689 wasi_preopens: switch (builtin.target.os.tag) {689 wasi_preopens: switch (builtin.target.os.tag) {
690 .wasi => std.fs.wasi.Preopens,690 .wasi => fs.wasi.Preopens,
691 else => void,691 else => void,
692 },692 },
693 self_exe_path: switch (builtin.target.os.tag) {693 self_exe_path: switch (builtin.target.os.tag) {
...@@ -744,7 +744,7 @@ pub const Directories = struct {...@@ -744,7 +744,7 @@ pub const Directories = struct {
744 .local_cache = local_cache,744 .local_cache = local_cache,
745 };745 };
746 }746 }
747 fn openWasiPreopen(preopens: std.fs.wasi.Preopens, name: []const u8) Cache.Directory {747 fn openWasiPreopen(preopens: fs.wasi.Preopens, name: []const u8) Cache.Directory {
748 return .{748 return .{
749 .path = if (std.mem.eql(u8, name, ".")) null else name,749 .path = if (std.mem.eql(u8, name, ".")) null else name,
750 .handle = .{750 .handle = .{
...@@ -758,8 +758,8 @@ pub const Directories = struct {...@@ -758,8 +758,8 @@ pub const Directories = struct {
758 };758 };
759 const nonempty_path = if (path.len == 0) "." else path;759 const nonempty_path = if (path.len == 0) "." else path;
760 const handle_or_err = switch (thing) {760 const handle_or_err = switch (thing) {
761 .@"zig lib" => std.fs.cwd().openDir(nonempty_path, .{}),761 .@"zig lib" => fs.cwd().openDir(nonempty_path, .{}),
762 .@"global cache", .@"local cache" => std.fs.cwd().makeOpenPath(nonempty_path, .{}),762 .@"global cache", .@"local cache" => fs.cwd().makeOpenPath(nonempty_path, .{}),
763 };763 };
764 return .{764 return .{
765 .path = if (path.len == 0) null else path,765 .path = if (path.len == 0) null else path,
...@@ -996,15 +996,15 @@ pub const CObject = struct {...@@ -996,15 +996,15 @@ pub const CObject = struct {
996 const source_line = source_line: {996 const source_line = source_line: {
997 if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0;997 if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0;
998998
999 const file = std.fs.cwd().openFile(file_name, .{}) catch break :source_line 0;999 const file = fs.cwd().openFile(file_name, .{}) catch break :source_line 0;
1000 defer file.close();1000 defer file.close();
1001 var buffer: [1 << 10]u8 = undefined;1001 var buffer: [1024]u8 = undefined;
1002 var fr = file.reader(&buffer);1002 var file_reader = file.reader(&buffer);
1003 fr.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;1003 file_reader.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
1004 var bw: Writer = .fixed(&buffer);1004 var aw: Writer.Allocating = .init(eb.gpa);
1005 break :source_line try eb.addString(1005 defer aw.deinit();
1006 buffer[0 .. fr.interface.readDelimiterEnding(&bw, '\n') catch break :source_line 0],1006 _ = file_reader.interface.streamDelimiterEnding(&aw.writer, '\n') catch break :source_line 0;
1007 );1007 break :source_line try eb.addString(aw.getWritten());
1008 };1008 };
10091009
1010 return .{1010 return .{
...@@ -1071,7 +1071,7 @@ pub const CObject = struct {...@@ -1071,7 +1071,7 @@ pub const CObject = struct {
1071 };1071 };
10721072
1073 var buffer: [1024]u8 = undefined;1073 var buffer: [1024]u8 = undefined;
1074 const file = try std.fs.cwd().openFile(path, .{});1074 const file = try fs.cwd().openFile(path, .{});
1075 defer file.close();1075 defer file.close();
1076 var file_reader = file.reader(&buffer);1076 var file_reader = file.reader(&buffer);
1077 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface });1077 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface });
...@@ -1876,12 +1876,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1876,12 +1876,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18761876
1877 if (options.verbose_llvm_cpu_features) {1877 if (options.verbose_llvm_cpu_features) {
1878 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {1878 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
1879 const stderr_bw = std.debug.lockStderrWriter(&.{});1879 const stderr_w = std.debug.lockStderrWriter(&.{});
1880 defer std.debug.unlockStderrWriter();1880 defer std.debug.unlockStderrWriter();
1881 stderr_bw.print("compilation: {s}\n", .{options.root_name}) catch break :print;1881 stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1882 stderr_bw.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;1882 stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
1883 stderr_bw.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;1883 stderr_w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
1884 stderr_bw.print(" features: {s}\n", .{cf}) catch {};1884 stderr_w.print(" features: {s}\n", .{cf}) catch {};
1885 }1885 }
1886 }1886 }
18871887
...@@ -1901,7 +1901,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1901,7 +1901,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1901 .manifest_dir = try options.dirs.local_cache.handle.makeOpenPath("h", .{}),1901 .manifest_dir = try options.dirs.local_cache.handle.makeOpenPath("h", .{}),
1902 };1902 };
1903 // These correspond to std.zig.Server.Message.PathPrefix.1903 // These correspond to std.zig.Server.Message.PathPrefix.
1904 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });1904 cache.addPrefix(.{ .path = null, .handle = fs.cwd() });
1905 cache.addPrefix(options.dirs.zig_lib);1905 cache.addPrefix(options.dirs.zig_lib);
1906 cache.addPrefix(options.dirs.local_cache);1906 cache.addPrefix(options.dirs.local_cache);
1907 cache.addPrefix(options.dirs.global_cache);1907 cache.addPrefix(options.dirs.global_cache);
...@@ -2192,7 +2192,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -2192,7 +2192,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
2192 comp.digest = hash.peekBin();2192 comp.digest = hash.peekBin();
2193 const digest = hash.final();2193 const digest = hash.final();
21942194
2195 const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest;2195 const artifact_sub_dir = "o" ++ fs.path.sep_str ++ digest;
2196 var artifact_dir = try options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{});2196 var artifact_dir = try options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{});
2197 errdefer artifact_dir.close();2197 errdefer artifact_dir.close();
2198 const artifact_directory: Cache.Directory = .{2198 const artifact_directory: Cache.Directory = .{
...@@ -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
...@@ -2604,11 +2604,11 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {...@@ -2604,11 +2604,11 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
2604 // temporary directories; it doesn't have a real cache directory anyway.2604 // temporary directories; it doesn't have a real cache directory anyway.
2605 return;2605 return;
2606 }2606 }
2607 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);2607 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2608 comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {2608 comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
2609 log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{2609 log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
2610 comp.dirs.local_cache.path orelse ".",2610 comp.dirs.local_cache.path orelse ".",
2611 std.fs.path.sep,2611 fs.path.sep,
2612 tmp_dir_sub_path,2612 tmp_dir_sub_path,
2613 @errorName(err),2613 @errorName(err),
2614 });2614 });
...@@ -2628,11 +2628,11 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {...@@ -2628,11 +2628,11 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
2628 if (whole.tmp_artifact_directory) |*tmp_dir| {2628 if (whole.tmp_artifact_directory) |*tmp_dir| {
2629 tmp_dir.handle.close();2629 tmp_dir.handle.close();
2630 whole.tmp_artifact_directory = null;2630 whole.tmp_artifact_directory = null;
2631 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);2631 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2632 comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {2632 comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
2633 log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{2633 log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
2634 comp.dirs.local_cache.path orelse ".",2634 comp.dirs.local_cache.path orelse ".",
2635 std.fs.path.sep,2635 fs.path.sep,
2636 tmp_dir_sub_path,2636 tmp_dir_sub_path,
2637 @errorName(err),2637 @errorName(err),
2638 });2638 });
...@@ -2668,7 +2668,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2668,7 +2668,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2668 assert(none.tmp_artifact_directory == null);2668 assert(none.tmp_artifact_directory == null);
2669 none.tmp_artifact_directory = d: {2669 none.tmp_artifact_directory = d: {
2670 tmp_dir_rand_int = std.crypto.random.int(u64);2670 tmp_dir_rand_int = std.crypto.random.int(u64);
2671 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);2671 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2672 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});2672 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
2673 break :d .{2673 break :d .{
2674 .path = path,2674 .path = path,
...@@ -2735,7 +2735,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2735,7 +2735,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2735 // Compile the artifacts to a temporary directory.2735 // Compile the artifacts to a temporary directory.
2736 whole.tmp_artifact_directory = d: {2736 whole.tmp_artifact_directory = d: {
2737 tmp_dir_rand_int = std.crypto.random.int(u64);2737 tmp_dir_rand_int = std.crypto.random.int(u64);
2738 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);2738 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2739 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});2739 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
2740 break :d .{2740 break :d .{
2741 .path = path,2741 .path = path,
...@@ -2910,7 +2910,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2910,7 +2910,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2910 // Close tmp dir and link.File to avoid open handle during rename.2910 // Close tmp dir and link.File to avoid open handle during rename.
2911 whole.tmp_artifact_directory.?.handle.close();2911 whole.tmp_artifact_directory.?.handle.close();
2912 whole.tmp_artifact_directory = null;2912 whole.tmp_artifact_directory = null;
2913 const s = std.fs.path.sep_str;2913 const s = fs.path.sep_str;
2914 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);2914 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
2915 const o_sub_path = "o" ++ s ++ hex_digest;2915 const o_sub_path = "o" ++ s ++ hex_digest;
2916 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {2916 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
...@@ -2932,7 +2932,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2932,7 +2932,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2932 if (comp.bin_file) |lf| {2932 if (comp.bin_file) |lf| {
2933 lf.emit = .{2933 lf.emit = .{
2934 .root_dir = comp.dirs.local_cache,2934 .root_dir = comp.dirs.local_cache,
2935 .sub_path = try std.fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),2935 .sub_path = try fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
2936 };2936 };
29372937
2938 switch (need_writable_dance) {2938 switch (need_writable_dance) {
...@@ -3105,7 +3105,7 @@ fn renameTmpIntoCache(...@@ -3105,7 +3105,7 @@ fn renameTmpIntoCache(
3105) !void {3105) !void {
3106 var seen_eaccess = false;3106 var seen_eaccess = false;
3107 while (true) {3107 while (true) {
3108 std.fs.rename(3108 fs.rename(
3109 cache_directory.handle,3109 cache_directory.handle,
3110 tmp_dir_sub_path,3110 tmp_dir_sub_path,
3111 cache_directory.handle,3111 cache_directory.handle,
...@@ -3931,12 +3931,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3931,12 +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 var stderr_bw = std.debug.lockStderrWriter(&.{});3934 var stderr_w = std.debug.lockStderrWriter(&.{});
3935 defer std.debug.unlockStderrWriter();3935 defer std.debug.unlockStderrWriter();
3936 try stderr_bw.writeAll("referenced transitive analysis errors, but none actually emitted\n");3936 try stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3937 try stderr_bw.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});3937 try stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
3938 while (ref) |r| {3938 while (ref) |r| {
3939 try stderr_bw.print("referenced by: {f}{s}\n", .{3939 try stderr_w.print("referenced by: {f}{s}\n", .{
3940 zcu.fmtAnalUnit(r.referencer),3940 zcu.fmtAnalUnit(r.referencer),
3941 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",3941 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
3942 });3942 });
...@@ -4843,7 +4843,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4843,7 +4843,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4843 defer out_dir.close();4843 defer out_dir.close();
48444844
4845 for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| {4845 for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| {
4846 const basename = std.fs.path.basename(sub_path);4846 const basename = fs.path.basename(sub_path);
4847 comp.dirs.zig_lib.handle.copyFile(sub_path, out_dir, basename, .{}) catch |err| {4847 comp.dirs.zig_lib.handle.copyFile(sub_path, out_dir, basename, .{}) catch |err| {
4848 comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {s}", .{4848 comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {s}", .{
4849 sub_path,4849 sub_path,
...@@ -4879,7 +4879,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4879,7 +4879,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4879 }4879 }
4880}4880}
48814881
4882fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: std.fs.File) !void {4882fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: fs.File) !void {
4883 const root = module.root;4883 const root = module.root;
4884 var mod_dir = d: {4884 var mod_dir = d: {
4885 const root_dir, const sub_path = root.openInfo(comp.dirs);4885 const root_dir, const sub_path = root.openInfo(comp.dirs);
...@@ -4974,7 +4974,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -4974,7 +4974,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
4974 });4974 });
49754975
4976 const src_basename = "main.zig";4976 const src_basename = "main.zig";
4977 const root_name = std.fs.path.stem(src_basename);4977 const root_name = fs.path.stem(src_basename);
49784978
4979 const dirs = comp.dirs.withoutLocalCache();4979 const dirs = comp.dirs.withoutLocalCache();
49804980
...@@ -5069,13 +5069,13 @@ fn workerUpdateFile(...@@ -5069,13 +5069,13 @@ fn workerUpdateFile(
5069 prog_node: std.Progress.Node,5069 prog_node: std.Progress.Node,
5070 wg: *WaitGroup,5070 wg: *WaitGroup,
5071) void {5071) void {
5072 const child_prog_node = prog_node.start(std.fs.path.basename(file.path.sub_path), 0);5072 const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0);
5073 defer child_prog_node.end();5073 defer child_prog_node.end();
50745074
5075 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));5075 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
5076 defer pt.deactivate();5076 defer pt.deactivate();
5077 pt.updateFile(file_index, file) catch |err| {5077 pt.updateFile(file_index, file) catch |err| {
5078 pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {5078 pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
5079 error.OutOfMemory => {5079 error.OutOfMemory => {
5080 comp.mutex.lock();5080 comp.mutex.lock();
5081 defer comp.mutex.unlock();5081 defer comp.mutex.unlock();
...@@ -5240,7 +5240,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module...@@ -5240,7 +5240,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
5240 const arena = arena_allocator.allocator();5240 const arena = arena_allocator.allocator();
52415241
5242 const tmp_digest = man.hash.peek();5242 const tmp_digest = man.hash.peek();
5243 const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });5243 const tmp_dir_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });
5244 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});5244 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
5245 defer zig_cache_tmp_dir.close();5245 defer zig_cache_tmp_dir.close();
5246 const cimport_basename = "cimport.h";5246 const cimport_basename = "cimport.h";
...@@ -5309,7 +5309,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module...@@ -5309,7 +5309,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
5309 log.info("C import .d file: {s}", .{out_dep_path});5309 log.info("C import .d file: {s}", .{out_dep_path});
5310 }5310 }
53115311
5312 const dep_basename = std.fs.path.basename(out_dep_path);5312 const dep_basename = fs.path.basename(out_dep_path);
5313 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);5313 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
5314 switch (comp.cache_use) {5314 switch (comp.cache_use) {
5315 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {5315 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
...@@ -5322,14 +5322,14 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module...@@ -5322,14 +5322,14 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
53225322
5323 const bin_digest = man.finalBin();5323 const bin_digest = man.finalBin();
5324 const hex_digest = Cache.binToHex(bin_digest);5324 const hex_digest = Cache.binToHex(bin_digest);
5325 const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest;5325 const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
5326 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});5326 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
5327 defer o_dir.close();5327 defer o_dir.close();
53285328
5329 var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{});5329 var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{});
5330 defer out_zig_file.close();5330 defer out_zig_file.close();
53315331
5332 const formatted = try tree.render(comp.gpa);5332 const formatted = try tree.renderAlloc(comp.gpa);
5333 defer comp.gpa.free(formatted);5333 defer comp.gpa.free(formatted);
53345334
5335 try out_zig_file.writeAll(formatted);5335 try out_zig_file.writeAll(formatted);
...@@ -5675,7 +5675,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5675,7 +5675,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5675 defer arena_allocator.deinit();5675 defer arena_allocator.deinit();
5676 const arena = arena_allocator.allocator();5676 const arena = arena_allocator.allocator();
56775677
5678 const c_source_basename = std.fs.path.basename(c_object.src.src_path);5678 const c_source_basename = fs.path.basename(c_object.src.src_path);
56795679
5680 const child_progress_node = c_obj_prog_node.start(c_source_basename, 0);5680 const child_progress_node = c_obj_prog_node.start(c_source_basename, 0);
5681 defer child_progress_node.end();5681 defer child_progress_node.end();
...@@ -5688,7 +5688,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5688,7 +5688,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5688 const o_basename_noext = if (direct_o)5688 const o_basename_noext = if (direct_o)
5689 comp.root_name5689 comp.root_name
5690 else5690 else
5691 c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len];5691 c_source_basename[0 .. c_source_basename.len - fs.path.extension(c_source_basename).len];
56925692
5693 const target = comp.getTarget();5693 const target = comp.getTarget();
5694 const o_ext = target.ofmt.fileExt(target.cpu.arch);5694 const o_ext = target.ofmt.fileExt(target.cpu.arch);
...@@ -5815,11 +5815,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5815,11 +5815,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5815 }5815 }
58165816
5817 // Just to save disk space, we delete the files that are never needed again.5817 // Just to save disk space, we delete the files that are never needed again.
5818 defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(std.fs.path.basename(diag_file_path)) catch |err| switch (err) {5818 defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(diag_file_path)) catch |err| switch (err) {
5819 error.FileNotFound => {}, // the file wasn't created due to an error we reported5819 error.FileNotFound => {}, // the file wasn't created due to an error we reported
5820 else => log.warn("failed to delete '{s}': {s}", .{ diag_file_path, @errorName(err) }),5820 else => log.warn("failed to delete '{s}': {s}", .{ diag_file_path, @errorName(err) }),
5821 };5821 };
5822 defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(std.fs.path.basename(dep_file_path)) catch |err| switch (err) {5822 defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(dep_file_path)) catch |err| switch (err) {
5823 error.FileNotFound => {}, // the file wasn't created due to an error we reported5823 error.FileNotFound => {}, // the file wasn't created due to an error we reported
5824 else => log.warn("failed to delete '{s}': {s}", .{ dep_file_path, @errorName(err) }),5824 else => log.warn("failed to delete '{s}': {s}", .{ dep_file_path, @errorName(err) }),
5825 };5825 };
...@@ -5890,7 +5890,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5890,7 +5890,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5890 }5890 }
58915891
5892 if (out_dep_path) |dep_file_path| {5892 if (out_dep_path) |dep_file_path| {
5893 const dep_basename = std.fs.path.basename(dep_file_path);5893 const dep_basename = fs.path.basename(dep_file_path);
5894 // Add the files depended on to the cache system.5894 // Add the files depended on to the cache system.
5895 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);5895 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
5896 switch (comp.cache_use) {5896 switch (comp.cache_use) {
...@@ -5910,11 +5910,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5910,11 +5910,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
59105910
5911 // Rename into place.5911 // Rename into place.
5912 const digest = man.final();5912 const digest = man.final();
5913 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });5913 const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest });
5914 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});5914 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
5915 defer o_dir.close();5915 defer o_dir.close();
5916 const tmp_basename = std.fs.path.basename(out_obj_path);5916 const tmp_basename = fs.path.basename(out_obj_path);
5917 try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename);5917 try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename);
5918 break :blk digest;5918 break :blk digest;
5919 };5919 };
59205920
...@@ -5936,7 +5936,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5936,7 +5936,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5936 .success = .{5936 .success = .{
5937 .object_path = .{5937 .object_path = .{
5938 .root_dir = comp.dirs.local_cache,5938 .root_dir = comp.dirs.local_cache,
5939 .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, o_basename }),5939 .sub_path = try fs.path.join(gpa, &.{ "o", &digest, o_basename }),
5940 },5940 },
5941 .lock = man.toOwnedLock(),5941 .lock = man.toOwnedLock(),
5942 },5942 },
...@@ -5960,7 +5960,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5960,7 +5960,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5960 .rc => |rc_src| rc_src.src_path,5960 .rc => |rc_src| rc_src.src_path,
5961 .manifest => |src_path| src_path,5961 .manifest => |src_path| src_path,
5962 };5962 };
5963 const src_basename = std.fs.path.basename(src_path);5963 const src_basename = fs.path.basename(src_path);
59645964
5965 log.debug("updating win32 resource: {s}", .{src_path});5965 log.debug("updating win32 resource: {s}", .{src_path});
59665966
...@@ -5997,7 +5997,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5997,7 +5997,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5997 // get the digest now and write the .res directly to the cache5997 // get the digest now and write the .res directly to the cache
5998 const digest = man.final();5998 const digest = man.final();
59995999
6000 const o_sub_path = try std.fs.path.join(arena, &.{ "o", &digest });6000 const o_sub_path = try fs.path.join(arena, &.{ "o", &digest });
6001 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});6001 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
6002 defer o_dir.close();6002 defer o_dir.close();
60036003
...@@ -6083,7 +6083,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6083,7 +6083,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6083 _ = try man.addFile(rc_src.src_path, null);6083 _ = try man.addFile(rc_src.src_path, null);
6084 man.hash.addListOfBytes(rc_src.extra_flags);6084 man.hash.addListOfBytes(rc_src.extra_flags);
60856085
6086 const rc_basename_noext = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];6086 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];
60876087
6088 const digest = if (try man.hit()) man.final() else blk: {6088 const digest = if (try man.hit()) man.final() else blk: {
6089 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{});6089 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{});
...@@ -6128,7 +6128,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6128,7 +6128,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
61286128
6129 // Read depfile and update cache manifest6129 // Read depfile and update cache manifest
6130 {6130 {
6131 const dep_basename = std.fs.path.basename(out_dep_path);6131 const dep_basename = fs.path.basename(out_dep_path);
6132 const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(arena, dep_basename, 50 * 1024 * 1024);6132 const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(arena, dep_basename, 50 * 1024 * 1024);
6133 defer arena.free(dep_file_contents);6133 defer arena.free(dep_file_contents);
61346134
...@@ -6156,11 +6156,11 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6156,11 +6156,11 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
61566156
6157 // Rename into place.6157 // Rename into place.
6158 const digest = man.final();6158 const digest = man.final();
6159 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });6159 const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest });
6160 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});6160 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
6161 defer o_dir.close();6161 defer o_dir.close();
6162 const tmp_basename = std.fs.path.basename(out_res_path);6162 const tmp_basename = fs.path.basename(out_res_path);
6163 try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename);6163 try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename);
6164 break :blk digest;6164 break :blk digest;
6165 };6165 };
61666166
...@@ -6268,7 +6268,7 @@ fn spawnZigRc(...@@ -6268,7 +6268,7 @@ fn spawnZigRc(
6268}6268}
62696269
6270pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {6270pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
6271 const s = std.fs.path.sep_str;6271 const s = fs.path.sep_str;
6272 const rand_int = std.crypto.random.int(u64);6272 const rand_int = std.crypto.random.int(u64);
6273 if (comp.dirs.local_cache.path) |p| {6273 if (comp.dirs.local_cache.path) |p| {
6274 return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });6274 return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
...@@ -6518,12 +6518,12 @@ pub fn addCCArgs(...@@ -6518,12 +6518,12 @@ pub fn addCCArgs(
65186518
6519 if (comp.config.link_libcpp) {6519 if (comp.config.link_libcpp) {
6520 try argv.append("-isystem");6520 try argv.append("-isystem");
6521 try argv.append(try std.fs.path.join(arena, &[_][]const u8{6521 try argv.append(try fs.path.join(arena, &[_][]const u8{
6522 comp.dirs.zig_lib.path.?, "libcxx", "include",6522 comp.dirs.zig_lib.path.?, "libcxx", "include",
6523 }));6523 }));
65246524
6525 try argv.append("-isystem");6525 try argv.append("-isystem");
6526 try argv.append(try std.fs.path.join(arena, &[_][]const u8{6526 try argv.append(try fs.path.join(arena, &[_][]const u8{
6527 comp.dirs.zig_lib.path.?, "libcxxabi", "include",6527 comp.dirs.zig_lib.path.?, "libcxxabi", "include",
6528 }));6528 }));
65296529
...@@ -6534,7 +6534,7 @@ pub fn addCCArgs(...@@ -6534,7 +6534,7 @@ pub fn addCCArgs(
6534 // However as noted by @dimenus, appending libc headers before compiler headers breaks6534 // However as noted by @dimenus, appending libc headers before compiler headers breaks
6535 // intrinsics and other compiler specific items.6535 // intrinsics and other compiler specific items.
6536 try argv.append("-isystem");6536 try argv.append("-isystem");
6537 try argv.append(try std.fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "include" }));6537 try argv.append(try fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "include" }));
65386538
6539 try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);6539 try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);
6540 for (comp.libc_include_dir_list) |include_dir| {6540 for (comp.libc_include_dir_list) |include_dir| {
...@@ -6552,7 +6552,7 @@ pub fn addCCArgs(...@@ -6552,7 +6552,7 @@ pub fn addCCArgs(
65526552
6553 if (comp.config.link_libunwind) {6553 if (comp.config.link_libunwind) {
6554 try argv.append("-isystem");6554 try argv.append("-isystem");
6555 try argv.append(try std.fs.path.join(arena, &[_][]const u8{6555 try argv.append(try fs.path.join(arena, &[_][]const u8{
6556 comp.dirs.zig_lib.path.?, "libunwind", "include",6556 comp.dirs.zig_lib.path.?, "libunwind", "include",
6557 }));6557 }));
6558 }6558 }
...@@ -7145,7 +7145,7 @@ fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8)...@@ -7145,7 +7145,7 @@ fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8)
7145 return (try crtFilePath(&comp.crt_files, basename)) orelse {7145 return (try crtFilePath(&comp.crt_files, basename)) orelse {
7146 const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable;7146 const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable;
7147 const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir;7147 const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir;
7148 const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename });7148 const full_path = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename });
7149 return Cache.Path.initCwd(full_path);7149 return Cache.Path.initCwd(full_path);
7150 };7150 };
7151}7151}
...@@ -7207,13 +7207,15 @@ pub fn lockAndSetMiscFailure(...@@ -7207,13 +7207,15 @@ pub fn lockAndSetMiscFailure(
7207}7207}
72087208
7209pub fn dump_argv(argv: []const []const u8) void {7209pub fn dump_argv(argv: []const []const u8) void {
7210 var stderr = std.debug.lockStdErr2(&.{});7210 var buffer: [64]u8 = undefined;
7211 defer std.debug.unlockStdErr();7211 const stderr = std.debug.lockStderrWriter(&buffer);
7212 defer std.debug.unlockStderrWriter();
7212 nosuspend {7213 nosuspend {
7213 for (argv[0 .. argv.len - 1]) |arg| {7214 for (argv) |arg| {
7214 stderr.print("{s} ", .{arg}) catch return;7215 stderr.writeAll(arg) catch return;
7216 (stderr.writableArray(1) catch return)[0] = ' ';
7215 }7217 }
7216 stderr.print("{s}\n", .{argv[argv.len - 1]}) catch {};7218 stderr.buffer[stderr.end - 1] = '\n';
7217 }7219 }
7218}7220}
72197221
...@@ -7541,7 +7543,7 @@ pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {...@@ -7541,7 +7543,7 @@ pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {
7541 return .{7543 return .{
7542 .full_object_path = .{7544 .full_object_path = .{
7543 .root_dir = comp.dirs.local_cache,7545 .root_dir = comp.dirs.local_cache,
7544 .sub_path = try std.fs.path.join(comp.gpa, &.{7546 .sub_path = try fs.path.join(comp.gpa, &.{
7545 "o",7547 "o",
7546 &Cache.binToHex(comp.digest.?),7548 &Cache.binToHex(comp.digest.?),
7547 comp.emit_bin.?,7549 comp.emit_bin.?,
src/Package/Manifest.zig+8-4
...@@ -471,10 +471,14 @@ const Parse = struct {...@@ -471,10 +471,14 @@ const Parse = struct {
471 offset: u32,471 offset: u32,
472 ) InnerError!void {472 ) InnerError!void {
473 const raw_string = bytes[offset..];473 const raw_string = bytes[offset..];
474 var aw: std.io.Writer.Allocating = .fromArrayList(p.gpa, buf);474 const result = r: {
475 const result = std.zig.string_literal.parseWrite(&aw.interface, raw_string);475 var aw: std.io.Writer.Allocating = .fromArrayList(p.gpa, buf);
476 buf.* = aw.toArrayList();476 defer buf.* = aw.toArrayList();
477 switch (result catch return error.OutOfMemory) {477 break :r std.zig.string_literal.parseWrite(&aw.writer, raw_string) catch |err| switch (err) {
478 error.WriteFailed => return error.OutOfMemory,
479 };
480 };
481 switch (result) {
478 .success => {},482 .success => {},
479 .failure => |err| try p.appendStrLitError(err, token, bytes, offset),483 .failure => |err| try p.appendStrLitError(err, token, bytes, offset),
480 }484 }
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.GenericReader` 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.GenericWriter` 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/fmt.zig+31-29
...@@ -35,8 +35,8 @@ const Fmt = struct {...@@ -35,8 +35,8 @@ const Fmt = struct {
35 color: Color,35 color: Color,
36 gpa: Allocator,36 gpa: Allocator,
37 arena: Allocator,37 arena: Allocator,
38 out_buffer: std.ArrayListUnmanaged(u8),38 out_buffer: std.Io.Writer.Allocating,
39 stdout_writer: *File.Writer,39 stdout_writer: *fs.File.Writer,
4040
41 const SeenMap = std.AutoHashMap(fs.File.INode, void);41 const SeenMap = std.AutoHashMap(fs.File.INode, void);
42};42};
...@@ -58,7 +58,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -58,7 +58,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
58 const arg = args[i];58 const arg = args[i];
59 if (mem.startsWith(u8, arg, "-")) {59 if (mem.startsWith(u8, arg, "-")) {
60 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {60 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
61 try File.stdout().writeAll(usage_fmt);61 try fs.File.stdout().writeAll(usage_fmt);
62 return process.cleanExit();62 return process.cleanExit();
63 } else if (mem.eql(u8, arg, "--color")) {63 } else if (mem.eql(u8, arg, "--color")) {
64 if (i + 1 >= args.len) {64 if (i + 1 >= args.len) {
...@@ -98,7 +98,10 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -98,7 +98,10 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
98 fatal("cannot use --stdin with positional arguments", .{});98 fatal("cannot use --stdin with positional arguments", .{});
99 }99 }
100100
101 const source_code = std.zig.readSourceFileToEndAlloc(gpa, .stdin(), 0) catch |err| {101 const stdin: fs.File = .stdin();
102 var stdio_buffer: [1024]u8 = undefined;
103 var file_reader: fs.File.Reader = stdin.reader(&stdio_buffer);
104 const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| {
102 fatal("unable to read stdin: {}", .{err});105 fatal("unable to read stdin: {}", .{err});
103 };106 };
104 defer gpa.free(source_code);107 defer gpa.free(source_code);
...@@ -142,17 +145,15 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -142,17 +145,15 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
142 try std.zig.printAstErrorsToStderr(gpa, tree, "<stdin>", color);145 try std.zig.printAstErrorsToStderr(gpa, tree, "<stdin>", color);
143 process.exit(2);146 process.exit(2);
144 }147 }
145 var aw: std.io.Writer.Allocating = .init(gpa);148 const formatted = try tree.renderAlloc(gpa);
146 defer aw.deinit();149 defer gpa.free(formatted);
147 try tree.render(gpa, &aw.interface, .{});
148 const formatted = aw.getWritten();
149150
150 if (check_flag) {151 if (check_flag) {
151 const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code));152 const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code));
152 process.exit(code);153 process.exit(code);
153 }154 }
154155
155 return File.stdout().writeAll(formatted);156 return fs.File.stdout().writeAll(formatted);
156 }157 }
157158
158 if (input_files.items.len == 0) {159 if (input_files.items.len == 0) {
...@@ -160,7 +161,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -160,7 +161,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
160 }161 }
161162
162 var stdout_buffer: [4096]u8 = undefined;163 var stdout_buffer: [4096]u8 = undefined;
163 var stdout_writer = File.stdout().writer(&stdout_buffer);164 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
164165
165 var fmt: Fmt = .{166 var fmt: Fmt = .{
166 .gpa = gpa,167 .gpa = gpa,
...@@ -170,7 +171,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -170,7 +171,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
170 .check_ast = check_ast_flag,171 .check_ast = check_ast_flag,
171 .force_zon = force_zon,172 .force_zon = force_zon,
172 .color = color,173 .color = color,
173 .out_buffer = .empty,174 .out_buffer = .init(gpa),
174 .stdout_writer = &stdout_writer,175 .stdout_writer = &stdout_writer,
175 };176 };
176 defer fmt.seen.deinit();177 defer fmt.seen.deinit();
...@@ -198,10 +199,10 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -198,10 +199,10 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
198 if (fmt.any_error) {199 if (fmt.any_error) {
199 process.exit(1);200 process.exit(1);
200 }201 }
201 try fmt.stdout_writer.flush();202 try fmt.stdout_writer.interface.flush();
202}203}
203204
204fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) anyerror!void {205fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) !void {
205 fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {206 fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {
206 error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),207 error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),
207 else => {208 else => {
...@@ -218,7 +219,7 @@ fn fmtPathDir(...@@ -218,7 +219,7 @@ fn fmtPathDir(
218 check_mode: bool,219 check_mode: bool,
219 parent_dir: fs.Dir,220 parent_dir: fs.Dir,
220 parent_sub_path: []const u8,221 parent_sub_path: []const u8,
221) anyerror!void {222) !void {
222 var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });223 var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });
223 defer dir.close();224 defer dir.close();
224225
...@@ -254,7 +255,7 @@ fn fmtPathFile(...@@ -254,7 +255,7 @@ fn fmtPathFile(
254 check_mode: bool,255 check_mode: bool,
255 dir: fs.Dir,256 dir: fs.Dir,
256 sub_path: []const u8,257 sub_path: []const u8,
257) anyerror!void {258) !void {
258 const source_file = try dir.openFile(sub_path, .{});259 const source_file = try dir.openFile(sub_path, .{});
259 var file_closed = false;260 var file_closed = false;
260 errdefer if (!file_closed) source_file.close();261 errdefer if (!file_closed) source_file.close();
...@@ -264,12 +265,15 @@ fn fmtPathFile(...@@ -264,12 +265,15 @@ fn fmtPathFile(
264 if (stat.kind == .directory)265 if (stat.kind == .directory)
265 return error.IsDir;266 return error.IsDir;
266267
268 var read_buffer: [1024]u8 = undefined;
269 var file_reader: fs.File.Reader = source_file.reader(&read_buffer);
270 file_reader.size = stat.size;
271
267 const gpa = fmt.gpa;272 const gpa = fmt.gpa;
268 const source_code = try std.zig.readSourceFileToEndAlloc(273 const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| switch (err) {
269 gpa,274 error.ReadFailed => return file_reader.err.?,
270 source_file,275 else => |e| return e,
271 std.math.cast(usize, stat.size) orelse return error.FileTooBig,276 };
272 );
273 defer gpa.free(source_code);277 defer gpa.free(source_code);
274278
275 source_file.close();279 source_file.close();
...@@ -332,15 +336,13 @@ fn fmtPathFile(...@@ -332,15 +336,13 @@ fn fmtPathFile(
332 }336 }
333337
334 // As a heuristic, we make enough capacity for the same as the input source.338 // As a heuristic, we make enough capacity for the same as the input source.
335 fmt.out_buffer.shrinkRetainingCapacity(0);339 fmt.out_buffer.clearRetainingCapacity();
336 try fmt.out_buffer.ensureTotalCapacity(gpa, source_code.len);340 try fmt.out_buffer.ensureTotalCapacity(source_code.len);
337341
338 {342 tree.render(gpa, &fmt.out_buffer.writer, .{}) catch |err| switch (err) {
339 var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &fmt.out_buffer);343 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
340 defer fmt.out_buffer = aw.toArrayList();344 };
341 try tree.render(gpa, &aw.interface, .{});345 if (mem.eql(u8, fmt.out_buffer.getWritten(), source_code))
342 }
343 if (mem.eql(u8, fmt.out_buffer.items, source_code))
344 return;346 return;
345347
346 if (check_mode) {348 if (check_mode) {
...@@ -350,7 +352,7 @@ fn fmtPathFile(...@@ -350,7 +352,7 @@ fn fmtPathFile(
350 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });352 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });
351 defer af.deinit();353 defer af.deinit();
352354
353 try af.file.writeAll(fmt.out_buffer.items);355 try af.file.writeAll(fmt.out_buffer.getWritten());
354 try af.finish();356 try af.finish();
355 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});357 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
356 }358 }
src/link/Lld.zig+1-2
...@@ -205,7 +205,6 @@ pub fn createEmpty(...@@ -205,7 +205,6 @@ pub fn createEmpty(
205 const target = &comp.root_mod.resolved_target.result;205 const target = &comp.root_mod.resolved_target.result;
206 const output_mode = comp.config.output_mode;206 const output_mode = comp.config.output_mode;
207 const optimize_mode = comp.root_mod.optimize_mode;207 const optimize_mode = comp.root_mod.optimize_mode;
208 const is_native_os = comp.root_mod.resolved_target.is_native_os;
209208
210 const obj_file_ext: []const u8 = switch (target.ofmt) {209 const obj_file_ext: []const u8 = switch (target.ofmt) {
211 .coff => "obj",210 .coff => "obj",
...@@ -234,7 +233,7 @@ pub fn createEmpty(...@@ -234,7 +233,7 @@ pub fn createEmpty(
234 .gc_sections = gc_sections,233 .gc_sections = gc_sections,
235 .print_gc_sections = options.print_gc_sections,234 .print_gc_sections = options.print_gc_sections,
236 .stack_size = stack_size,235 .stack_size = stack_size,
237 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,236 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
238 .file = null,237 .file = null,
239 .build_id = options.build_id,238 .build_id = options.build_id,
240 },239 },
src/main.zig+25-20
...@@ -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!
...@@ -3561,10 +3563,12 @@ fn buildOutputType(...@@ -3561,10 +3563,12 @@ fn buildOutputType(
3561 switch (listen) {3563 switch (listen) {
3562 .none => {},3564 .none => {},
3563 .stdio => {3565 .stdio => {
3566 var stdin_reader = fs.File.stdin().reader(&stdin_buffer);
3567 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
3564 try serve(3568 try serve(
3565 comp,3569 comp,
3566 .stdin(),3570 &stdin_reader.interface,
3567 .stdout(),3571 &stdout_writer.interface,
3568 test_exec_args.items,3572 test_exec_args.items,
3569 self_exe_path,3573 self_exe_path,
3570 arg_mode,3574 arg_mode,
...@@ -3584,10 +3588,13 @@ fn buildOutputType(...@@ -3584,10 +3588,13 @@ fn buildOutputType(
3584 const conn = try server.accept();3588 const conn = try server.accept();
3585 defer conn.stream.close();3589 defer conn.stream.close();
35863590
3591 var input = conn.stream.reader(&stdin_buffer);
3592 var output = conn.stream.writer(&stdout_buffer);
3593
3587 try serve(3594 try serve(
3588 comp,3595 comp,
3589 .{ .handle = conn.stream.handle },3596 input.interface(),
3590 .{ .handle = conn.stream.handle },3597 &output.interface,
3591 test_exec_args.items,3598 test_exec_args.items,
3592 self_exe_path,3599 self_exe_path,
3593 arg_mode,3600 arg_mode,
...@@ -4053,8 +4060,8 @@ fn saveState(comp: *Compilation, incremental: bool) void {...@@ -4053,8 +4060,8 @@ fn saveState(comp: *Compilation, incremental: bool) void {
40534060
4054fn serve(4061fn serve(
4055 comp: *Compilation,4062 comp: *Compilation,
4056 in: fs.File,4063 in: *std.Io.Reader,
4057 out: fs.File,4064 out: *std.Io.Writer,
4058 test_exec_args: []const ?[]const u8,4065 test_exec_args: []const ?[]const u8,
4059 self_exe_path: ?[]const u8,4066 self_exe_path: ?[]const u8,
4060 arg_mode: ArgMode,4067 arg_mode: ArgMode,
...@@ -4064,12 +4071,10 @@ fn serve(...@@ -4064,12 +4071,10 @@ fn serve(
4064 const gpa = comp.gpa;4071 const gpa = comp.gpa;
40654072
4066 var server = try Server.init(.{4073 var server = try Server.init(.{
4067 .gpa = gpa,
4068 .in = in,4074 .in = in,
4069 .out = out,4075 .out = out,
4070 .zig_version = build_options.version,4076 .zig_version = build_options.version,
4071 });4077 });
4072 defer server.deinit();
40734078
4074 var child_pid: ?std.process.Child.Id = null;4079 var child_pid: ?std.process.Child.Id = null;
40754080
...@@ -5491,10 +5496,10 @@ fn jitCmd(...@@ -5491,10 +5496,10 @@ fn jitCmd(
5491 defer comp.destroy();5496 defer comp.destroy();
54925497
5493 if (options.server) {5498 if (options.server) {
5499 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
5494 var server: std.zig.Server = .{5500 var server: std.zig.Server = .{
5495 .out = fs.File.stdout(),5501 .out = &stdout_writer.interface,
5496 .in = undefined, // won't be receiving messages5502 .in = undefined, // won't be receiving messages
5497 .receive_fifo = undefined, // won't be receiving messages
5498 };5503 };
54995504
5500 try comp.update(root_prog_node);5505 try comp.update(root_prog_node);
...@@ -6058,7 +6063,7 @@ fn cmdAstCheck(...@@ -6058,7 +6063,7 @@ fn cmdAstCheck(
6058 };6063 };
6059 } else fs.File.stdin();6064 } else fs.File.stdin();
6060 defer if (zig_source_path != null) f.close();6065 defer if (zig_source_path != null) f.close();
6061 var file_reader: fs.File.Reader = f.reader(&stdio_buffer);6066 var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
6062 break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| {6067 break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| {
6063 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });6068 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
6064 };6069 };
...@@ -6076,7 +6081,7 @@ fn cmdAstCheck(...@@ -6076,7 +6081,7 @@ fn cmdAstCheck(
60766081
6077 const tree = try Ast.parse(arena, source, mode);6082 const tree = try Ast.parse(arena, source, mode);
60786083
6079 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6084 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6080 const stdout_bw = &stdout_writer.interface;6085 const stdout_bw = &stdout_writer.interface;
6081 switch (mode) {6086 switch (mode) {
6082 .zig => {6087 .zig => {
...@@ -6291,7 +6296,7 @@ fn detectNativeCpuWithLLVM(...@@ -6291,7 +6296,7 @@ fn detectNativeCpuWithLLVM(
6291}6296}
62926297
6293fn printCpu(cpu: std.Target.Cpu) !void {6298fn printCpu(cpu: std.Target.Cpu) !void {
6294 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6299 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6295 const stdout_bw = &stdout_writer.interface;6300 const stdout_bw = &stdout_writer.interface;
62966301
6297 if (cpu.model.llvm_name) |llvm_name| {6302 if (cpu.model.llvm_name) |llvm_name| {
...@@ -6340,7 +6345,7 @@ fn cmdDumpLlvmInts(...@@ -6340,7 +6345,7 @@ fn cmdDumpLlvmInts(
6340 const dl = tm.createTargetDataLayout();6345 const dl = tm.createTargetDataLayout();
6341 const context = llvm.Context.create();6346 const context = llvm.Context.create();
63426347
6343 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6348 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6344 const stdout_bw = &stdout_writer.interface;6349 const stdout_bw = &stdout_writer.interface;
6345 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {6350 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
6346 const int_type = context.intType(bits);6351 const int_type = context.intType(bits);
...@@ -6369,7 +6374,7 @@ fn cmdDumpZir(...@@ -6369,7 +6374,7 @@ fn cmdDumpZir(
6369 defer f.close();6374 defer f.close();
63706375
6371 const zir = try Zcu.loadZirCache(arena, f);6376 const zir = try Zcu.loadZirCache(arena, f);
6372 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6377 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6373 const stdout_bw = &stdout_writer.interface;6378 const stdout_bw = &stdout_writer.interface;
6374 {6379 {
6375 const instruction_bytes = zir.instructions.len *6380 const instruction_bytes = zir.instructions.len *
...@@ -6416,7 +6421,7 @@ fn cmdChangelist(...@@ -6416,7 +6421,7 @@ fn cmdChangelist(
6416 var f = fs.cwd().openFile(old_source_path, .{}) catch |err|6421 var f = fs.cwd().openFile(old_source_path, .{}) catch |err|
6417 fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) });6422 fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
6418 defer f.close();6423 defer f.close();
6419 var file_reader: fs.File.Reader = f.reader(&stdio_buffer);6424 var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
6420 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|6425 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|
6421 fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) });6426 fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
6422 };6427 };
...@@ -6424,7 +6429,7 @@ fn cmdChangelist(...@@ -6424,7 +6429,7 @@ fn cmdChangelist(
6424 var f = fs.cwd().openFile(new_source_path, .{}) catch |err|6429 var f = fs.cwd().openFile(new_source_path, .{}) catch |err|
6425 fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) });6430 fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
6426 defer f.close();6431 defer f.close();
6427 var file_reader: fs.File.Reader = f.reader(&stdio_buffer);6432 var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
6428 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|6433 break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|
6429 fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) });6434 fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
6430 };6435 };
...@@ -6456,7 +6461,7 @@ fn cmdChangelist(...@@ -6456,7 +6461,7 @@ fn cmdChangelist(
6456 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;6461 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
6457 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);6462 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
64586463
6459 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);6464 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
6460 const stdout_bw = &stdout_writer.interface;6465 const stdout_bw = &stdout_writer.interface;
6461 {6466 {
6462 try stdout_bw.print("Instruction mappings:\n", .{});6467 try stdout_bw.print("Instruction mappings:\n", .{});
...@@ -6916,7 +6921,7 @@ fn cmdFetch(...@@ -6916,7 +6921,7 @@ fn cmdFetch(
69166921
6917 const name = switch (save) {6922 const name = switch (save) {
6918 .no => {6923 .no => {
6919 var stdout = fs.File.stdout().writerStreaming(&stdio_buffer);6924 var stdout = fs.File.stdout().writerStreaming(&stdout_buffer);
6920 try stdout.interface.print("{s}\n", .{package_hash_slice});6925 try stdout.interface.print("{s}\n", .{package_hash_slice});
6921 try stdout.interface.flush();6926 try stdout.interface.flush();
6922 return cleanExit();6927 return cleanExit();
test/cases/compile_errors/@import_zon_bad_type.zig created+128
...@@ -0,0 +1,128 @@
1export fn testVoid() void {
2 const f: void = @import("zon/neg_inf.zon");
3 _ = f;
4}
5
6export fn testInStruct() void {
7 const f: struct { f: [*]const u8 } = @import("zon/neg_inf.zon");
8 _ = f;
9}
10
11export fn testError() void {
12 const f: struct { error{foo} } = @import("zon/neg_inf.zon");
13 _ = f;
14}
15
16export fn testInUnion() void {
17 const f: union(enum) { a: void, b: [*c]const u8 } = @import("zon/neg_inf.zon");
18 _ = f;
19}
20
21export fn testInVector() void {
22 const f: @Vector(0, [*c]const u8) = @import("zon/neg_inf.zon");
23 _ = f;
24}
25
26export fn testInOpt() void {
27 const f: *const ?[*c]const u8 = @import("zon/neg_inf.zon");
28 _ = f;
29}
30
31export fn testComptimeField() void {
32 const f: struct { comptime foo: ??u8 = null } = @import("zon/neg_inf.zon");
33 _ = f;
34}
35
36export fn testEnumLiteral() void {
37 const f: @TypeOf(.foo) = @import("zon/neg_inf.zon");
38 _ = f;
39}
40
41export fn testNestedOpt1() void {
42 const f: ??u8 = @import("zon/neg_inf.zon");
43 _ = f;
44}
45
46export fn testNestedOpt2() void {
47 const f: ?*const ?u8 = @import("zon/neg_inf.zon");
48 _ = f;
49}
50
51export fn testNestedOpt3() void {
52 const f: *const ?*const ?*const u8 = @import("zon/neg_inf.zon");
53 _ = f;
54}
55
56export fn testOpt() void {
57 const f: ?u8 = @import("zon/neg_inf.zon");
58 _ = f;
59}
60
61const E = enum(u8) { _ };
62export fn testNonExhaustiveEnum() void {
63 const f: E = @import("zon/neg_inf.zon");
64 _ = f;
65}
66
67const U = union { foo: void };
68export fn testUntaggedUnion() void {
69 const f: U = @import("zon/neg_inf.zon");
70 _ = f;
71}
72
73const EU = union(enum) { foo: void };
74export fn testTaggedUnionVoid() void {
75 const f: EU = @import("zon/neg_inf.zon");
76 _ = f;
77}
78
79export fn testVisited() void {
80 const V = struct {
81 ?f32, // Adds `?f32` to the visited list
82 ??f32, // `?f32` is already visited, we need to detect the nested opt anyway
83 f32,
84 };
85 const f: V = @import("zon/neg_inf.zon");
86 _ = f;
87}
88
89export fn testMutablePointer() void {
90 const f: *i32 = @import("zon/neg_inf.zon");
91 _ = f;
92}
93
94// error
95// imports=zon/neg_inf.zon
96//
97// tmp.zig:2:29: error: type 'void' is not available in ZON
98// tmp.zig:7:50: error: type '[*]const u8' is not available in ZON
99// tmp.zig:7:50: note: ZON does not allow many-pointers
100// tmp.zig:12:46: error: type 'error{foo}' is not available in ZON
101// tmp.zig:17:65: error: type '[*c]const u8' is not available in ZON
102// tmp.zig:17:65: note: ZON does not allow C pointers
103// tmp.zig:22:49: error: type '[*c]const u8' is not available in ZON
104// tmp.zig:22:49: note: ZON does not allow C pointers
105// tmp.zig:27:45: error: type '[*c]const u8' is not available in ZON
106// tmp.zig:27:45: note: ZON does not allow C pointers
107// tmp.zig:32:61: error: type '??u8' is not available in ZON
108// tmp.zig:32:61: note: ZON does not allow nested optionals
109// tmp.zig:42:29: error: type '??u8' is not available in ZON
110// tmp.zig:42:29: note: ZON does not allow nested optionals
111// tmp.zig:47:36: error: type '?*const ?u8' is not available in ZON
112// tmp.zig:47:36: note: ZON does not allow nested optionals
113// tmp.zig:52:50: error: type '?*const ?*const u8' is not available in ZON
114// tmp.zig:52:50: note: ZON does not allow nested optionals
115// tmp.zig:85:26: error: type '??f32' is not available in ZON
116// tmp.zig:85:26: note: ZON does not allow nested optionals
117// tmp.zig:90:29: error: type '*i32' is not available in ZON
118// tmp.zig:90:29: note: ZON does not allow mutable pointers
119// neg_inf.zon:1:1: error: expected type '@Type(.enum_literal)'
120// tmp.zig:37:38: note: imported here
121// neg_inf.zon:1:1: error: expected type '?u8'
122// tmp.zig:57:28: note: imported here
123// neg_inf.zon:1:1: error: expected type 'tmp.E'
124// tmp.zig:63:26: note: imported here
125// neg_inf.zon:1:1: error: expected type 'tmp.U'
126// tmp.zig:69:26: note: imported here
127// neg_inf.zon:1:1: error: expected type 'tmp.EU'
128// tmp.zig:75:27: note: imported here
test/cases/compile_errors/anytype_param_requires_comptime.zig created+21
...@@ -0,0 +1,21 @@
1const C = struct {
2 c: type,
3 b: u32,
4};
5const S = struct {
6 fn foo(b: u32, c: anytype) void {
7 bar(C{ .c = c, .b = b });
8 }
9 fn bar(_: anytype) void {}
10};
11
12pub export fn entry() void {
13 S.foo(0, u32);
14}
15
16// error
17//
18//:7:25: error: unable to resolve comptime value
19//:7:25: note: initializer of comptime-only struct 'tmp.C' must be comptime-known
20//:2:8: note: struct requires comptime because of this field
21//:2:8: note: types are not available at runtime
test/cases/compile_errors/bogus_method_call_on_slice.zig created+26
...@@ -0,0 +1,26 @@
1var self = "aoeu";
2
3fn f(m: []const u8) void {
4 m.copy(u8, self[0..], m);
5}
6
7export fn entry() usize {
8 return @sizeOf(@TypeOf(&f));
9}
10
11pub export fn entry1() void {
12 .{}.bar();
13}
14
15const S = struct { foo: i32 };
16pub export fn entry2() void {
17 const x = S{ .foo = 1 };
18 x.bar();
19}
20
21// error
22//
23// :4:6: error: no field or member function named 'copy' in '[]const u8'
24// :12:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
25// :18:6: error: no field or member function named 'bar' in 'tmp.S'
26// :15:11: note: struct declared here
test/cases/compile_errors/coerce_anon_struct.zig created+12
...@@ -0,0 +1,12 @@
1const A = struct { x: u32 };
2const T = struct { x: u32 };
3export fn foo() void {
4 const a = A{ .x = 123 };
5 _ = @as(T, a);
6}
7
8// error
9//
10// :5:16: error: expected type 'tmp.T', found 'tmp.A'
11// :1:11: note: struct declared here
12// :2:11: note: struct declared here
test/cases/compile_errors/redundant_try.zig created+52
...@@ -0,0 +1,52 @@
1const S = struct { x: u32 = 0 };
2const T = struct { []const u8 };
3
4fn test0() !void {
5 const x: u8 = try 1;
6 _ = x;
7}
8
9fn test1() !void {
10 const x: S = try .{};
11 _ = x;
12}
13
14fn test2() !void {
15 const x: S = try S{ .x = 123 };
16 _ = x;
17}
18
19fn test3() !void {
20 const x: S = try try S{ .x = 123 };
21 _ = x;
22}
23
24fn test4() !void {
25 const x: T = try .{"hello"};
26 _ = x;
27}
28
29fn test5() !void {
30 const x: error{Foo}!u32 = 123;
31 _ = try try x;
32}
33
34comptime {
35 _ = &test0;
36 _ = &test1;
37 _ = &test2;
38 _ = &test3;
39 _ = &test4;
40 _ = &test5;
41}
42
43// error
44//
45// :5:23: error: expected error union type, found 'comptime_int'
46// :10:23: error: expected error union type, found '@TypeOf(.{})'
47// :15:23: error: expected error union type, found 'tmp.S'
48// :1:11: note: struct declared here
49// :20:27: error: expected error union type, found 'tmp.S'
50// :1:11: note: struct declared here
51// :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }'
52// :31:13: error: expected error union type, found 'u32'
test/cases/type_names.zig+26-20
...@@ -46,14 +46,18 @@ const StructInStruct = struct { a: struct { b: u8 } };...@@ -46,14 +46,18 @@ const StructInStruct = struct { a: struct { b: u8 } };
46const UnionInStruct = struct { a: union { b: u8 } };46const UnionInStruct = struct { a: union { b: u8 } };
47const StructInUnion = union { a: struct { b: u8 } };47const StructInUnion = union { a: struct { b: u8 } };
48const UnionInUnion = union { a: union { b: u8 } };48const UnionInUnion = union { a: union { b: u8 } };
49const StructInTuple = struct { struct { b: u8 } };49const InnerStruct = struct { b: u8 };
50const UnionInTuple = struct { union { b: u8 } };50const StructInTuple = struct { a: InnerStruct };
51const InnerUnion = union { b: u8 };
52const UnionInTuple = struct { a: InnerUnion };
5153
52export fn nestedTypes() void {54export fn nestedTypes() void {
53 @compileLog(@typeName(StructInStruct));55 @compileLog(@typeName(StructInStruct));
54 @compileLog(@typeName(UnionInStruct));56 @compileLog(@typeName(UnionInStruct));
55 @compileLog(@typeName(StructInUnion));57 @compileLog(@typeName(StructInUnion));
56 @compileLog(@typeName(UnionInUnion));58 @compileLog(@typeName(UnionInUnion));
59 @compileLog(@typeName(StructInTuple));
60 @compileLog(@typeName(UnionInTuple));
57}61}
5862
59// error63// error
...@@ -61,22 +65,24 @@ export fn nestedTypes() void {...@@ -61,22 +65,24 @@ export fn nestedTypes() void {
61// :8:5: error: found compile log statement65// :8:5: error: found compile log statement
62// :19:5: note: also here66// :19:5: note: also here
63// :39:5: note: also here67// :39:5: note: also here
64// :53:5: note: also here68// :55:5: note: also here
65//69//
66// Compile Log Output:70//Compile Log Output:
67// @as(*const [15:0]u8, "tmp.namespace.S")71//@as(*const [15:0]u8, "tmp.namespace.S")
68// @as(*const [15:0]u8, "tmp.namespace.E")72//@as(*const [15:0]u8, "tmp.namespace.E")
69// @as(*const [15:0]u8, "tmp.namespace.U")73//@as(*const [15:0]u8, "tmp.namespace.U")
70// @as(*const [15:0]u8, "tmp.namespace.O")74//@as(*const [15:0]u8, "tmp.namespace.O")
71// @as(*const [19:0]u8, "tmp.localVarValue.S")75//@as(*const [19:0]u8, "tmp.localVarValue.S")
72// @as(*const [19:0]u8, "tmp.localVarValue.E")76//@as(*const [19:0]u8, "tmp.localVarValue.E")
73// @as(*const [19:0]u8, "tmp.localVarValue.U")77//@as(*const [19:0]u8, "tmp.localVarValue.U")
74// @as(*const [19:0]u8, "tmp.localVarValue.O")78//@as(*const [19:0]u8, "tmp.localVarValue.O")
75// @as(*const [11:0]u8, "tmp.MakeS()")79//@as(*const [11:0]u8, "tmp.MakeS()")
76// @as(*const [11:0]u8, "tmp.MakeE()")80//@as(*const [11:0]u8, "tmp.MakeE()")
77// @as(*const [11:0]u8, "tmp.MakeU()")81//@as(*const [11:0]u8, "tmp.MakeU()")
78// @as(*const [11:0]u8, "tmp.MakeO()")82//@as(*const [11:0]u8, "tmp.MakeO()")
79// @as(*const [18:0]u8, "tmp.StructInStruct")83//@as(*const [18:0]u8, "tmp.StructInStruct")
80// @as(*const [17:0]u8, "tmp.UnionInStruct")84//@as(*const [17:0]u8, "tmp.UnionInStruct")
81// @as(*const [17:0]u8, "tmp.StructInUnion")85//@as(*const [17:0]u8, "tmp.StructInUnion")
82// @as(*const [16:0]u8, "tmp.UnionInUnion")86//@as(*const [16:0]u8, "tmp.UnionInUnion")
87//@as(*const [17:0]u8, "tmp.StructInTuple")
88//@as(*const [16:0]u8, "tmp.UnionInTuple")
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,
tools/gen_spirv_spec.zig+1-1
...@@ -120,7 +120,7 @@ pub fn main() !void {...@@ -120,7 +120,7 @@ pub fn main() !void {
120 error_bundle.renderToStdErr(color.renderOptions());120 error_bundle.renderToStdErr(color.renderOptions());
121 }121 }
122122
123 const formatted_output = try tree.render(allocator);123 const formatted_output = try tree.renderAlloc(allocator);
124 _ = try std.fs.File.stdout().write(formatted_output);124 _ = try std.fs.File.stdout().write(formatted_output);
125}125}
126126