mirror of
https://github.com/ziglang/zig.git
synced 2026-01-24 16:25:25 +00:00
Merge remote-tracking branch 'origin/more' into wrangle-writer-buffering
This commit is contained in:
commit
5d2faeb8f3
@ -49,10 +49,13 @@ unset CXX
|
||||
ninja install
|
||||
|
||||
# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
|
||||
stage3-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 \
|
||||
--maxrss 34359738368 \
|
||||
stage3-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 \
|
||||
--maxrss 68719476736 \
|
||||
-Dstatic-llvm \
|
||||
-Dskip-non-native \
|
||||
-Dskip-single-threaded \
|
||||
-Dskip-translate-c \
|
||||
-Dskip-run-translated-c \
|
||||
-Dtarget=native-native-musl \
|
||||
--search-prefix "$PREFIX" \
|
||||
--zig-lib-dir "$PWD/../lib"
|
||||
|
||||
@ -49,10 +49,13 @@ unset CXX
|
||||
ninja install
|
||||
|
||||
# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
|
||||
stage3-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 \
|
||||
--maxrss 34359738368 \
|
||||
stage3-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 \
|
||||
--maxrss 68719476736 \
|
||||
-Dstatic-llvm \
|
||||
-Dskip-non-native \
|
||||
-Dskip-single-threaded \
|
||||
-Dskip-translate-c \
|
||||
-Dskip-run-translated-c \
|
||||
-Dtarget=native-native-musl \
|
||||
--search-prefix "$PREFIX" \
|
||||
--zig-lib-dir "$PWD/../lib"
|
||||
|
||||
@ -1824,7 +1824,7 @@ pub fn main() !void {
|
||||
};
|
||||
defer tree.deinit(gpa);
|
||||
|
||||
const formatted = try tree.render(arena);
|
||||
const formatted = try tree.renderAlloc(arena);
|
||||
try std.fs.File.stdout().writeAll(formatted);
|
||||
return std.process.cleanExit();
|
||||
}
|
||||
|
||||
@ -10,6 +10,9 @@ const assert = std.debug.assert;
|
||||
const fatal = std.process.fatal;
|
||||
const Server = std.zig.Server;
|
||||
|
||||
var stdin_buffer: [1024]u8 = undefined;
|
||||
var stdout_buffer: [1024]u8 = undefined;
|
||||
|
||||
pub fn main() !void {
|
||||
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena_instance.deinit();
|
||||
@ -22,11 +25,8 @@ pub fn main() !void {
|
||||
return cmdObjCopy(gpa, arena, args[1..]);
|
||||
}
|
||||
|
||||
fn cmdObjCopy(
|
||||
gpa: Allocator,
|
||||
arena: Allocator,
|
||||
args: []const []const u8,
|
||||
) !void {
|
||||
fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
_ = gpa;
|
||||
var i: usize = 0;
|
||||
var opt_out_fmt: ?std.Target.ObjectFormat = null;
|
||||
var opt_input: ?[]const u8 = null;
|
||||
@ -225,13 +225,13 @@ fn cmdObjCopy(
|
||||
}
|
||||
|
||||
if (listen) {
|
||||
var stdin_reader = fs.File.stdin().reader(&stdin_buffer);
|
||||
var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
|
||||
var server = try Server.init(.{
|
||||
.gpa = gpa,
|
||||
.in = .stdin(),
|
||||
.out = .stdout(),
|
||||
.in = &stdin_reader.interface,
|
||||
.out = &stdout_writer.interface,
|
||||
.zig_version = builtin.zig_version_string,
|
||||
});
|
||||
defer server.deinit();
|
||||
|
||||
var seen_update = false;
|
||||
while (true) {
|
||||
|
||||
@ -13,6 +13,8 @@ const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePag
|
||||
const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
|
||||
const aro = @import("aro");
|
||||
|
||||
var stdout_buffer: [1024]u8 = undefined;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||
defer std.debug.assert(gpa.deinit() == .ok);
|
||||
@ -41,12 +43,12 @@ pub fn main() !void {
|
||||
cli_args = args[3..];
|
||||
}
|
||||
|
||||
var stdout_writer2 = std.fs.File.stdout().writer(&stdout_buffer);
|
||||
var error_handler: ErrorHandler = switch (zig_integration) {
|
||||
true => .{
|
||||
.server = .{
|
||||
.out = std.fs.File.stdout(),
|
||||
.out = &stdout_writer2.interface,
|
||||
.in = undefined, // won't be receiving messages
|
||||
.receive_fifo = undefined, // won't be receiving messages
|
||||
},
|
||||
},
|
||||
false => .{
|
||||
|
||||
@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
@ -211,32 +212,100 @@ pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {
|
||||
}
|
||||
}
|
||||
|
||||
test "exp32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(expf(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f32, expf(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expf(0.2), 1.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expf(0.8923), 2.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expf(1.5), 4.481689, epsilon));
|
||||
}
|
||||
|
||||
test "exp64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f64, exp(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp(0.2), 1.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp(0.8923), 2.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp(1.5), 4.481689, epsilon));
|
||||
}
|
||||
|
||||
test "exp32.special" {
|
||||
try expect(math.isPositiveInf(expf(math.inf(f32))));
|
||||
test "expf() special" {
|
||||
try expectEqual(expf(0.0), 1.0);
|
||||
try expectEqual(expf(-0.0), 1.0);
|
||||
try expectEqual(expf(1.0), math.e);
|
||||
try expectEqual(expf(math.ln2), 2.0);
|
||||
try expectEqual(expf(math.inf(f32)), math.inf(f32));
|
||||
try expect(math.isPositiveZero(expf(-math.inf(f32))));
|
||||
try expect(math.isNan(expf(math.nan(f32))));
|
||||
try expect(math.isNan(expf(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "exp64.special" {
|
||||
try expect(math.isPositiveInf(exp(math.inf(f64))));
|
||||
try expect(math.isNan(exp(math.nan(f64))));
|
||||
test "expf() sanity" {
|
||||
try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12);
|
||||
try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6);
|
||||
try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
|
||||
try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10);
|
||||
try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13);
|
||||
try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0);
|
||||
try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
|
||||
try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0);
|
||||
try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1);
|
||||
try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1);
|
||||
try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8);
|
||||
try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20);
|
||||
try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25);
|
||||
try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20);
|
||||
try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8);
|
||||
try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2);
|
||||
try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16);
|
||||
try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24);
|
||||
try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
|
||||
try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28);
|
||||
}
|
||||
|
||||
test "expf() boundary" {
|
||||
try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite
|
||||
try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
|
||||
try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value
|
||||
try expectEqual(expf(0x1p-149), 1.0); // Min positive input value
|
||||
try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value
|
||||
try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input
|
||||
try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input
|
||||
try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero
|
||||
try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero
|
||||
try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal
|
||||
try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
|
||||
|
||||
}
|
||||
|
||||
test "exp() special" {
|
||||
try expectEqual(exp(0.0), 1.0);
|
||||
try expectEqual(exp(-0.0), 1.0);
|
||||
// TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC
|
||||
// try expectEqual(exp(1.0), math.e);
|
||||
try expectEqual(exp(math.ln2), 2.0);
|
||||
try expectEqual(exp(math.inf(f64)), math.inf(f64));
|
||||
try expect(math.isPositiveZero(exp(-math.inf(f64))));
|
||||
try expect(math.isNan(exp(math.nan(f64))));
|
||||
try expect(math.isNan(exp(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "exp() sanity" {
|
||||
try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
|
||||
try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
|
||||
try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
|
||||
try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
|
||||
try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
|
||||
try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
|
||||
try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
|
||||
try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
|
||||
try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
|
||||
try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
|
||||
try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
|
||||
try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
|
||||
try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
|
||||
try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
|
||||
try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
|
||||
try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
|
||||
try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
|
||||
try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
|
||||
try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
|
||||
try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
|
||||
}
|
||||
|
||||
test "exp() boundary" {
|
||||
try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite
|
||||
try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
|
||||
try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
|
||||
try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value
|
||||
try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value
|
||||
try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input
|
||||
try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input
|
||||
try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero
|
||||
try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero
|
||||
try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal
|
||||
try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ const arch = builtin.cpu.arch;
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
@ -58,7 +59,7 @@ pub fn exp2f(x: f32) callconv(.c) f32 {
|
||||
if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x1.0p-149 / x);
|
||||
}
|
||||
// x <= -150
|
||||
if (u >= 0x3160000) {
|
||||
if (u >= 0xC3160000) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -457,34 +458,78 @@ const exp2dt = [_]f64{
|
||||
0x1.690f4b19e9471p+0, -0x1.9780p-45,
|
||||
};
|
||||
|
||||
test "exp2_32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp2f(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f32, exp2f(0.2), 1.148698, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(0.8923), 1.856133, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(1.5), 2.828427, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(37.45), 187747237888, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(-1), 0.5, epsilon));
|
||||
}
|
||||
|
||||
test "exp2_64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp2(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f64, exp2(0.2), 1.148698, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(0.8923), 1.856133, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(1.5), 2.828427, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(-1), 0.5, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1, epsilon));
|
||||
}
|
||||
|
||||
test "exp2_32.special" {
|
||||
try expect(math.isPositiveInf(exp2f(math.inf(f32))));
|
||||
test "exp2f() special" {
|
||||
try expectEqual(exp2f(0.0), 1.0);
|
||||
try expectEqual(exp2f(-0.0), 1.0);
|
||||
try expectEqual(exp2f(1.0), 2.0);
|
||||
try expectEqual(exp2f(-1.0), 0.5);
|
||||
try expectEqual(exp2f(math.inf(f32)), math.inf(f32));
|
||||
try expect(math.isPositiveZero(exp2f(-math.inf(f32))));
|
||||
try expect(math.isNan(exp2f(math.nan(f32))));
|
||||
try expect(math.isNan(exp2f(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "exp2_64.special" {
|
||||
try expect(math.isPositiveInf(exp2(math.inf(f64))));
|
||||
try expect(math.isNan(exp2(math.nan(f64))));
|
||||
test "exp2f() sanity" {
|
||||
try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9);
|
||||
try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4);
|
||||
try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9);
|
||||
try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7);
|
||||
try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9);
|
||||
try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0);
|
||||
try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1);
|
||||
try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0);
|
||||
try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0);
|
||||
try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1);
|
||||
}
|
||||
|
||||
test "exp2f() boundary" {
|
||||
try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
|
||||
try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result
|
||||
try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
|
||||
try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
|
||||
try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
|
||||
try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
|
||||
try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value
|
||||
try expectEqual(exp2f(0x1p-149), 1); // Min positive input value
|
||||
try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value
|
||||
try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input
|
||||
try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input
|
||||
}
|
||||
|
||||
test "exp2() special" {
|
||||
try expectEqual(exp2(0.0), 1.0);
|
||||
try expectEqual(exp2(-0.0), 1.0);
|
||||
try expectEqual(exp2(1.0), 2.0);
|
||||
try expectEqual(exp2(-1.0), 0.5);
|
||||
try expectEqual(exp2(math.inf(f64)), math.inf(f64));
|
||||
try expect(math.isPositiveZero(exp2(-math.inf(f64))));
|
||||
try expect(math.isNan(exp2(math.nan(f64))));
|
||||
try expect(math.isNan(exp2(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "exp2() sanity" {
|
||||
try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
|
||||
try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
|
||||
try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
|
||||
try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
|
||||
try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
|
||||
try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
|
||||
try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
|
||||
try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
|
||||
try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
|
||||
try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
|
||||
}
|
||||
|
||||
test "exp2() boundary" {
|
||||
try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
|
||||
try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result
|
||||
try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
|
||||
try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
|
||||
try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
|
||||
try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
|
||||
try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
|
||||
try expectEqual(exp2(0x1p-1074), 1); // Min positive input value
|
||||
try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value
|
||||
try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input
|
||||
try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input
|
||||
}
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const arch = builtin.cpu.arch;
|
||||
const common = @import("common.zig");
|
||||
|
||||
@ -110,8 +111,8 @@ pub fn log(x_: f64) callconv(.c) f64 {
|
||||
|
||||
// subnormal, scale x
|
||||
k -= 54;
|
||||
x *= 0x1.0p54;
|
||||
hx = @intCast(@as(u64, @bitCast(ix)) >> 32);
|
||||
x *= 0x1p54;
|
||||
hx = @intCast(@as(u64, @bitCast(x)) >> 32);
|
||||
} else if (hx >= 0x7FF00000) {
|
||||
return x;
|
||||
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||
@ -159,38 +160,72 @@ pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {
|
||||
}
|
||||
}
|
||||
|
||||
test "ln32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try testing.expect(math.approxEqAbs(f32, logf(0.2), -1.609438, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, logf(0.8923), -0.113953, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, logf(1.5), 0.405465, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, logf(37.45), 3.623007, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, logf(89.123), 4.490017, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, logf(123123.234375), 11.720941, epsilon));
|
||||
test "logf() special" {
|
||||
try expectEqual(logf(0.0), -math.inf(f32));
|
||||
try expectEqual(logf(-0.0), -math.inf(f32));
|
||||
try expect(math.isPositiveZero(logf(1.0)));
|
||||
try expectEqual(logf(math.e), 1.0);
|
||||
try expectEqual(logf(math.inf(f32)), math.inf(f32));
|
||||
try expect(math.isNan(logf(-1.0)));
|
||||
try expect(math.isNan(logf(-math.inf(f32))));
|
||||
try expect(math.isNan(logf(math.nan(f32))));
|
||||
try expect(math.isNan(logf(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "ln64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try testing.expect(math.approxEqAbs(f64, log(0.2), -1.609438, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log(0.8923), -0.113953, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log(1.5), 0.405465, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log(37.45), 3.623007, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log(89.123), 4.490017, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log(123123.234375), 11.720941, epsilon));
|
||||
test "logf() sanity" {
|
||||
try expect(math.isNan(logf(-0x1.0223a0p+3)));
|
||||
try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0);
|
||||
try expect(math.isNan(logf(-0x1.0c34b4p+3)));
|
||||
try expect(math.isNan(logf(-0x1.a206f0p+2)));
|
||||
try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1);
|
||||
try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2);
|
||||
try expect(math.isNan(logf(-0x1.a05cc8p-2)));
|
||||
try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1);
|
||||
try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2);
|
||||
try expect(math.isNan(logf(-0x1.5b86eap-1)));
|
||||
}
|
||||
|
||||
test "ln32.special" {
|
||||
try testing.expect(math.isPositiveInf(logf(math.inf(f32))));
|
||||
try testing.expect(math.isNegativeInf(logf(0.0)));
|
||||
try testing.expect(math.isNan(logf(-1.0)));
|
||||
try testing.expect(math.isNan(logf(math.nan(f32))));
|
||||
test "logf() boundary" {
|
||||
try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
|
||||
try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
|
||||
try expect(math.isNan(logf(-0x1p-149))); // Min negative input value
|
||||
try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0
|
||||
try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
|
||||
try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal
|
||||
try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal
|
||||
}
|
||||
|
||||
test "ln64.special" {
|
||||
try testing.expect(math.isPositiveInf(log(math.inf(f64))));
|
||||
try testing.expect(math.isNegativeInf(log(0.0)));
|
||||
try testing.expect(math.isNan(log(-1.0)));
|
||||
try testing.expect(math.isNan(log(math.nan(f64))));
|
||||
test "log() special" {
|
||||
try expectEqual(log(0.0), -math.inf(f64));
|
||||
try expectEqual(log(-0.0), -math.inf(f64));
|
||||
try expect(math.isPositiveZero(log(1.0)));
|
||||
try expectEqual(log(math.e), 1.0);
|
||||
try expectEqual(log(math.inf(f64)), math.inf(f64));
|
||||
try expect(math.isNan(log(-1.0)));
|
||||
try expect(math.isNan(log(-math.inf(f64))));
|
||||
try expect(math.isNan(log(math.nan(f64))));
|
||||
try expect(math.isNan(log(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "log() sanity" {
|
||||
try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3)));
|
||||
try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
|
||||
try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3)));
|
||||
try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2)));
|
||||
try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
|
||||
try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
|
||||
try expect(math.isNan(log(-0x1.a05cc754481d1p-2)));
|
||||
try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
|
||||
try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
|
||||
try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1)));
|
||||
}
|
||||
|
||||
test "log() boundary" {
|
||||
try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
|
||||
try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
|
||||
try expect(math.isNan(log(-0x1p-1074))); // Min negative input value
|
||||
try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0
|
||||
try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
|
||||
try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
|
||||
try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal
|
||||
}
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const maxInt = std.math.maxInt;
|
||||
const arch = builtin.cpu.arch;
|
||||
const common = @import("common.zig");
|
||||
@ -187,38 +188,74 @@ pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {
|
||||
}
|
||||
}
|
||||
|
||||
test "log10_32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try testing.expect(math.approxEqAbs(f32, log10f(0.2), -0.698970, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, log10f(0.8923), -0.049489, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, log10f(1.5), 0.176091, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, log10f(37.45), 1.573452, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, log10f(89.123), 1.94999, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f32, log10f(123123.234375), 5.09034, epsilon));
|
||||
test "log10f() special" {
|
||||
try expectEqual(log10f(0.0), -math.inf(f32));
|
||||
try expectEqual(log10f(-0.0), -math.inf(f32));
|
||||
try expect(math.isPositiveZero(log10f(1.0)));
|
||||
try expectEqual(log10f(10.0), 1.0);
|
||||
try expectEqual(log10f(0.1), -1.0);
|
||||
try expectEqual(log10f(math.inf(f32)), math.inf(f32));
|
||||
try expect(math.isNan(log10f(-1.0)));
|
||||
try expect(math.isNan(log10f(-math.inf(f32))));
|
||||
try expect(math.isNan(log10f(math.nan(f32))));
|
||||
try expect(math.isNan(log10f(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "log10_64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try testing.expect(math.approxEqAbs(f64, log10(0.2), -0.698970, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log10(0.8923), -0.049489, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log10(1.5), 0.176091, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log10(37.45), 1.573452, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log10(89.123), 1.94999, epsilon));
|
||||
try testing.expect(math.approxEqAbs(f64, log10(123123.234375), 5.09034, epsilon));
|
||||
test "log10f() sanity" {
|
||||
try expect(math.isNan(log10f(-0x1.0223a0p+3)));
|
||||
try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1);
|
||||
try expect(math.isNan(log10f(-0x1.0c34b4p+3)));
|
||||
try expect(math.isNan(log10f(-0x1.a206f0p+2)));
|
||||
try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1);
|
||||
try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
|
||||
try expect(math.isNan(log10f(-0x1.a05cc8p-2)));
|
||||
try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2);
|
||||
try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4);
|
||||
try expect(math.isNan(log10f(-0x1.5b86eap-1)));
|
||||
}
|
||||
|
||||
test "log10_32.special" {
|
||||
try testing.expect(math.isPositiveInf(log10f(math.inf(f32))));
|
||||
try testing.expect(math.isNegativeInf(log10f(0.0)));
|
||||
try testing.expect(math.isNan(log10f(-1.0)));
|
||||
try testing.expect(math.isNan(log10f(math.nan(f32))));
|
||||
test "log10f() boundary" {
|
||||
try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value
|
||||
try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
|
||||
try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value
|
||||
try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0
|
||||
try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
|
||||
try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal
|
||||
try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal
|
||||
}
|
||||
|
||||
test "log10_64.special" {
|
||||
try testing.expect(math.isPositiveInf(log10(math.inf(f64))));
|
||||
try testing.expect(math.isNegativeInf(log10(0.0)));
|
||||
try testing.expect(math.isNan(log10(-1.0)));
|
||||
try testing.expect(math.isNan(log10(math.nan(f64))));
|
||||
test "log10() special" {
|
||||
try expectEqual(log10(0.0), -math.inf(f64));
|
||||
try expectEqual(log10(-0.0), -math.inf(f64));
|
||||
try expect(math.isPositiveZero(log10(1.0)));
|
||||
try expectEqual(log10(10.0), 1.0);
|
||||
try expectEqual(log10(0.1), -1.0);
|
||||
try expectEqual(log10(math.inf(f64)), math.inf(f64));
|
||||
try expect(math.isNan(log10(-1.0)));
|
||||
try expect(math.isNan(log10(-math.inf(f64))));
|
||||
try expect(math.isNan(log10(math.nan(f64))));
|
||||
try expect(math.isNan(log10(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "log10() sanity" {
|
||||
try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3)));
|
||||
try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
|
||||
try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3)));
|
||||
try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2)));
|
||||
try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
|
||||
try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
|
||||
try expect(math.isNan(log10(-0x1.a05cc754481d1p-2)));
|
||||
try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
|
||||
try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
|
||||
try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1)));
|
||||
}
|
||||
|
||||
test "log10() boundary" {
|
||||
try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
|
||||
try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
|
||||
try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value
|
||||
try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0
|
||||
try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
|
||||
try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
|
||||
try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const maxInt = std.math.maxInt;
|
||||
const arch = builtin.cpu.arch;
|
||||
const common = @import("common.zig");
|
||||
@ -179,36 +180,73 @@ pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {
|
||||
}
|
||||
}
|
||||
|
||||
test "log2_32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(math.approxEqAbs(f32, log2f(0.2), -2.321928, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log2f(0.8923), -0.164399, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log2f(1.5), 0.584962, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log2f(37.45), 5.226894, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log2f(123123.234375), 16.909744, epsilon));
|
||||
}
|
||||
|
||||
test "log2_64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(math.approxEqAbs(f64, log2(0.2), -2.321928, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log2(0.8923), -0.164399, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log2(1.5), 0.584962, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log2(37.45), 5.226894, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log2(123123.234375), 16.909744, epsilon));
|
||||
}
|
||||
|
||||
test "log2_32.special" {
|
||||
try expect(math.isPositiveInf(log2f(math.inf(f32))));
|
||||
try expect(math.isNegativeInf(log2f(0.0)));
|
||||
test "log2f() special" {
|
||||
try expectEqual(log2f(0.0), -math.inf(f32));
|
||||
try expectEqual(log2f(-0.0), -math.inf(f32));
|
||||
try expect(math.isPositiveZero(log2f(1.0)));
|
||||
try expectEqual(log2f(2.0), 1.0);
|
||||
try expectEqual(log2f(math.inf(f32)), math.inf(f32));
|
||||
try expect(math.isNan(log2f(-1.0)));
|
||||
try expect(math.isNan(log2f(-math.inf(f32))));
|
||||
try expect(math.isNan(log2f(math.nan(f32))));
|
||||
try expect(math.isNan(log2f(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "log2_64.special" {
|
||||
try expect(math.isPositiveInf(log2(math.inf(f64))));
|
||||
try expect(math.isNegativeInf(log2(0.0)));
|
||||
try expect(math.isNan(log2(-1.0)));
|
||||
try expect(math.isNan(log2(math.nan(f64))));
|
||||
test "log2f() sanity" {
|
||||
try expect(math.isNan(log2f(-0x1.0223a0p+3)));
|
||||
try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1);
|
||||
try expect(math.isNan(log2f(-0x1.0c34b4p+3)));
|
||||
try expect(math.isNan(log2f(-0x1.a206f0p+2)));
|
||||
try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1);
|
||||
try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
|
||||
try expect(math.isNan(log2f(-0x1.a05cc8p-2)));
|
||||
try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1);
|
||||
try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2);
|
||||
try expect(math.isNan(log2f(-0x1.5b86eap-1)));
|
||||
}
|
||||
|
||||
test "log2f() boundary" {
|
||||
try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value
|
||||
try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value
|
||||
try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value
|
||||
try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0
|
||||
try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
|
||||
try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal
|
||||
try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal
|
||||
|
||||
}
|
||||
|
||||
test "log2() special" {
|
||||
try expectEqual(log2(0.0), -math.inf(f64));
|
||||
try expectEqual(log2(-0.0), -math.inf(f64));
|
||||
try expect(math.isPositiveZero(log2(1.0)));
|
||||
try expectEqual(log2(2.0), 1.0);
|
||||
try expectEqual(log2(math.inf(f64)), math.inf(f64));
|
||||
try expect(math.isNan(log2(-1.0)));
|
||||
try expect(math.isNan(log2(-math.inf(f64))));
|
||||
try expect(math.isNan(log2(math.nan(f64))));
|
||||
try expect(math.isNan(log2(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "log2() sanity" {
|
||||
try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3)));
|
||||
try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
|
||||
try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3)));
|
||||
try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2)));
|
||||
try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
|
||||
try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
|
||||
try expect(math.isNan(log2(-0x1.a05cc754481d1p-2)));
|
||||
try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
|
||||
try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
|
||||
try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1)));
|
||||
}
|
||||
|
||||
test "log2() boundary" {
|
||||
try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
|
||||
try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value
|
||||
try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value
|
||||
try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0
|
||||
try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
|
||||
try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal
|
||||
try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal
|
||||
}
|
||||
|
||||
@ -13,11 +13,11 @@ comptime {
|
||||
// Default stack-probe functions emitted by LLVM
|
||||
if (builtin.target.isMinGW()) {
|
||||
@export(&_chkstk, .{ .name = "_alloca", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__chkstk, .{ .name = "__chkstk", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&___chkstk, .{ .name = "__alloca", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&___chkstk, .{ .name = "___chkstk", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__chkstk_ms, .{ .name = "__chkstk_ms", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = common.linkage, .visibility = common.visibility });
|
||||
|
||||
if (arch == .thumb or arch == .aarch64) {
|
||||
@export(&__chkstk, .{ .name = "__chkstk", .linkage = common.linkage, .visibility = common.visibility });
|
||||
}
|
||||
} else if (!builtin.link_libc) {
|
||||
// This symbols are otherwise exported by MSVCRT.lib
|
||||
@export(&_chkstk, .{ .name = "_chkstk", .linkage = common.linkage, .visibility = common.visibility });
|
||||
|
||||
@ -433,20 +433,18 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {
|
||||
defer ast.deinit(gpa);
|
||||
|
||||
const token_offsets = ast.tokens.items(.start);
|
||||
var rendered_err: std.ArrayListUnmanaged(u8) = .{};
|
||||
defer rendered_err.deinit(gpa);
|
||||
var rendered_err: std.Io.Writer.Allocating = .init(gpa);
|
||||
defer rendered_err.deinit();
|
||||
for (ast.errors) |err| {
|
||||
const err_offset = token_offsets[err.token] + ast.errorOffset(err);
|
||||
const err_loc = std.zig.findLineColumn(ast.source, err_offset);
|
||||
rendered_err.clearRetainingCapacity();
|
||||
{
|
||||
var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &rendered_err);
|
||||
defer rendered_err = aw.toArrayList();
|
||||
ast.renderError(err, &aw.interface) catch |e| switch (e) {
|
||||
error.WriteFailed => return error.OutOfMemory,
|
||||
};
|
||||
}
|
||||
log.err("{s}:{d}:{d}: {s}", .{ file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.items });
|
||||
ast.renderError(err, &rendered_err.writer) catch |e| switch (e) {
|
||||
error.WriteFailed => return error.OutOfMemory,
|
||||
};
|
||||
log.err("{s}:{d}:{d}: {s}", .{
|
||||
file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.getWritten(),
|
||||
});
|
||||
}
|
||||
return Ast.parse(gpa, "", .zig);
|
||||
}
|
||||
|
||||
@ -101,6 +101,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
|
||||
.generated_dir = .{ .step = &config_header.step },
|
||||
};
|
||||
|
||||
if (options.style.getPath()) |s| {
|
||||
s.addStepDependencies(&config_header.step);
|
||||
}
|
||||
return config_header;
|
||||
}
|
||||
|
||||
|
||||
@ -372,6 +372,34 @@ pub fn discard(self: Self) anyerror!u64 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper for bridging to the new `Reader` API while upgrading.
|
||||
pub fn adaptToNewApi(self: *const Self) Adapter {
|
||||
return .{
|
||||
.derp_reader = self.*,
|
||||
.new_interface = .{
|
||||
.buffer = &.{},
|
||||
.vtable = &.{ .stream = Adapter.stream },
|
||||
.seek = 0,
|
||||
.end = 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub const Adapter = struct {
|
||||
derp_reader: Self,
|
||||
new_interface: std.io.Reader,
|
||||
err: ?Error = null,
|
||||
|
||||
fn stream(r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
|
||||
const a: *@This() = @alignCast(@fieldParentPtr("new_interface", r));
|
||||
const buf = limit.slice(try w.writableSliceGreedy(1));
|
||||
return a.derp_reader.read(buf) catch |err| {
|
||||
a.err = err;
|
||||
return error.ReadFailed;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const std = @import("../std.zig");
|
||||
const Self = @This();
|
||||
const math = std.math;
|
||||
|
||||
@ -246,33 +246,40 @@ pub fn appendRemaining(
|
||||
limit: Limit,
|
||||
) LimitedAllocError!void {
|
||||
assert(r.buffer.len != 0); // Needed to detect limit exceeded without losing data.
|
||||
const buffer = r.buffer;
|
||||
const buffer_contents = buffer[r.seek..r.end];
|
||||
const buffer_contents = r.buffer[r.seek..r.end];
|
||||
const copy_len = limit.minInt(buffer_contents.len);
|
||||
try list.ensureUnusedCapacity(gpa, copy_len);
|
||||
@memcpy(list.unusedCapacitySlice()[0..copy_len], buffer[0..copy_len]);
|
||||
list.items.len += copy_len;
|
||||
try list.appendSlice(gpa, r.buffer[0..copy_len]);
|
||||
r.seek += copy_len;
|
||||
if (copy_len == buffer_contents.len) {
|
||||
r.seek = 0;
|
||||
r.end = 0;
|
||||
}
|
||||
var remaining = limit.subtract(copy_len).?;
|
||||
if (buffer_contents.len - copy_len != 0) return error.StreamTooLong;
|
||||
r.seek = 0;
|
||||
r.end = 0;
|
||||
var remaining = @intFromEnum(limit) - copy_len;
|
||||
while (true) {
|
||||
try list.ensureUnusedCapacity(gpa, 1);
|
||||
const dest = remaining.slice(list.unusedCapacitySlice());
|
||||
const additional_buffer: []u8 = if (@intFromEnum(remaining) == dest.len) buffer else &.{};
|
||||
const n = readVec(r, &.{ dest, additional_buffer }) catch |err| switch (err) {
|
||||
error.EndOfStream => break,
|
||||
error.ReadFailed => return error.ReadFailed,
|
||||
};
|
||||
if (n > dest.len) {
|
||||
r.end = n - dest.len;
|
||||
list.items.len += dest.len;
|
||||
return error.StreamTooLong;
|
||||
const cap = list.unusedCapacitySlice();
|
||||
const dest = cap[0..@min(cap.len, remaining)];
|
||||
if (remaining - dest.len == 0) {
|
||||
// Additionally provides `buffer` to detect end.
|
||||
const new_remaining = readVecInner(r, &.{}, dest, remaining) catch |err| switch (err) {
|
||||
error.EndOfStream => {
|
||||
if (r.bufferedLen() != 0) return error.StreamTooLong;
|
||||
return;
|
||||
},
|
||||
error.ReadFailed => return error.ReadFailed,
|
||||
};
|
||||
list.items.len += remaining - new_remaining;
|
||||
remaining = new_remaining;
|
||||
} else {
|
||||
// Leave `buffer` empty, appending directly to `list`.
|
||||
var dest_w: Writer = .fixed(dest);
|
||||
const n = r.vtable.stream(r, &dest_w, .limited(dest.len)) catch |err| switch (err) {
|
||||
error.WriteFailed => unreachable, // Prevented by the limit.
|
||||
error.EndOfStream => return,
|
||||
error.ReadFailed => return error.ReadFailed,
|
||||
};
|
||||
list.items.len += n;
|
||||
remaining -= n;
|
||||
}
|
||||
list.items.len += n;
|
||||
remaining = remaining.subtract(n).?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,62 +320,68 @@ pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {
|
||||
// buffer capacity requirements met.
|
||||
r.seek = 0;
|
||||
r.end = 0;
|
||||
const first = buf[copy_len..];
|
||||
const middle = data[i + 1 ..];
|
||||
var wrapper: Writer.VectorWrapper = .{
|
||||
.it = .{
|
||||
.first = first,
|
||||
.middle = middle,
|
||||
.last = r.buffer,
|
||||
},
|
||||
.writer = .{
|
||||
.buffer = if (first.len >= r.buffer.len) first else r.buffer,
|
||||
.vtable = Writer.VectorWrapper.vtable,
|
||||
},
|
||||
};
|
||||
var n = r.vtable.stream(r, &wrapper.writer, .limited(remaining)) catch |err| switch (err) {
|
||||
error.WriteFailed => {
|
||||
assert(!wrapper.used);
|
||||
if (wrapper.writer.buffer.ptr == first.ptr) {
|
||||
remaining -= wrapper.writer.end;
|
||||
} else {
|
||||
assert(wrapper.writer.end <= r.buffer.len);
|
||||
r.end = wrapper.writer.end;
|
||||
}
|
||||
break;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
if (!wrapper.used) {
|
||||
if (wrapper.writer.buffer.ptr == first.ptr) {
|
||||
remaining -= n;
|
||||
} else {
|
||||
assert(n <= r.buffer.len);
|
||||
r.end = n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (n < first.len) {
|
||||
remaining -= n;
|
||||
break;
|
||||
}
|
||||
remaining -= first.len;
|
||||
n -= first.len;
|
||||
for (middle) |mid| {
|
||||
if (n < mid.len) {
|
||||
remaining -= n;
|
||||
break;
|
||||
}
|
||||
remaining -= mid.len;
|
||||
n -= mid.len;
|
||||
}
|
||||
assert(n <= r.buffer.len);
|
||||
r.end = n;
|
||||
remaining = try readVecInner(r, data[i + 1 ..], buf[copy_len..], remaining);
|
||||
break;
|
||||
}
|
||||
return @intFromEnum(limit) - remaining;
|
||||
}
|
||||
|
||||
fn readVecInner(r: *Reader, middle: []const []u8, first: []u8, remaining: usize) Error!usize {
|
||||
var wrapper: Writer.VectorWrapper = .{
|
||||
.it = .{
|
||||
.first = first,
|
||||
.middle = middle,
|
||||
.last = r.buffer,
|
||||
},
|
||||
.writer = .{
|
||||
.buffer = if (first.len >= r.buffer.len) first else r.buffer,
|
||||
.vtable = Writer.VectorWrapper.vtable,
|
||||
},
|
||||
};
|
||||
// If the limit may pass beyond user buffer into Reader buffer, use
|
||||
// unlimited, allowing the Reader buffer to fill.
|
||||
const limit: Limit = l: {
|
||||
var n: usize = first.len;
|
||||
for (middle) |m| n += m.len;
|
||||
break :l if (remaining >= n) .unlimited else .limited(remaining);
|
||||
};
|
||||
var n = r.vtable.stream(r, &wrapper.writer, limit) catch |err| switch (err) {
|
||||
error.WriteFailed => {
|
||||
assert(!wrapper.used);
|
||||
if (wrapper.writer.buffer.ptr == first.ptr) {
|
||||
return remaining - wrapper.writer.end;
|
||||
} else {
|
||||
assert(wrapper.writer.end <= r.buffer.len);
|
||||
r.end = wrapper.writer.end;
|
||||
return remaining;
|
||||
}
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
if (!wrapper.used) {
|
||||
if (wrapper.writer.buffer.ptr == first.ptr) {
|
||||
return remaining - n;
|
||||
} else {
|
||||
assert(n <= r.buffer.len);
|
||||
r.end = n;
|
||||
return remaining;
|
||||
}
|
||||
}
|
||||
if (n < first.len) return remaining - n;
|
||||
var result = remaining - first.len;
|
||||
n -= first.len;
|
||||
for (middle) |mid| {
|
||||
if (n < mid.len) {
|
||||
return result - n;
|
||||
}
|
||||
result -= mid.len;
|
||||
n -= mid.len;
|
||||
}
|
||||
assert(n <= r.buffer.len);
|
||||
r.end = n;
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn buffered(r: *Reader) []u8 {
|
||||
return r.buffer[r.seek..r.end];
|
||||
}
|
||||
@ -580,48 +593,29 @@ pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void {
|
||||
/// See also:
|
||||
/// * `readSliceAll`
|
||||
pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize {
|
||||
const in_buffer = r.buffer[r.seek..r.end];
|
||||
const copy_len = @min(buffer.len, in_buffer.len);
|
||||
@memcpy(buffer[0..copy_len], in_buffer[0..copy_len]);
|
||||
if (buffer.len - copy_len == 0) {
|
||||
r.seek += copy_len;
|
||||
return buffer.len;
|
||||
}
|
||||
var i: usize = copy_len;
|
||||
r.end = 0;
|
||||
r.seek = 0;
|
||||
var i: usize = 0;
|
||||
while (true) {
|
||||
const buffer_contents = r.buffer[r.seek..r.end];
|
||||
const dest = buffer[i..];
|
||||
const copy_len = @min(dest.len, buffer_contents.len);
|
||||
@memcpy(dest[0..copy_len], buffer_contents[0..copy_len]);
|
||||
if (dest.len - copy_len == 0) {
|
||||
@branchHint(.likely);
|
||||
r.seek += copy_len;
|
||||
return buffer.len;
|
||||
}
|
||||
i += copy_len;
|
||||
r.end = 0;
|
||||
r.seek = 0;
|
||||
const remaining = buffer[i..];
|
||||
var wrapper: Writer.VectorWrapper = .{
|
||||
.it = .{
|
||||
.first = remaining,
|
||||
.last = r.buffer,
|
||||
},
|
||||
.writer = .{
|
||||
.buffer = if (remaining.len >= r.buffer.len) remaining else r.buffer,
|
||||
.vtable = Writer.VectorWrapper.vtable,
|
||||
},
|
||||
};
|
||||
const n = r.vtable.stream(r, &wrapper.writer, .unlimited) catch |err| switch (err) {
|
||||
error.WriteFailed => {
|
||||
if (!wrapper.used) {
|
||||
assert(r.seek == 0);
|
||||
r.seek = remaining.len;
|
||||
r.end = wrapper.writer.end;
|
||||
@memcpy(remaining, r.buffer[0..remaining.len]);
|
||||
}
|
||||
return buffer.len;
|
||||
},
|
||||
const new_remaining_len = readVecInner(r, &.{}, remaining, remaining.len) catch |err| switch (err) {
|
||||
error.EndOfStream => return i,
|
||||
error.ReadFailed => return error.ReadFailed,
|
||||
};
|
||||
if (n < remaining.len) {
|
||||
i += n;
|
||||
continue;
|
||||
}
|
||||
r.end = n - remaining.len;
|
||||
return buffer.len;
|
||||
if (new_remaining_len == 0) return buffer.len;
|
||||
i += remaining.len - new_remaining_len;
|
||||
}
|
||||
return buffer.len;
|
||||
}
|
||||
|
||||
/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
|
||||
@ -1627,6 +1621,19 @@ test readSliceShort {
|
||||
try testing.expectEqual(0, try r.readSliceShort(&buf));
|
||||
}
|
||||
|
||||
test "readSliceShort with smaller buffer than Reader" {
|
||||
var reader_buf: [15]u8 = undefined;
|
||||
const str = "This is a test";
|
||||
var one_byte_stream: testing.Reader = .init(&reader_buf, &.{
|
||||
.{ .buffer = str },
|
||||
});
|
||||
one_byte_stream.artificial_limit = .limited(1);
|
||||
|
||||
var buf: [14]u8 = undefined;
|
||||
try testing.expectEqual(14, try one_byte_stream.interface.readSliceShort(&buf));
|
||||
try testing.expectEqualStrings(str, &buf);
|
||||
}
|
||||
|
||||
test readVec {
|
||||
var r: Reader = .fixed(std.ascii.letters);
|
||||
var flat_buffer: [52]u8 = undefined;
|
||||
@ -1689,33 +1696,13 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
|
||||
}
|
||||
|
||||
test "readAlloc when the backing reader provides one byte at a time" {
|
||||
const OneByteReader = struct {
|
||||
str: []const u8,
|
||||
i: usize,
|
||||
reader: Reader,
|
||||
|
||||
fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
|
||||
assert(@intFromEnum(limit) >= 1);
|
||||
const self: *@This() = @fieldParentPtr("reader", r);
|
||||
if (self.str.len - self.i == 0) return error.EndOfStream;
|
||||
try w.writeByte(self.str[self.i]);
|
||||
self.i += 1;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
const str = "This is a test";
|
||||
var tiny_buffer: [1]u8 = undefined;
|
||||
var one_byte_stream: OneByteReader = .{
|
||||
.str = str,
|
||||
.i = 0,
|
||||
.reader = .{
|
||||
.buffer = &tiny_buffer,
|
||||
.vtable = &.{ .stream = OneByteReader.stream },
|
||||
.seek = 0,
|
||||
.end = 0,
|
||||
},
|
||||
};
|
||||
const res = try one_byte_stream.reader.allocRemaining(std.testing.allocator, .unlimited);
|
||||
var one_byte_stream: testing.Reader = .init(&tiny_buffer, &.{
|
||||
.{ .buffer = str },
|
||||
});
|
||||
one_byte_stream.artificial_limit = .limited(1);
|
||||
const res = try one_byte_stream.interface.allocRemaining(std.testing.allocator, .unlimited);
|
||||
defer std.testing.allocator.free(res);
|
||||
try std.testing.expectEqualStrings(str, res);
|
||||
}
|
||||
|
||||
@ -483,7 +483,7 @@ pub fn writeSplatAll(w: *Writer, data: [][]const u8, splat: usize) Error!void {
|
||||
|
||||
// Deal with any left over splats
|
||||
if (data.len != 0 and truncate < data[index].len * splat) {
|
||||
std.debug.assert(index == data.len - 1);
|
||||
assert(index == data.len - 1);
|
||||
var remaining_splat = splat;
|
||||
while (true) {
|
||||
remaining_splat -= truncate / data[index].len;
|
||||
@ -618,10 +618,6 @@ pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) E
|
||||
/// A user type may be a `struct`, `vector`, `union` or `enum` type.
|
||||
///
|
||||
/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
|
||||
///
|
||||
/// Asserts `buffer` capacity of at least 2 if a union is printed. This
|
||||
/// requirement could be lifted by adjusting the code, but if you trigger that
|
||||
/// assertion it is a clue that you should probably be using a buffer.
|
||||
pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
|
||||
const ArgsType = @TypeOf(args);
|
||||
const args_type_info = @typeInfo(ArgsType);
|
||||
@ -840,11 +836,11 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian
|
||||
.auto => @compileError("ill-defined memory layout"),
|
||||
.@"extern" => {
|
||||
if (native_endian == endian) {
|
||||
return w.writeStruct(value);
|
||||
return w.writeAll(@ptrCast((&value)[0..1]));
|
||||
} else {
|
||||
var copy = value;
|
||||
std.mem.byteSwapAllFields(@TypeOf(value), ©);
|
||||
return w.writeStruct(copy);
|
||||
return w.writeAll(@ptrCast((©)[0..1]));
|
||||
}
|
||||
},
|
||||
.@"packed" => {
|
||||
@ -855,6 +851,9 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian
|
||||
}
|
||||
}
|
||||
|
||||
/// If, `endian` is not native,
|
||||
/// * Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
|
||||
/// * Asserts that the buffer is aligned enough for `@alignOf(Elem)`.
|
||||
pub inline fn writeSliceEndian(
|
||||
w: *Writer,
|
||||
Elem: type,
|
||||
@ -864,7 +863,22 @@ pub inline fn writeSliceEndian(
|
||||
if (native_endian == endian) {
|
||||
return writeAll(w, @ptrCast(slice));
|
||||
} else {
|
||||
return w.writeArraySwap(w, Elem, slice);
|
||||
return writeSliceSwap(w, Elem, slice);
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
|
||||
///
|
||||
/// Asserts that the buffer is aligned enough for `@alignOf(Elem)`.
|
||||
pub fn writeSliceSwap(w: *Writer, Elem: type, slice: []const Elem) Error!void {
|
||||
var i: usize = 0;
|
||||
while (i < slice.len) {
|
||||
const dest_bytes = try w.writableSliceGreedy(@sizeOf(Elem));
|
||||
const dest: []Elem = @alignCast(@ptrCast(dest_bytes[0 .. dest_bytes.len - dest_bytes.len % @sizeOf(Elem)]));
|
||||
const copy_len = @min(dest.len, slice.len - i);
|
||||
@memcpy(dest[0..copy_len], slice[i..][0..copy_len]);
|
||||
i += copy_len;
|
||||
std.mem.byteSwapAllElements(Elem, dest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1257,14 +1271,13 @@ pub fn printValue(
|
||||
.@"extern", .@"packed" => {
|
||||
if (info.fields.len == 0) return w.writeAll(".{}");
|
||||
try w.writeAll(".{ ");
|
||||
inline for (info.fields) |field| {
|
||||
inline for (info.fields, 1..) |field, i| {
|
||||
try w.writeByte('.');
|
||||
try w.writeAll(field.name);
|
||||
try w.writeAll(" = ");
|
||||
try w.printValue(ANY, options, @field(value, field.name), max_depth - 1);
|
||||
(try w.writableArray(2)).* = ", ".*;
|
||||
try w.writeAll(if (i < info.fields.len) ", " else " }");
|
||||
}
|
||||
w.buffer[w.end - 2 ..][0..2].* = " }".*;
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -2475,6 +2488,18 @@ pub const Allocating = struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn ensureUnusedCapacity(a: *Allocating, additional_count: usize) Allocator.Error!void {
|
||||
var list = a.toArrayList();
|
||||
defer a.setArrayList(list);
|
||||
return list.ensureUnusedCapacity(a.allocator, additional_count);
|
||||
}
|
||||
|
||||
pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void {
|
||||
var list = a.toArrayList();
|
||||
defer a.setArrayList(list);
|
||||
return list.ensureTotalCapacity(a.allocator, new_capacity);
|
||||
}
|
||||
|
||||
pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 {
|
||||
var list = a.toArrayList();
|
||||
defer a.setArrayList(list);
|
||||
@ -2594,8 +2619,40 @@ test "allocating sendFile" {
|
||||
var file_reader = file_writer.moveToReader();
|
||||
try file_reader.seekTo(0);
|
||||
|
||||
var allocating: std.io.Writer.Allocating = .init(std.testing.allocator);
|
||||
var allocating: std.io.Writer.Allocating = .init(testing.allocator);
|
||||
defer allocating.deinit();
|
||||
|
||||
_ = try file_reader.interface.streamRemaining(&allocating.writer);
|
||||
}
|
||||
|
||||
test writeStruct {
|
||||
var buffer: [16]u8 = undefined;
|
||||
const S = extern struct { a: u64, b: u32, c: u32 };
|
||||
const s: S = .{ .a = 1, .b = 2, .c = 3 };
|
||||
{
|
||||
var w: Writer = .fixed(&buffer);
|
||||
try w.writeStruct(s, .little);
|
||||
try testing.expectEqualSlices(u8, &.{
|
||||
1, 0, 0, 0, 0, 0, 0, 0, //
|
||||
2, 0, 0, 0, //
|
||||
3, 0, 0, 0, //
|
||||
}, &buffer);
|
||||
}
|
||||
{
|
||||
var w: Writer = .fixed(&buffer);
|
||||
try w.writeStruct(s, .big);
|
||||
try testing.expectEqualSlices(u8, &.{
|
||||
0, 0, 0, 0, 0, 0, 0, 1, //
|
||||
0, 0, 0, 2, //
|
||||
0, 0, 0, 3, //
|
||||
}, &buffer);
|
||||
}
|
||||
}
|
||||
|
||||
test writeSliceEndian {
|
||||
var buffer: [4]u8 align(2) = undefined;
|
||||
var w: Writer = .fixed(&buffer);
|
||||
const array: [2]u16 = .{ 0x1234, 0x5678 };
|
||||
try writeSliceEndian(&w, u16, &array, .big);
|
||||
try testing.expectEqualSlices(u8, &.{ 0x12, 0x34, 0x56, 0x78 }, &buffer);
|
||||
}
|
||||
|
||||
@ -633,6 +633,7 @@ pub fn lockStderrWriter(buffer: []u8) *Writer {
|
||||
|
||||
pub fn unlockStderrWriter() void {
|
||||
stderr_writer.flush() catch {};
|
||||
stderr_writer.end = 0;
|
||||
stderr_writer.buffer = &.{};
|
||||
stderr_mutex.unlock();
|
||||
}
|
||||
|
||||
@ -566,6 +566,13 @@ pub fn assertReadable(slice: []const volatile u8) void {
|
||||
for (slice) |*byte| _ = byte.*;
|
||||
}
|
||||
|
||||
/// Invokes detectable illegal behavior when the provided array is not aligned
|
||||
/// to the provided amount.
|
||||
pub fn assertAligned(ptr: anytype, comptime alignment: std.mem.Alignment) void {
|
||||
const aligned_ptr: *align(alignment.toByteUnits()) anyopaque = @alignCast(@ptrCast(ptr));
|
||||
_ = aligned_ptr;
|
||||
}
|
||||
|
||||
/// Equivalent to `@panic` but with a formatted message.
|
||||
pub fn panic(comptime format: []const u8, args: anytype) noreturn {
|
||||
@branchHint(.cold);
|
||||
|
||||
@ -10,6 +10,7 @@ const std = @import("../std.zig");
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1
|
||||
/// when x is near 0.
|
||||
@ -39,9 +40,9 @@ fn expm1_32(x_: f32) f32 {
|
||||
const Q2: f32 = 1.5807170421e-3;
|
||||
|
||||
var x = x_;
|
||||
const ux = @as(u32, @bitCast(x));
|
||||
const ux: u32 = @bitCast(x);
|
||||
const hx = ux & 0x7FFFFFFF;
|
||||
const sign = hx >> 31;
|
||||
const sign = ux >> 31;
|
||||
|
||||
// TODO: Shouldn't need this check explicitly.
|
||||
if (math.isNegativeInf(x)) {
|
||||
@ -147,7 +148,7 @@ fn expm1_32(x_: f32) f32 {
|
||||
return y - 1.0;
|
||||
}
|
||||
|
||||
const uf = @as(f32, @bitCast(@as(u32, @intCast(0x7F -% k)) << 23));
|
||||
const uf: f32 = @bitCast(@as(u32, @intCast(0x7F -% k)) << 23);
|
||||
if (k < 23) {
|
||||
return (x - e + (1 - uf)) * twopk;
|
||||
} else {
|
||||
@ -286,39 +287,77 @@ fn expm1_64(x_: f64) f64 {
|
||||
}
|
||||
}
|
||||
|
||||
test expm1 {
|
||||
try expect(expm1(@as(f32, 0.0)) == expm1_32(0.0));
|
||||
try expect(expm1(@as(f64, 0.0)) == expm1_64(0.0));
|
||||
}
|
||||
|
||||
test expm1_32 {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
test "expm1_32() special" {
|
||||
try expect(math.isPositiveZero(expm1_32(0.0)));
|
||||
try expect(math.approxEqAbs(f32, expm1_32(0.0), 0.0, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expm1_32(0.2), 0.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expm1_32(0.8923), 1.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expm1_32(1.5), 3.481689, epsilon));
|
||||
}
|
||||
|
||||
test expm1_64 {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(math.isPositiveZero(expm1_64(0.0)));
|
||||
try expect(math.approxEqAbs(f64, expm1_64(0.0), 0.0, epsilon));
|
||||
try expect(math.approxEqAbs(f64, expm1_64(0.2), 0.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f64, expm1_64(0.8923), 1.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f64, expm1_64(1.5), 3.481689, epsilon));
|
||||
}
|
||||
|
||||
test "expm1_32.special" {
|
||||
try expect(math.isPositiveInf(expm1_32(math.inf(f32))));
|
||||
try expect(expm1_32(-math.inf(f32)) == -1.0);
|
||||
try expect(math.isNegativeZero(expm1_32(-0.0)));
|
||||
try expectEqual(expm1_32(math.ln2), 1.0);
|
||||
try expectEqual(expm1_32(math.inf(f32)), math.inf(f32));
|
||||
try expectEqual(expm1_32(-math.inf(f32)), -1.0);
|
||||
try expect(math.isNan(expm1_32(math.nan(f32))));
|
||||
try expect(math.isNan(expm1_32(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "expm1_64.special" {
|
||||
try expect(math.isPositiveInf(expm1_64(math.inf(f64))));
|
||||
try expect(expm1_64(-math.inf(f64)) == -1.0);
|
||||
try expect(math.isNan(expm1_64(math.nan(f64))));
|
||||
test "expm1_32() sanity" {
|
||||
try expectEqual(expm1_32(-0x1.0223a0p+3), -0x1.ffd6e0p-1);
|
||||
try expectEqual(expm1_32(0x1.161868p+2), 0x1.30712ap+6);
|
||||
try expectEqual(expm1_32(-0x1.0c34b4p+3), -0x1.ffe1fap-1);
|
||||
try expectEqual(expm1_32(-0x1.a206f0p+2), -0x1.ff4116p-1);
|
||||
try expectEqual(expm1_32(0x1.288bbcp+3), 0x1.4ab480p+13); // Disagrees with GCC in last bit
|
||||
try expectEqual(expm1_32(0x1.52efd0p-1), 0x1.e09536p-1);
|
||||
try expectEqual(expm1_32(-0x1.a05cc8p-2), -0x1.561c3ep-2);
|
||||
try expectEqual(expm1_32(0x1.1f9efap-1), 0x1.81ec4ep-1);
|
||||
try expectEqual(expm1_32(0x1.8c5db0p-1), 0x1.2b3364p+0);
|
||||
try expectEqual(expm1_32(-0x1.5b86eap-1), -0x1.f8951ap-2);
|
||||
}
|
||||
|
||||
test "expm1_32() boundary" {
|
||||
// TODO: The last value before inf is actually 0x1.62e300p+6 -> 0x1.ff681ep+127
|
||||
// try expectEqual(expm1_32(0x1.62e42ep+6), 0x1.ffff08p+127); // Last value before result is inf
|
||||
try expectEqual(expm1_32(0x1.62e430p+6), math.inf(f32)); // First value that gives inf
|
||||
try expectEqual(expm1_32(0x1.fffffep+127), math.inf(f32)); // Max input value
|
||||
try expectEqual(expm1_32(0x1p-149), 0x1p-149); // Min positive input value
|
||||
try expectEqual(expm1_32(-0x1p-149), -0x1p-149); // Min negative input value
|
||||
try expectEqual(expm1_32(0x1p-126), 0x1p-126); // First positive subnormal input
|
||||
try expectEqual(expm1_32(-0x1p-126), -0x1p-126); // First negative subnormal input
|
||||
try expectEqual(expm1_32(0x1.fffffep-125), 0x1.fffffep-125); // Last positive value before subnormal
|
||||
try expectEqual(expm1_32(-0x1.fffffep-125), -0x1.fffffep-125); // Last negative value before subnormal
|
||||
try expectEqual(expm1_32(-0x1.154244p+4), -0x1.fffffep-1); // Last value before result is -1
|
||||
try expectEqual(expm1_32(-0x1.154246p+4), -1); // First value where result is -1
|
||||
}
|
||||
|
||||
test "expm1_64() special" {
|
||||
try expect(math.isPositiveZero(expm1_64(0.0)));
|
||||
try expect(math.isNegativeZero(expm1_64(-0.0)));
|
||||
try expectEqual(expm1_64(math.ln2), 1.0);
|
||||
try expectEqual(expm1_64(math.inf(f64)), math.inf(f64));
|
||||
try expectEqual(expm1_64(-math.inf(f64)), -1.0);
|
||||
try expect(math.isNan(expm1_64(math.nan(f64))));
|
||||
try expect(math.isNan(expm1_64(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "expm1_64() sanity" {
|
||||
try expectEqual(expm1_64(-0x1.02239f3c6a8f1p+3), -0x1.ffd6df9b02b3ep-1);
|
||||
try expectEqual(expm1_64(0x1.161868e18bc67p+2), 0x1.30712ed238c04p+6);
|
||||
try expectEqual(expm1_64(-0x1.0c34b3e01e6e7p+3), -0x1.ffe1f94e493e7p-1);
|
||||
try expectEqual(expm1_64(-0x1.a206f0a19dcc4p+2), -0x1.ff4115c03f78dp-1);
|
||||
try expectEqual(expm1_64(0x1.288bbb0d6a1e6p+3), 0x1.4ab477496e07ep+13);
|
||||
try expectEqual(expm1_64(0x1.52efd0cd80497p-1), 0x1.e095382100a01p-1);
|
||||
try expectEqual(expm1_64(-0x1.a05cc754481d1p-2), -0x1.561c3e0582be6p-2);
|
||||
try expectEqual(expm1_64(0x1.1f9ef934745cbp-1), 0x1.81ec4cd4d4a8fp-1);
|
||||
try expectEqual(expm1_64(0x1.8c5db097f7442p-1), 0x1.2b3363a944bf7p+0);
|
||||
try expectEqual(expm1_64(-0x1.5b86ea8118a0ep-1), -0x1.f8951aebffbafp-2);
|
||||
}
|
||||
|
||||
test "expm1_64() boundary" {
|
||||
try expectEqual(expm1_64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // Last value before result is inf
|
||||
try expectEqual(expm1_64(0x1.62e42fefa39f0p+9), math.inf(f64)); // First value that gives inf
|
||||
try expectEqual(expm1_64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
|
||||
try expectEqual(expm1_64(0x1p-1074), 0x1p-1074); // Min positive input value
|
||||
try expectEqual(expm1_64(-0x1p-1074), -0x1p-1074); // Min negative input value
|
||||
try expectEqual(expm1_64(0x1p-1022), 0x1p-1022); // First positive subnormal input
|
||||
try expectEqual(expm1_64(-0x1p-1022), -0x1p-1022); // First negative subnormal input
|
||||
try expectEqual(expm1_64(0x1.fffffffffffffp-1021), 0x1.fffffffffffffp-1021); // Last positive value before subnormal
|
||||
try expectEqual(expm1_64(-0x1.fffffffffffffp-1021), -0x1.fffffffffffffp-1021); // Last negative value before subnormal
|
||||
try expectEqual(expm1_64(-0x1.2b708872320e1p+5), -0x1.fffffffffffffp-1); // Last value before result is -1
|
||||
try expectEqual(expm1_64(-0x1.2b708872320e2p+5), -1); // First value where result is -1
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ const std = @import("../std.zig");
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
/// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero.
|
||||
///
|
||||
@ -182,49 +183,72 @@ fn log1p_64(x: f64) f64 {
|
||||
return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
|
||||
}
|
||||
|
||||
test log1p {
|
||||
try expect(log1p(@as(f32, 0.0)) == log1p_32(0.0));
|
||||
try expect(log1p(@as(f64, 0.0)) == log1p_64(0.0));
|
||||
}
|
||||
|
||||
test log1p_32 {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(math.approxEqAbs(f32, log1p_32(0.0), 0.0, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log1p_32(0.2), 0.182322, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log1p_32(0.8923), 0.637793, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log1p_32(1.5), 0.916291, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log1p_32(37.45), 3.649359, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log1p_32(89.123), 4.501175, epsilon));
|
||||
try expect(math.approxEqAbs(f32, log1p_32(123123.234375), 11.720949, epsilon));
|
||||
}
|
||||
|
||||
test log1p_64 {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(math.approxEqAbs(f64, log1p_64(0.0), 0.0, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log1p_64(0.2), 0.182322, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log1p_64(0.8923), 0.637793, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log1p_64(1.5), 0.916291, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log1p_64(37.45), 3.649359, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log1p_64(89.123), 4.501175, epsilon));
|
||||
try expect(math.approxEqAbs(f64, log1p_64(123123.234375), 11.720949, epsilon));
|
||||
}
|
||||
|
||||
test "log1p_32.special" {
|
||||
try expect(math.isPositiveInf(log1p_32(math.inf(f32))));
|
||||
test "log1p_32() special" {
|
||||
try expect(math.isPositiveZero(log1p_32(0.0)));
|
||||
try expect(math.isNegativeZero(log1p_32(-0.0)));
|
||||
try expect(math.isNegativeInf(log1p_32(-1.0)));
|
||||
try expectEqual(log1p_32(-1.0), -math.inf(f32));
|
||||
try expectEqual(log1p_32(1.0), math.ln2);
|
||||
try expectEqual(log1p_32(math.inf(f32)), math.inf(f32));
|
||||
try expect(math.isNan(log1p_32(-2.0)));
|
||||
try expect(math.isNan(log1p_32(-math.inf(f32))));
|
||||
try expect(math.isNan(log1p_32(math.nan(f32))));
|
||||
try expect(math.isNan(log1p_32(math.snan(f32))));
|
||||
}
|
||||
|
||||
test "log1p_64.special" {
|
||||
try expect(math.isPositiveInf(log1p_64(math.inf(f64))));
|
||||
test "log1p_32() sanity" {
|
||||
try expect(math.isNan(log1p_32(-0x1.0223a0p+3)));
|
||||
try expectEqual(log1p_32(0x1.161868p+2), 0x1.ad1bdcp+0);
|
||||
try expect(math.isNan(log1p_32(-0x1.0c34b4p+3)));
|
||||
try expect(math.isNan(log1p_32(-0x1.a206f0p+2)));
|
||||
try expectEqual(log1p_32(0x1.288bbcp+3), 0x1.2a1ab8p+1);
|
||||
try expectEqual(log1p_32(0x1.52efd0p-1), 0x1.041a4ep-1);
|
||||
try expectEqual(log1p_32(-0x1.a05cc8p-2), -0x1.0b3596p-1);
|
||||
try expectEqual(log1p_32(0x1.1f9efap-1), 0x1.c88344p-2);
|
||||
try expectEqual(log1p_32(0x1.8c5db0p-1), 0x1.258a8ep-1);
|
||||
try expectEqual(log1p_32(-0x1.5b86eap-1), -0x1.22b542p+0);
|
||||
}
|
||||
|
||||
test "log1p_32() boundary" {
|
||||
try expectEqual(log1p_32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
|
||||
try expectEqual(log1p_32(0x1p-149), 0x1p-149); // Min positive input value
|
||||
try expectEqual(log1p_32(-0x1p-149), -0x1p-149); // Min negative input value
|
||||
try expectEqual(log1p_32(0x1p-126), 0x1p-126); // First subnormal
|
||||
try expectEqual(log1p_32(-0x1p-126), -0x1p-126); // First negative subnormal
|
||||
try expectEqual(log1p_32(-0x1.fffffep-1), -0x1.0a2b24p+4); // Last value before result is -inf
|
||||
try expect(math.isNan(log1p_32(-0x1.000002p+0))); // First value where result is nan
|
||||
}
|
||||
|
||||
test "log1p_64() special" {
|
||||
try expect(math.isPositiveZero(log1p_64(0.0)));
|
||||
try expect(math.isNegativeZero(log1p_64(-0.0)));
|
||||
try expect(math.isNegativeInf(log1p_64(-1.0)));
|
||||
try expectEqual(log1p_64(-1.0), -math.inf(f64));
|
||||
try expectEqual(log1p_64(1.0), math.ln2);
|
||||
try expectEqual(log1p_64(math.inf(f64)), math.inf(f64));
|
||||
try expect(math.isNan(log1p_64(-2.0)));
|
||||
try expect(math.isNan(log1p_64(-math.inf(f64))));
|
||||
try expect(math.isNan(log1p_64(math.nan(f64))));
|
||||
try expect(math.isNan(log1p_64(math.snan(f64))));
|
||||
}
|
||||
|
||||
test "log1p_64() sanity" {
|
||||
try expect(math.isNan(log1p_64(-0x1.02239f3c6a8f1p+3)));
|
||||
try expectEqual(log1p_64(0x1.161868e18bc67p+2), 0x1.ad1bdd1e9e686p+0); // Disagrees with GCC in last bit
|
||||
try expect(math.isNan(log1p_64(-0x1.0c34b3e01e6e7p+3)));
|
||||
try expect(math.isNan(log1p_64(-0x1.a206f0a19dcc4p+2)));
|
||||
try expectEqual(log1p_64(0x1.288bbb0d6a1e6p+3), 0x1.2a1ab8365b56fp+1);
|
||||
try expectEqual(log1p_64(0x1.52efd0cd80497p-1), 0x1.041a4ec2a680ap-1);
|
||||
try expectEqual(log1p_64(-0x1.a05cc754481d1p-2), -0x1.0b3595423aec1p-1);
|
||||
try expectEqual(log1p_64(0x1.1f9ef934745cbp-1), 0x1.c8834348a846ep-2);
|
||||
try expectEqual(log1p_64(0x1.8c5db097f7442p-1), 0x1.258a8e8a35bbfp-1);
|
||||
try expectEqual(log1p_64(-0x1.5b86ea8118a0ep-1), -0x1.22b5426327502p+0);
|
||||
}
|
||||
|
||||
test "log1p_64() boundary" {
|
||||
try expectEqual(log1p_64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
|
||||
try expectEqual(log1p_64(0x1p-1074), 0x1p-1074); // Min positive input value
|
||||
try expectEqual(log1p_64(-0x1p-1074), -0x1p-1074); // Min negative input value
|
||||
try expectEqual(log1p_64(0x1p-1022), 0x1p-1022); // First subnormal
|
||||
try expectEqual(log1p_64(-0x1p-1022), -0x1p-1022); // First negative subnormal
|
||||
try expectEqual(log1p_64(-0x1.fffffffffffffp-1), -0x1.25e4f7b2737fap+5); // Last value before result is -inf
|
||||
try expect(math.isNan(log1p_64(-0x1.0000000000001p+0))); // First value where result is nan
|
||||
}
|
||||
|
||||
@ -2179,22 +2179,8 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
|
||||
const BackingInt = std.meta.Int(.unsigned, @bitSizeOf(S));
|
||||
ptr.* = @bitCast(@byteSwap(@as(BackingInt, @bitCast(ptr.*))));
|
||||
},
|
||||
.array => {
|
||||
for (ptr) |*item| {
|
||||
switch (@typeInfo(@TypeOf(item.*))) {
|
||||
.@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(item.*), item),
|
||||
.@"enum" => {
|
||||
item.* = @enumFromInt(@byteSwap(@intFromEnum(item.*)));
|
||||
},
|
||||
.bool => {},
|
||||
.float => |float_info| {
|
||||
item.* = @bitCast(@byteSwap(@as(std.meta.Int(.unsigned, float_info.bits), @bitCast(item.*))));
|
||||
},
|
||||
else => {
|
||||
item.* = @byteSwap(item.*);
|
||||
},
|
||||
}
|
||||
}
|
||||
.array => |info| {
|
||||
byteSwapAllElements(info.child, ptr);
|
||||
},
|
||||
else => {
|
||||
ptr.* = @byteSwap(ptr.*);
|
||||
@ -2258,6 +2244,24 @@ test byteSwapAllFields {
|
||||
}, k);
|
||||
}
|
||||
|
||||
pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
|
||||
for (slice) |*elem| {
|
||||
switch (@typeInfo(@TypeOf(elem.*))) {
|
||||
.@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(elem.*), elem),
|
||||
.@"enum" => {
|
||||
elem.* = @enumFromInt(@byteSwap(@intFromEnum(elem.*)));
|
||||
},
|
||||
.bool => {},
|
||||
.float => |float_info| {
|
||||
elem.* = @bitCast(@byteSwap(@as(std.meta.Int(.unsigned, float_info.bits), @bitCast(elem.*))));
|
||||
},
|
||||
else => {
|
||||
elem.* = @byteSwap(elem.*);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that iterates over the slices of `buffer` that are not
|
||||
/// any of the items in `delimiters`.
|
||||
///
|
||||
|
||||
@ -214,7 +214,7 @@ pub const File = extern struct {
|
||||
pub fn getInfo(
|
||||
self: *const File,
|
||||
comptime info: std.meta.Tag(Info),
|
||||
buffer: []u8,
|
||||
buffer: []align(@alignOf(@FieldType(Info, @tagName(info)))) u8,
|
||||
) GetInfoError!*@FieldType(Info, @tagName(info)) {
|
||||
const InfoType = @FieldType(Info, @tagName(info));
|
||||
|
||||
|
||||
@ -1210,12 +1210,14 @@ pub inline fn fuzz(
|
||||
return @import("root").fuzz(context, testOne, options);
|
||||
}
|
||||
|
||||
/// A `std.io.Reader` that writes a predetermined list of buffers during `stream`.
|
||||
/// A `std.Io.Reader` that writes a predetermined list of buffers during `stream`.
|
||||
pub const Reader = struct {
|
||||
calls: []const Call,
|
||||
interface: std.io.Reader,
|
||||
interface: std.Io.Reader,
|
||||
next_call_index: usize,
|
||||
next_offset: usize,
|
||||
/// Further reduces how many bytes are written in each `stream` call.
|
||||
artificial_limit: std.Io.Limit = .unlimited,
|
||||
|
||||
pub const Call = struct {
|
||||
buffer: []const u8,
|
||||
@ -1235,11 +1237,11 @@ pub const Reader = struct {
|
||||
};
|
||||
}
|
||||
|
||||
fn stream(io_r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
|
||||
fn stream(io_r: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize {
|
||||
const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r));
|
||||
if (r.calls.len - r.next_call_index == 0) return error.EndOfStream;
|
||||
const call = r.calls[r.next_call_index];
|
||||
const buffer = limit.sliceConst(call.buffer[r.next_offset..]);
|
||||
const buffer = r.artificial_limit.sliceConst(limit.sliceConst(call.buffer[r.next_offset..]));
|
||||
const n = try w.write(buffer);
|
||||
r.next_offset += n;
|
||||
if (call.buffer.len - r.next_offset == 0) {
|
||||
|
||||
@ -536,7 +536,8 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *std.fs.File.Reader
|
||||
|
||||
if (file_reader.getSize()) |size| {
|
||||
const casted_size = std.math.cast(u32, size) orelse return error.StreamTooLong;
|
||||
try buffer.ensureTotalCapacityPrecise(gpa, casted_size);
|
||||
// +1 to avoid resizing for the null byte added in toOwnedSliceSentinel below.
|
||||
try buffer.ensureTotalCapacityPrecise(gpa, casted_size + 1);
|
||||
} else |_| {}
|
||||
|
||||
try file_reader.interface.appendRemaining(gpa, .@"2", &buffer, .limited(max_src_size));
|
||||
@ -904,4 +905,5 @@ test {
|
||||
_ = system;
|
||||
_ = target;
|
||||
_ = c_translation;
|
||||
_ = llvm;
|
||||
}
|
||||
|
||||
@ -484,8 +484,7 @@ fn findNativeKernel32LibDir(
|
||||
|
||||
for (installs) |install| {
|
||||
result_buf.shrinkAndFree(0);
|
||||
const stream = result_buf.writer();
|
||||
try stream.print("{s}\\Lib\\{s}\\um\\{s}", .{ install.path, install.version, arch_sub_dir });
|
||||
try result_buf.print("{s}\\Lib\\{s}\\um\\{s}", .{ install.path, install.version, arch_sub_dir });
|
||||
|
||||
var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound,
|
||||
|
||||
@ -118,6 +118,8 @@ pub fn init(options: Options) !Server {
|
||||
.in = options.in,
|
||||
.out = options.out,
|
||||
};
|
||||
assert(s.out.buffer.len >= 4);
|
||||
std.debug.assertAligned(s.out.buffer.ptr, .@"4");
|
||||
try s.serveStringMessage(.zig_version, options.zig_version);
|
||||
return s;
|
||||
}
|
||||
@ -141,7 +143,7 @@ pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !voi
|
||||
|
||||
/// Don't forget to flush!
|
||||
pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void {
|
||||
try s.out.writeStructEndian(header, .little);
|
||||
try s.out.writeStruct(header, .little);
|
||||
}
|
||||
|
||||
pub fn serveU64Message(s: *const Server, tag: OutMessage.Tag, int: u64) !void {
|
||||
@ -162,7 +164,7 @@ pub fn serveEmitDigest(
|
||||
.tag = .emit_digest,
|
||||
.bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)),
|
||||
});
|
||||
try s.out.writeStructEndian(header, .little);
|
||||
try s.out.writeStruct(header, .little);
|
||||
try s.out.writeAll(digest);
|
||||
try s.out.flush();
|
||||
}
|
||||
@ -172,7 +174,7 @@ pub fn serveTestResults(s: *Server, msg: OutMessage.TestResults) !void {
|
||||
.tag = .test_results,
|
||||
.bytes_len = @intCast(@sizeOf(OutMessage.TestResults)),
|
||||
});
|
||||
try s.out.writeStructEndian(msg, .little);
|
||||
try s.out.writeStruct(msg, .little);
|
||||
try s.out.flush();
|
||||
}
|
||||
|
||||
@ -187,7 +189,7 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
|
||||
.tag = .error_bundle,
|
||||
.bytes_len = @intCast(bytes_len),
|
||||
});
|
||||
try s.out.writeStructEndian(eb_hdr, .little);
|
||||
try s.out.writeStruct(eb_hdr, .little);
|
||||
try s.out.writeSliceEndian(u32, error_bundle.extra, .little);
|
||||
try s.out.writeAll(error_bundle.string_bytes);
|
||||
try s.out.flush();
|
||||
@ -212,7 +214,7 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
|
||||
.tag = .test_metadata,
|
||||
.bytes_len = @intCast(bytes_len),
|
||||
});
|
||||
try s.out.writeStructEndian(header, .little);
|
||||
try s.out.writeStruct(header, .little);
|
||||
try s.out.writeSliceEndian(u32, test_metadata.names, .little);
|
||||
try s.out.writeSliceEndian(u32, test_metadata.expected_panic_msgs, .little);
|
||||
try s.out.writeAll(test_metadata.string_bytes);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const WindowsSdk = @This();
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const Writer = std.io.Writer;
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
windows10sdk: ?Installation,
|
||||
windows81sdk: ?Installation,
|
||||
@ -760,13 +760,13 @@ const MsvcLibDir = struct {
|
||||
while (instances_dir_it.next() catch return error.PathNotFound) |entry| {
|
||||
if (entry.kind != .directory) continue;
|
||||
|
||||
var bw: Writer = .fixed(&state_subpath_buf);
|
||||
var writer: Writer = .fixed(&state_subpath_buf);
|
||||
|
||||
bw.writeAll(entry.name) catch unreachable;
|
||||
bw.writeByte(std.fs.path.sep) catch unreachable;
|
||||
bw.writeAll("state.json") catch unreachable;
|
||||
writer.writeAll(entry.name) catch unreachable;
|
||||
writer.writeByte(std.fs.path.sep) catch unreachable;
|
||||
writer.writeAll("state.json") catch unreachable;
|
||||
|
||||
const json_contents = instances_dir.readFileAlloc(allocator, bw.getWritten(), std.math.maxInt(usize)) catch continue;
|
||||
const json_contents = instances_dir.readFileAlloc(allocator, writer.buffered(), std.math.maxInt(usize)) catch continue;
|
||||
defer allocator.free(json_contents);
|
||||
|
||||
var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue;
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
pub const BitcodeReader = @import("llvm/BitcodeReader.zig");
|
||||
pub const bitcode_writer = @import("llvm/bitcode_writer.zig");
|
||||
pub const Builder = @import("llvm/Builder.zig");
|
||||
|
||||
test {
|
||||
_ = BitcodeReader;
|
||||
_ = bitcode_writer;
|
||||
_ = Builder;
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ pub fn next(bc: *BitcodeReader) !?Item {
|
||||
|
||||
pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {
|
||||
assert(bc.bit_offset == 0);
|
||||
try bc.reader.discard(4 * @as(u34, block.len));
|
||||
try bc.reader.discardAll(4 * @as(u34, block.len));
|
||||
try bc.endBlock();
|
||||
}
|
||||
|
||||
@ -513,3 +513,7 @@ const Abbrev = struct {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
test {
|
||||
_ = &skipBlock;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const Tokenizer = std.zig.Tokenizer;
|
||||
const io = std.io;
|
||||
const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
|
||||
|
||||
const source = @embedFile("../os.zig");
|
||||
@ -22,16 +21,15 @@ pub fn main() !void {
|
||||
const bytes_per_sec_float = @as(f64, @floatFromInt(source.len * iterations)) / elapsed_s;
|
||||
const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));
|
||||
|
||||
var stdout_file: std.fs.File = .stdout();
|
||||
const stdout = stdout_file.writer();
|
||||
try stdout.print("parsing speed: {:.2}/s, {:.2} used \n", .{
|
||||
fmtIntSizeBin(bytes_per_sec),
|
||||
fmtIntSizeBin(memory_used),
|
||||
});
|
||||
var stdout_buffer: [1024]u8 = undefined;
|
||||
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||
const stdout = &stdout_writer.interface;
|
||||
try stdout.print("parsing speed: {Bi:.2}/s, {Bi:.2} used \n", .{ bytes_per_sec, memory_used });
|
||||
try stdout.flush();
|
||||
}
|
||||
|
||||
fn testOnce() usize {
|
||||
var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
|
||||
var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(&fixed_buffer_mem);
|
||||
const allocator = fixed_buf_alloc.allocator();
|
||||
_ = std.zig.Ast.parse(allocator, source, .zig) catch @panic("parse failure");
|
||||
return fixed_buf_alloc.end_index;
|
||||
|
||||
@ -379,15 +379,18 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {
|
||||
}
|
||||
|
||||
pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
|
||||
var f = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
|
||||
var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
|
||||
else => return null,
|
||||
};
|
||||
defer f.close();
|
||||
defer file.close();
|
||||
|
||||
var buffer: [4096]u8 = undefined; // "flags" lines can get pretty long.
|
||||
var file_reader = file.reader(&buffer);
|
||||
|
||||
const current_arch = builtin.cpu.arch;
|
||||
switch (current_arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => {
|
||||
return ArmCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
|
||||
return ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
|
||||
},
|
||||
.aarch64, .aarch64_be => {
|
||||
const registers = [12]u64{
|
||||
@ -409,13 +412,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
|
||||
return core;
|
||||
},
|
||||
.sparc64 => {
|
||||
return SparcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
|
||||
return SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
|
||||
},
|
||||
.powerpc, .powerpcle, .powerpc64, .powerpc64le => {
|
||||
return PowerpcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
|
||||
return PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
|
||||
},
|
||||
.riscv64, .riscv32 => {
|
||||
return RiscvCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
|
||||
return RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
@ -411,16 +411,22 @@ const Parser = struct {
|
||||
diag: ?*Diagnostics,
|
||||
options: Options,
|
||||
|
||||
fn parseExpr(self: *@This(), T: type, node: Zoir.Node.Index) error{ ParseZon, OutOfMemory }!T {
|
||||
const ParseExprError = error{ ParseZon, OutOfMemory };
|
||||
|
||||
fn parseExpr(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprError!T {
|
||||
return self.parseExprInner(T, node) catch |err| switch (err) {
|
||||
error.WrongType => return self.failExpectedType(T, node),
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
const InnerError = error{ ParseZon, OutOfMemory, WrongType };
|
||||
const ParseExprInnerError = error{ ParseZon, OutOfMemory, WrongType };
|
||||
|
||||
fn parseExprInner(self: *@This(), T: type, node: Zoir.Node.Index) InnerError!T {
|
||||
fn parseExprInner(
|
||||
self: *@This(),
|
||||
T: type,
|
||||
node: Zoir.Node.Index,
|
||||
) ParseExprInnerError!T {
|
||||
if (T == Zoir.Node.Index) {
|
||||
return node;
|
||||
}
|
||||
@ -600,7 +606,7 @@ const Parser = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn parseSlicePointer(self: *@This(), T: type, node: Zoir.Node.Index) InnerError!T {
|
||||
fn parseSlicePointer(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprInnerError!T {
|
||||
switch (node.get(self.zoir)) {
|
||||
.string_literal => return self.parseString(T, node),
|
||||
.array_literal => |nodes| return self.parseSlice(T, nodes),
|
||||
@ -609,19 +615,17 @@ const Parser = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn parseString(self: *@This(), T: type, node: Zoir.Node.Index) InnerError!T {
|
||||
fn parseString(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprInnerError!T {
|
||||
const ast_node = node.getAstNode(self.zoir);
|
||||
const pointer = @typeInfo(T).pointer;
|
||||
var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);
|
||||
if (pointer.sentinel() != null) size_hint += 1;
|
||||
const gpa = self.gpa;
|
||||
|
||||
var aw = try std.io.Writer.Allocating.initCapacity(gpa, size_hint);
|
||||
var aw: std.Io.Writer.Allocating = .init(self.gpa);
|
||||
try aw.ensureUnusedCapacity(size_hint);
|
||||
defer aw.deinit();
|
||||
const parsed = ZonGen.parseStrLit(self.ast, ast_node, &aw.interface) catch |err| switch (err) {
|
||||
error.WriteFailed => return error.OutOfMemory,
|
||||
};
|
||||
switch (parsed) {
|
||||
const result = ZonGen.parseStrLit(self.ast, ast_node, &aw.writer) catch return error.OutOfMemory;
|
||||
switch (result) {
|
||||
.success => {},
|
||||
.failure => |err| {
|
||||
const token = self.ast.nodeMainToken(ast_node);
|
||||
|
||||
@ -687,7 +687,7 @@ pub const Directories = struct {
|
||||
global,
|
||||
},
|
||||
wasi_preopens: switch (builtin.target.os.tag) {
|
||||
.wasi => std.fs.wasi.Preopens,
|
||||
.wasi => fs.wasi.Preopens,
|
||||
else => void,
|
||||
},
|
||||
self_exe_path: switch (builtin.target.os.tag) {
|
||||
@ -744,7 +744,7 @@ pub const Directories = struct {
|
||||
.local_cache = local_cache,
|
||||
};
|
||||
}
|
||||
fn openWasiPreopen(preopens: std.fs.wasi.Preopens, name: []const u8) Cache.Directory {
|
||||
fn openWasiPreopen(preopens: fs.wasi.Preopens, name: []const u8) Cache.Directory {
|
||||
return .{
|
||||
.path = if (std.mem.eql(u8, name, ".")) null else name,
|
||||
.handle = .{
|
||||
@ -758,8 +758,8 @@ pub const Directories = struct {
|
||||
};
|
||||
const nonempty_path = if (path.len == 0) "." else path;
|
||||
const handle_or_err = switch (thing) {
|
||||
.@"zig lib" => std.fs.cwd().openDir(nonempty_path, .{}),
|
||||
.@"global cache", .@"local cache" => std.fs.cwd().makeOpenPath(nonempty_path, .{}),
|
||||
.@"zig lib" => fs.cwd().openDir(nonempty_path, .{}),
|
||||
.@"global cache", .@"local cache" => fs.cwd().makeOpenPath(nonempty_path, .{}),
|
||||
};
|
||||
return .{
|
||||
.path = if (path.len == 0) null else path,
|
||||
@ -996,15 +996,15 @@ pub const CObject = struct {
|
||||
const source_line = source_line: {
|
||||
if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0;
|
||||
|
||||
const file = std.fs.cwd().openFile(file_name, .{}) catch break :source_line 0;
|
||||
const file = fs.cwd().openFile(file_name, .{}) catch break :source_line 0;
|
||||
defer file.close();
|
||||
var buffer: [1 << 10]u8 = undefined;
|
||||
var fr = file.reader(&buffer);
|
||||
fr.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
|
||||
var bw: Writer = .fixed(&buffer);
|
||||
break :source_line try eb.addString(
|
||||
buffer[0 .. fr.interface.readDelimiterEnding(&bw, '\n') catch break :source_line 0],
|
||||
);
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var file_reader = file.reader(&buffer);
|
||||
file_reader.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
|
||||
var aw: Writer.Allocating = .init(eb.gpa);
|
||||
defer aw.deinit();
|
||||
_ = file_reader.interface.streamDelimiterEnding(&aw.writer, '\n') catch break :source_line 0;
|
||||
break :source_line try eb.addString(aw.getWritten());
|
||||
};
|
||||
|
||||
return .{
|
||||
@ -1071,7 +1071,7 @@ pub const CObject = struct {
|
||||
};
|
||||
|
||||
var buffer: [1024]u8 = undefined;
|
||||
const file = try std.fs.cwd().openFile(path, .{});
|
||||
const file = try fs.cwd().openFile(path, .{});
|
||||
defer file.close();
|
||||
var file_reader = file.reader(&buffer);
|
||||
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
|
||||
|
||||
if (options.verbose_llvm_cpu_features) {
|
||||
if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
|
||||
const stderr_bw = std.debug.lockStderrWriter(&.{});
|
||||
const stderr_w = std.debug.lockStderrWriter(&.{});
|
||||
defer std.debug.unlockStderrWriter();
|
||||
stderr_bw.print("compilation: {s}\n", .{options.root_name}) catch break :print;
|
||||
stderr_bw.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
|
||||
stderr_bw.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
|
||||
stderr_bw.print(" features: {s}\n", .{cf}) catch {};
|
||||
stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
|
||||
stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
|
||||
stderr_w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
|
||||
stderr_w.print(" features: {s}\n", .{cf}) catch {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1901,7 +1901,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||
.manifest_dir = try options.dirs.local_cache.handle.makeOpenPath("h", .{}),
|
||||
};
|
||||
// These correspond to std.zig.Server.Message.PathPrefix.
|
||||
cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
|
||||
cache.addPrefix(.{ .path = null, .handle = fs.cwd() });
|
||||
cache.addPrefix(options.dirs.zig_lib);
|
||||
cache.addPrefix(options.dirs.local_cache);
|
||||
cache.addPrefix(options.dirs.global_cache);
|
||||
@ -2192,7 +2192,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||
comp.digest = hash.peekBin();
|
||||
const digest = hash.final();
|
||||
|
||||
const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest;
|
||||
const artifact_sub_dir = "o" ++ fs.path.sep_str ++ digest;
|
||||
var artifact_dir = try options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{});
|
||||
errdefer artifact_dir.close();
|
||||
const artifact_directory: Cache.Directory = .{
|
||||
@ -2483,7 +2483,7 @@ pub fn destroy(comp: *Compilation) void {
|
||||
if (comp.zcu) |zcu| zcu.deinit();
|
||||
comp.cache_use.deinit();
|
||||
|
||||
for (comp.work_queues) |work_queue| work_queue.deinit();
|
||||
for (&comp.work_queues) |*work_queue| work_queue.deinit();
|
||||
comp.c_object_work_queue.deinit();
|
||||
comp.win32_resource_work_queue.deinit();
|
||||
|
||||
@ -2604,11 +2604,11 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
|
||||
// temporary directories; it doesn't have a real cache directory anyway.
|
||||
return;
|
||||
}
|
||||
const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
|
||||
log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
|
||||
comp.dirs.local_cache.path orelse ".",
|
||||
std.fs.path.sep,
|
||||
fs.path.sep,
|
||||
tmp_dir_sub_path,
|
||||
@errorName(err),
|
||||
});
|
||||
@ -2628,11 +2628,11 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
|
||||
if (whole.tmp_artifact_directory) |*tmp_dir| {
|
||||
tmp_dir.handle.close();
|
||||
whole.tmp_artifact_directory = null;
|
||||
const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
|
||||
log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
|
||||
comp.dirs.local_cache.path orelse ".",
|
||||
std.fs.path.sep,
|
||||
fs.path.sep,
|
||||
tmp_dir_sub_path,
|
||||
@errorName(err),
|
||||
});
|
||||
@ -2668,7 +2668,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
assert(none.tmp_artifact_directory == null);
|
||||
none.tmp_artifact_directory = d: {
|
||||
tmp_dir_rand_int = std.crypto.random.int(u64);
|
||||
const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
|
||||
break :d .{
|
||||
.path = path,
|
||||
@ -2735,7 +2735,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
// Compile the artifacts to a temporary directory.
|
||||
whole.tmp_artifact_directory = d: {
|
||||
tmp_dir_rand_int = std.crypto.random.int(u64);
|
||||
const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
|
||||
break :d .{
|
||||
.path = path,
|
||||
@ -2910,7 +2910,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
// Close tmp dir and link.File to avoid open handle during rename.
|
||||
whole.tmp_artifact_directory.?.handle.close();
|
||||
whole.tmp_artifact_directory = null;
|
||||
const s = std.fs.path.sep_str;
|
||||
const s = fs.path.sep_str;
|
||||
const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const o_sub_path = "o" ++ s ++ hex_digest;
|
||||
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 {
|
||||
if (comp.bin_file) |lf| {
|
||||
lf.emit = .{
|
||||
.root_dir = comp.dirs.local_cache,
|
||||
.sub_path = try std.fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
|
||||
.sub_path = try fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
|
||||
};
|
||||
|
||||
switch (need_writable_dance) {
|
||||
@ -3105,7 +3105,7 @@ fn renameTmpIntoCache(
|
||||
) !void {
|
||||
var seen_eaccess = false;
|
||||
while (true) {
|
||||
std.fs.rename(
|
||||
fs.rename(
|
||||
cache_directory.handle,
|
||||
tmp_dir_sub_path,
|
||||
cache_directory.handle,
|
||||
@ -3931,12 +3931,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
|
||||
// This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
|
||||
// However, we haven't reported any such error.
|
||||
// This is a compiler bug.
|
||||
var stderr_bw = std.debug.lockStderrWriter(&.{});
|
||||
var stderr_w = std.debug.lockStderrWriter(&.{});
|
||||
defer std.debug.unlockStderrWriter();
|
||||
try stderr_bw.writeAll("referenced transitive analysis errors, but none actually emitted\n");
|
||||
try stderr_bw.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
|
||||
try stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n");
|
||||
try stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
|
||||
while (ref) |r| {
|
||||
try stderr_bw.print("referenced by: {f}{s}\n", .{
|
||||
try stderr_w.print("referenced by: {f}{s}\n", .{
|
||||
zcu.fmtAnalUnit(r.referencer),
|
||||
if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
|
||||
});
|
||||
@ -4843,7 +4843,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
|
||||
defer out_dir.close();
|
||||
|
||||
for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| {
|
||||
const basename = std.fs.path.basename(sub_path);
|
||||
const basename = fs.path.basename(sub_path);
|
||||
comp.dirs.zig_lib.handle.copyFile(sub_path, out_dir, basename, .{}) catch |err| {
|
||||
comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {s}", .{
|
||||
sub_path,
|
||||
@ -4879,7 +4879,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
|
||||
}
|
||||
}
|
||||
|
||||
fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: std.fs.File) !void {
|
||||
fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: fs.File) !void {
|
||||
const root = module.root;
|
||||
var mod_dir = d: {
|
||||
const root_dir, const sub_path = root.openInfo(comp.dirs);
|
||||
@ -4974,7 +4974,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
|
||||
});
|
||||
|
||||
const src_basename = "main.zig";
|
||||
const root_name = std.fs.path.stem(src_basename);
|
||||
const root_name = fs.path.stem(src_basename);
|
||||
|
||||
const dirs = comp.dirs.withoutLocalCache();
|
||||
|
||||
@ -5069,13 +5069,13 @@ fn workerUpdateFile(
|
||||
prog_node: std.Progress.Node,
|
||||
wg: *WaitGroup,
|
||||
) void {
|
||||
const child_prog_node = prog_node.start(std.fs.path.basename(file.path.sub_path), 0);
|
||||
const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0);
|
||||
defer child_prog_node.end();
|
||||
|
||||
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
pt.updateFile(file_index, file) catch |err| {
|
||||
pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
|
||||
pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
|
||||
error.OutOfMemory => {
|
||||
comp.mutex.lock();
|
||||
defer comp.mutex.unlock();
|
||||
@ -5240,7 +5240,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const tmp_digest = man.hash.peek();
|
||||
const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });
|
||||
const tmp_dir_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });
|
||||
var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
|
||||
defer zig_cache_tmp_dir.close();
|
||||
const cimport_basename = "cimport.h";
|
||||
@ -5309,7 +5309,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
|
||||
log.info("C import .d file: {s}", .{out_dep_path});
|
||||
}
|
||||
|
||||
const dep_basename = std.fs.path.basename(out_dep_path);
|
||||
const dep_basename = fs.path.basename(out_dep_path);
|
||||
try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
|
||||
switch (comp.cache_use) {
|
||||
.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
|
||||
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest;
|
||||
const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
|
||||
var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
|
||||
var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{});
|
||||
defer out_zig_file.close();
|
||||
|
||||
const formatted = try tree.render(comp.gpa);
|
||||
const formatted = try tree.renderAlloc(comp.gpa);
|
||||
defer comp.gpa.free(formatted);
|
||||
|
||||
try out_zig_file.writeAll(formatted);
|
||||
@ -5675,7 +5675,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const c_source_basename = std.fs.path.basename(c_object.src.src_path);
|
||||
const c_source_basename = fs.path.basename(c_object.src.src_path);
|
||||
|
||||
const child_progress_node = c_obj_prog_node.start(c_source_basename, 0);
|
||||
defer child_progress_node.end();
|
||||
@ -5688,7 +5688,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
|
||||
const o_basename_noext = if (direct_o)
|
||||
comp.root_name
|
||||
else
|
||||
c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len];
|
||||
c_source_basename[0 .. c_source_basename.len - fs.path.extension(c_source_basename).len];
|
||||
|
||||
const target = comp.getTarget();
|
||||
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
|
||||
}
|
||||
|
||||
// Just to save disk space, we delete the files that are never needed again.
|
||||
defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(std.fs.path.basename(diag_file_path)) catch |err| switch (err) {
|
||||
defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(diag_file_path)) catch |err| switch (err) {
|
||||
error.FileNotFound => {}, // the file wasn't created due to an error we reported
|
||||
else => log.warn("failed to delete '{s}': {s}", .{ diag_file_path, @errorName(err) }),
|
||||
};
|
||||
defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(std.fs.path.basename(dep_file_path)) catch |err| switch (err) {
|
||||
defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(dep_file_path)) catch |err| switch (err) {
|
||||
error.FileNotFound => {}, // the file wasn't created due to an error we reported
|
||||
else => log.warn("failed to delete '{s}': {s}", .{ dep_file_path, @errorName(err) }),
|
||||
};
|
||||
@ -5890,7 +5890,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
|
||||
}
|
||||
|
||||
if (out_dep_path) |dep_file_path| {
|
||||
const dep_basename = std.fs.path.basename(dep_file_path);
|
||||
const dep_basename = fs.path.basename(dep_file_path);
|
||||
// Add the files depended on to the cache system.
|
||||
try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
|
||||
switch (comp.cache_use) {
|
||||
@ -5910,11 +5910,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
|
||||
|
||||
// Rename into place.
|
||||
const digest = man.final();
|
||||
const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
const tmp_basename = std.fs.path.basename(out_obj_path);
|
||||
try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename);
|
||||
const tmp_basename = fs.path.basename(out_obj_path);
|
||||
try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename);
|
||||
break :blk digest;
|
||||
};
|
||||
|
||||
@ -5936,7 +5936,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
|
||||
.success = .{
|
||||
.object_path = .{
|
||||
.root_dir = comp.dirs.local_cache,
|
||||
.sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, o_basename }),
|
||||
.sub_path = try fs.path.join(gpa, &.{ "o", &digest, o_basename }),
|
||||
},
|
||||
.lock = man.toOwnedLock(),
|
||||
},
|
||||
@ -5960,7 +5960,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
||||
.rc => |rc_src| rc_src.src_path,
|
||||
.manifest => |src_path| src_path,
|
||||
};
|
||||
const src_basename = std.fs.path.basename(src_path);
|
||||
const src_basename = fs.path.basename(src_path);
|
||||
|
||||
log.debug("updating win32 resource: {s}", .{src_path});
|
||||
|
||||
@ -5997,7 +5997,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
||||
// get the digest now and write the .res directly to the cache
|
||||
const digest = man.final();
|
||||
|
||||
const o_sub_path = try std.fs.path.join(arena, &.{ "o", &digest });
|
||||
const o_sub_path = try fs.path.join(arena, &.{ "o", &digest });
|
||||
var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
|
||||
@ -6083,7 +6083,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
||||
_ = try man.addFile(rc_src.src_path, null);
|
||||
man.hash.addListOfBytes(rc_src.extra_flags);
|
||||
|
||||
const rc_basename_noext = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
|
||||
const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];
|
||||
|
||||
const digest = if (try man.hit()) man.final() else blk: {
|
||||
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
|
||||
|
||||
// Read depfile and update cache manifest
|
||||
{
|
||||
const dep_basename = std.fs.path.basename(out_dep_path);
|
||||
const dep_basename = fs.path.basename(out_dep_path);
|
||||
const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(arena, dep_basename, 50 * 1024 * 1024);
|
||||
defer arena.free(dep_file_contents);
|
||||
|
||||
@ -6156,11 +6156,11 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
||||
|
||||
// Rename into place.
|
||||
const digest = man.final();
|
||||
const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
const tmp_basename = std.fs.path.basename(out_res_path);
|
||||
try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename);
|
||||
const tmp_basename = fs.path.basename(out_res_path);
|
||||
try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename);
|
||||
break :blk digest;
|
||||
};
|
||||
|
||||
@ -6268,7 +6268,7 @@ fn spawnZigRc(
|
||||
}
|
||||
|
||||
pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
|
||||
const s = std.fs.path.sep_str;
|
||||
const s = fs.path.sep_str;
|
||||
const rand_int = std.crypto.random.int(u64);
|
||||
if (comp.dirs.local_cache.path) |p| {
|
||||
return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
|
||||
@ -6518,12 +6518,12 @@ pub fn addCCArgs(
|
||||
|
||||
if (comp.config.link_libcpp) {
|
||||
try argv.append("-isystem");
|
||||
try argv.append(try std.fs.path.join(arena, &[_][]const u8{
|
||||
try argv.append(try fs.path.join(arena, &[_][]const u8{
|
||||
comp.dirs.zig_lib.path.?, "libcxx", "include",
|
||||
}));
|
||||
|
||||
try argv.append("-isystem");
|
||||
try argv.append(try std.fs.path.join(arena, &[_][]const u8{
|
||||
try argv.append(try fs.path.join(arena, &[_][]const u8{
|
||||
comp.dirs.zig_lib.path.?, "libcxxabi", "include",
|
||||
}));
|
||||
|
||||
@ -6534,7 +6534,7 @@ pub fn addCCArgs(
|
||||
// However as noted by @dimenus, appending libc headers before compiler headers breaks
|
||||
// intrinsics and other compiler specific items.
|
||||
try argv.append("-isystem");
|
||||
try argv.append(try std.fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "include" }));
|
||||
try argv.append(try fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "include" }));
|
||||
|
||||
try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);
|
||||
for (comp.libc_include_dir_list) |include_dir| {
|
||||
@ -6552,7 +6552,7 @@ pub fn addCCArgs(
|
||||
|
||||
if (comp.config.link_libunwind) {
|
||||
try argv.append("-isystem");
|
||||
try argv.append(try std.fs.path.join(arena, &[_][]const u8{
|
||||
try argv.append(try fs.path.join(arena, &[_][]const u8{
|
||||
comp.dirs.zig_lib.path.?, "libunwind", "include",
|
||||
}));
|
||||
}
|
||||
@ -7145,7 +7145,7 @@ fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8)
|
||||
return (try crtFilePath(&comp.crt_files, basename)) orelse {
|
||||
const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable;
|
||||
const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir;
|
||||
const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename });
|
||||
const full_path = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename });
|
||||
return Cache.Path.initCwd(full_path);
|
||||
};
|
||||
}
|
||||
@ -7207,13 +7207,15 @@ pub fn lockAndSetMiscFailure(
|
||||
}
|
||||
|
||||
pub fn dump_argv(argv: []const []const u8) void {
|
||||
var stderr = std.debug.lockStdErr2(&.{});
|
||||
defer std.debug.unlockStdErr();
|
||||
var buffer: [64]u8 = undefined;
|
||||
const stderr = std.debug.lockStderrWriter(&buffer);
|
||||
defer std.debug.unlockStderrWriter();
|
||||
nosuspend {
|
||||
for (argv[0 .. argv.len - 1]) |arg| {
|
||||
stderr.print("{s} ", .{arg}) catch return;
|
||||
for (argv) |arg| {
|
||||
stderr.writeAll(arg) catch return;
|
||||
(stderr.writableArray(1) catch return)[0] = ' ';
|
||||
}
|
||||
stderr.print("{s}\n", .{argv[argv.len - 1]}) catch {};
|
||||
stderr.buffer[stderr.end - 1] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@ -7541,7 +7543,7 @@ pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {
|
||||
return .{
|
||||
.full_object_path = .{
|
||||
.root_dir = comp.dirs.local_cache,
|
||||
.sub_path = try std.fs.path.join(comp.gpa, &.{
|
||||
.sub_path = try fs.path.join(comp.gpa, &.{
|
||||
"o",
|
||||
&Cache.binToHex(comp.digest.?),
|
||||
comp.emit_bin.?,
|
||||
|
||||
@ -471,10 +471,14 @@ const Parse = struct {
|
||||
offset: u32,
|
||||
) InnerError!void {
|
||||
const raw_string = bytes[offset..];
|
||||
var aw: std.io.Writer.Allocating = .fromArrayList(p.gpa, buf);
|
||||
const result = std.zig.string_literal.parseWrite(&aw.interface, raw_string);
|
||||
buf.* = aw.toArrayList();
|
||||
switch (result catch return error.OutOfMemory) {
|
||||
const result = r: {
|
||||
var aw: std.io.Writer.Allocating = .fromArrayList(p.gpa, buf);
|
||||
defer buf.* = aw.toArrayList();
|
||||
break :r std.zig.string_literal.parseWrite(&aw.writer, raw_string) catch |err| switch (err) {
|
||||
error.WriteFailed => return error.OutOfMemory,
|
||||
};
|
||||
};
|
||||
switch (result) {
|
||||
.success => {},
|
||||
.failure => |err| try p.appendStrLitError(err, token, bytes, offset),
|
||||
}
|
||||
|
||||
@ -52,15 +52,6 @@ pub fn LinearFifo(comptime T: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reduce allocated capacity to `size`.
|
||||
pub fn shrink(self: *Self, size: usize) void {
|
||||
assert(size >= self.count);
|
||||
self.realign();
|
||||
self.buf = self.allocator.realloc(self.buf, size) catch |e| switch (e) {
|
||||
error.OutOfMemory => return, // no problem, capacity is still correct then.
|
||||
};
|
||||
}
|
||||
|
||||
/// Ensure that the buffer can fit at least `size` items
|
||||
pub fn ensureTotalCapacity(self: *Self, size: usize) !void {
|
||||
if (self.buf.len >= size) return;
|
||||
@ -76,11 +67,6 @@ pub fn LinearFifo(comptime T: type) type {
|
||||
return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory);
|
||||
}
|
||||
|
||||
/// Returns number of items currently in fifo
|
||||
pub fn readableLength(self: Self) usize {
|
||||
return self.count;
|
||||
}
|
||||
|
||||
/// Returns a writable slice from the 'read' end of the fifo
|
||||
fn readableSliceMut(self: Self, offset: usize) []T {
|
||||
if (offset > self.count) return &[_]T{};
|
||||
@ -95,22 +81,6 @@ pub fn LinearFifo(comptime T: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a readable slice from `offset`
|
||||
pub fn readableSlice(self: Self, offset: usize) []const T {
|
||||
return self.readableSliceMut(offset);
|
||||
}
|
||||
|
||||
pub fn readableSliceOfLen(self: *Self, len: usize) []const T {
|
||||
assert(len <= self.count);
|
||||
const buf = self.readableSlice(0);
|
||||
if (buf.len >= len) {
|
||||
return buf[0..len];
|
||||
} else {
|
||||
self.realign();
|
||||
return self.readableSlice(0)[0..len];
|
||||
}
|
||||
}
|
||||
|
||||
/// Discard first `count` items in the fifo
|
||||
pub fn discard(self: *Self, count: usize) void {
|
||||
assert(count <= self.count);
|
||||
@ -143,28 +113,6 @@ pub fn LinearFifo(comptime T: type) type {
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Read data from the fifo into `dst`, returns number of items copied.
|
||||
pub fn read(self: *Self, dst: []T) usize {
|
||||
var dst_left = dst;
|
||||
|
||||
while (dst_left.len > 0) {
|
||||
const slice = self.readableSlice(0);
|
||||
if (slice.len == 0) break;
|
||||
const n = @min(slice.len, dst_left.len);
|
||||
@memcpy(dst_left[0..n], slice[0..n]);
|
||||
self.discard(n);
|
||||
dst_left = dst_left[n..];
|
||||
}
|
||||
|
||||
return dst.len - dst_left.len;
|
||||
}
|
||||
|
||||
/// Same as `read` except it returns an error union
|
||||
/// The purpose of this function existing is to match `std.io.GenericReader` API.
|
||||
fn readFn(self: *Self, dest: []u8) error{}!usize {
|
||||
return self.read(dest);
|
||||
}
|
||||
|
||||
/// Returns number of items available in fifo
|
||||
pub fn writableLength(self: Self) usize {
|
||||
return self.buf.len - self.count;
|
||||
@ -183,20 +131,6 @@ pub fn LinearFifo(comptime T: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a writable buffer of at least `size` items, allocating memory as needed.
|
||||
/// Use `fifo.update` once you've written data to it.
|
||||
pub fn writableWithSize(self: *Self, size: usize) ![]T {
|
||||
try self.ensureUnusedCapacity(size);
|
||||
|
||||
// try to avoid realigning buffer
|
||||
var slice = self.writableSlice(0);
|
||||
if (slice.len < size) {
|
||||
self.realign();
|
||||
slice = self.writableSlice(0);
|
||||
}
|
||||
return slice;
|
||||
}
|
||||
|
||||
/// Update the tail location of the buffer (usually follows use of writable/writableWithSize)
|
||||
pub fn update(self: *Self, count: usize) void {
|
||||
assert(self.count + count <= self.buf.len);
|
||||
@ -231,201 +165,5 @@ pub fn LinearFifo(comptime T: type) type {
|
||||
self.buf[tail] = item;
|
||||
self.update(1);
|
||||
}
|
||||
|
||||
/// Appends the data in `src` to the fifo.
|
||||
/// Allocates more memory as necessary
|
||||
pub fn write(self: *Self, src: []const T) !void {
|
||||
try self.ensureUnusedCapacity(src.len);
|
||||
|
||||
return self.writeAssumeCapacity(src);
|
||||
}
|
||||
|
||||
/// Same as `write` except it returns the number of bytes written, which is always the same
|
||||
/// as `bytes.len`. The purpose of this function existing is to match `std.io.GenericWriter` API.
|
||||
fn appendWrite(self: *Self, bytes: []const u8) error{OutOfMemory}!usize {
|
||||
try self.write(bytes);
|
||||
return bytes.len;
|
||||
}
|
||||
|
||||
/// Make `count` items available before the current read location
|
||||
fn rewind(self: *Self, count: usize) void {
|
||||
assert(self.writableLength() >= count);
|
||||
|
||||
var head = self.head + (self.buf.len - count);
|
||||
head &= self.buf.len - 1;
|
||||
self.head = head;
|
||||
self.count += count;
|
||||
}
|
||||
|
||||
/// Place data back into the read stream
|
||||
pub fn unget(self: *Self, src: []const T) !void {
|
||||
try self.ensureUnusedCapacity(src.len);
|
||||
|
||||
self.rewind(src.len);
|
||||
|
||||
const slice = self.readableSliceMut(0);
|
||||
if (src.len < slice.len) {
|
||||
@memcpy(slice[0..src.len], src);
|
||||
} else {
|
||||
@memcpy(slice, src[0..slice.len]);
|
||||
const slice2 = self.readableSliceMut(slice.len);
|
||||
@memcpy(slice2[0 .. src.len - slice.len], src[slice.len..]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the item at `offset`.
|
||||
/// Asserts offset is within bounds.
|
||||
pub fn peekItem(self: Self, offset: usize) T {
|
||||
assert(offset < self.count);
|
||||
|
||||
var index = self.head + offset;
|
||||
index &= self.buf.len - 1;
|
||||
return self.buf[index];
|
||||
}
|
||||
|
||||
pub fn toOwnedSlice(self: *Self) Allocator.Error![]T {
|
||||
if (self.head != 0) self.realign();
|
||||
assert(self.head == 0);
|
||||
assert(self.count <= self.buf.len);
|
||||
const allocator = self.allocator;
|
||||
if (allocator.resize(self.buf, self.count)) {
|
||||
const result = self.buf[0..self.count];
|
||||
self.* = Self.init(allocator);
|
||||
return result;
|
||||
}
|
||||
const new_memory = try allocator.dupe(T, self.buf[0..self.count]);
|
||||
allocator.free(self.buf);
|
||||
self.* = Self.init(allocator);
|
||||
return new_memory;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "LinearFifo(u8, .Dynamic) discard(0) from empty buffer should not error on overflow" {
|
||||
var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
|
||||
defer fifo.deinit();
|
||||
|
||||
// If overflow is not explicitly allowed this will crash in debug / safe mode
|
||||
fifo.discard(0);
|
||||
}
|
||||
|
||||
test "LinearFifo(u8, .Dynamic)" {
|
||||
var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
|
||||
defer fifo.deinit();
|
||||
|
||||
try fifo.write("HELLO");
|
||||
try testing.expectEqual(@as(usize, 5), fifo.readableLength());
|
||||
try testing.expectEqualSlices(u8, "HELLO", fifo.readableSlice(0));
|
||||
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < 5) : (i += 1) {
|
||||
try fifo.write(&[_]u8{fifo.peekItem(i)});
|
||||
}
|
||||
try testing.expectEqual(@as(usize, 10), fifo.readableLength());
|
||||
try testing.expectEqualSlices(u8, "HELLOHELLO", fifo.readableSlice(0));
|
||||
}
|
||||
|
||||
{
|
||||
try testing.expectEqual(@as(u8, 'H'), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(u8, 'E'), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(u8, 'L'), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(u8, 'L'), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(u8, 'O'), fifo.readItem().?);
|
||||
}
|
||||
try testing.expectEqual(@as(usize, 5), fifo.readableLength());
|
||||
|
||||
{ // Writes that wrap around
|
||||
try testing.expectEqual(@as(usize, 11), fifo.writableLength());
|
||||
try testing.expectEqual(@as(usize, 6), fifo.writableSlice(0).len);
|
||||
fifo.writeAssumeCapacity("6<chars<11");
|
||||
try testing.expectEqualSlices(u8, "HELLO6<char", fifo.readableSlice(0));
|
||||
try testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(11));
|
||||
try testing.expectEqualSlices(u8, "11", fifo.readableSlice(13));
|
||||
try testing.expectEqualSlices(u8, "", fifo.readableSlice(15));
|
||||
fifo.discard(11);
|
||||
try testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(0));
|
||||
fifo.discard(4);
|
||||
try testing.expectEqual(@as(usize, 0), fifo.readableLength());
|
||||
}
|
||||
|
||||
{
|
||||
const buf = try fifo.writableWithSize(12);
|
||||
try testing.expectEqual(@as(usize, 12), buf.len);
|
||||
var i: u8 = 0;
|
||||
while (i < 10) : (i += 1) {
|
||||
buf[i] = i + 'a';
|
||||
}
|
||||
fifo.update(10);
|
||||
try testing.expectEqualSlices(u8, "abcdefghij", fifo.readableSlice(0));
|
||||
}
|
||||
|
||||
{
|
||||
try fifo.unget("prependedstring");
|
||||
var result: [30]u8 = undefined;
|
||||
try testing.expectEqualSlices(u8, "prependedstringabcdefghij", result[0..fifo.read(&result)]);
|
||||
try fifo.unget("b");
|
||||
try fifo.unget("a");
|
||||
try testing.expectEqualSlices(u8, "ab", result[0..fifo.read(&result)]);
|
||||
}
|
||||
|
||||
fifo.shrink(0);
|
||||
|
||||
{
|
||||
try fifo.writer().print("{s}, {s}!", .{ "Hello", "World" });
|
||||
var result: [30]u8 = undefined;
|
||||
try testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);
|
||||
try testing.expectEqual(@as(usize, 0), fifo.readableLength());
|
||||
}
|
||||
|
||||
{
|
||||
try fifo.writer().writeAll("This is a test");
|
||||
var result: [30]u8 = undefined;
|
||||
try testing.expectEqualSlices(u8, "This", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
|
||||
try testing.expectEqualSlices(u8, "is", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
|
||||
try testing.expectEqualSlices(u8, "a", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
|
||||
try testing.expectEqualSlices(u8, "test", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
|
||||
}
|
||||
|
||||
{
|
||||
try fifo.ensureTotalCapacity(1);
|
||||
var in_fbs = std.io.fixedBufferStream("pump test");
|
||||
var out_buf: [50]u8 = undefined;
|
||||
var out_fbs = std.io.fixedBufferStream(&out_buf);
|
||||
try fifo.pump(in_fbs.reader(), out_fbs.writer());
|
||||
try testing.expectEqualSlices(u8, in_fbs.buffer, out_fbs.getWritten());
|
||||
}
|
||||
}
|
||||
|
||||
test LinearFifo {
|
||||
inline for ([_]type{ u1, u8, u16, u64 }) |T| {
|
||||
const FifoType = LinearFifo(T);
|
||||
var fifo: FifoType = .init(testing.allocator);
|
||||
defer fifo.deinit();
|
||||
|
||||
try fifo.write(&[_]T{ 0, 1, 1, 0, 1 });
|
||||
try testing.expectEqual(@as(usize, 5), fifo.readableLength());
|
||||
|
||||
{
|
||||
try testing.expectEqual(@as(T, 0), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(T, 1), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(T, 1), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(T, 0), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(T, 1), fifo.readItem().?);
|
||||
try testing.expectEqual(@as(usize, 0), fifo.readableLength());
|
||||
}
|
||||
|
||||
{
|
||||
try fifo.writeItem(1);
|
||||
try fifo.writeItem(1);
|
||||
try fifo.writeItem(1);
|
||||
try testing.expectEqual(@as(usize, 3), fifo.readableLength());
|
||||
}
|
||||
|
||||
{
|
||||
var readBuf: [3]T = undefined;
|
||||
const n = fifo.read(&readBuf);
|
||||
try testing.expectEqual(@as(usize, 3), n); // NOTE: It should be the number of items.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
60
src/fmt.zig
60
src/fmt.zig
@ -35,8 +35,8 @@ const Fmt = struct {
|
||||
color: Color,
|
||||
gpa: Allocator,
|
||||
arena: Allocator,
|
||||
out_buffer: std.ArrayListUnmanaged(u8),
|
||||
stdout_writer: *File.Writer,
|
||||
out_buffer: std.Io.Writer.Allocating,
|
||||
stdout_writer: *fs.File.Writer,
|
||||
|
||||
const SeenMap = std.AutoHashMap(fs.File.INode, void);
|
||||
};
|
||||
@ -58,7 +58,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
const arg = args[i];
|
||||
if (mem.startsWith(u8, arg, "-")) {
|
||||
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
||||
try File.stdout().writeAll(usage_fmt);
|
||||
try fs.File.stdout().writeAll(usage_fmt);
|
||||
return process.cleanExit();
|
||||
} else if (mem.eql(u8, arg, "--color")) {
|
||||
if (i + 1 >= args.len) {
|
||||
@ -98,7 +98,10 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
fatal("cannot use --stdin with positional arguments", .{});
|
||||
}
|
||||
|
||||
const source_code = std.zig.readSourceFileToEndAlloc(gpa, .stdin(), 0) catch |err| {
|
||||
const stdin: fs.File = .stdin();
|
||||
var stdio_buffer: [1024]u8 = undefined;
|
||||
var file_reader: fs.File.Reader = stdin.reader(&stdio_buffer);
|
||||
const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| {
|
||||
fatal("unable to read stdin: {}", .{err});
|
||||
};
|
||||
defer gpa.free(source_code);
|
||||
@ -142,17 +145,15 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
try std.zig.printAstErrorsToStderr(gpa, tree, "<stdin>", color);
|
||||
process.exit(2);
|
||||
}
|
||||
var aw: std.io.Writer.Allocating = .init(gpa);
|
||||
defer aw.deinit();
|
||||
try tree.render(gpa, &aw.interface, .{});
|
||||
const formatted = aw.getWritten();
|
||||
const formatted = try tree.renderAlloc(gpa);
|
||||
defer gpa.free(formatted);
|
||||
|
||||
if (check_flag) {
|
||||
const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code));
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
return File.stdout().writeAll(formatted);
|
||||
return fs.File.stdout().writeAll(formatted);
|
||||
}
|
||||
|
||||
if (input_files.items.len == 0) {
|
||||
@ -160,7 +161,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
}
|
||||
|
||||
var stdout_buffer: [4096]u8 = undefined;
|
||||
var stdout_writer = File.stdout().writer(&stdout_buffer);
|
||||
var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
|
||||
|
||||
var fmt: Fmt = .{
|
||||
.gpa = gpa,
|
||||
@ -170,7 +171,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
.check_ast = check_ast_flag,
|
||||
.force_zon = force_zon,
|
||||
.color = color,
|
||||
.out_buffer = .empty,
|
||||
.out_buffer = .init(gpa),
|
||||
.stdout_writer = &stdout_writer,
|
||||
};
|
||||
defer fmt.seen.deinit();
|
||||
@ -198,10 +199,10 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
if (fmt.any_error) {
|
||||
process.exit(1);
|
||||
}
|
||||
try fmt.stdout_writer.flush();
|
||||
try fmt.stdout_writer.interface.flush();
|
||||
}
|
||||
|
||||
fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) anyerror!void {
|
||||
fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) !void {
|
||||
fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {
|
||||
error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),
|
||||
else => {
|
||||
@ -218,7 +219,7 @@ fn fmtPathDir(
|
||||
check_mode: bool,
|
||||
parent_dir: fs.Dir,
|
||||
parent_sub_path: []const u8,
|
||||
) anyerror!void {
|
||||
) !void {
|
||||
var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });
|
||||
defer dir.close();
|
||||
|
||||
@ -254,7 +255,7 @@ fn fmtPathFile(
|
||||
check_mode: bool,
|
||||
dir: fs.Dir,
|
||||
sub_path: []const u8,
|
||||
) anyerror!void {
|
||||
) !void {
|
||||
const source_file = try dir.openFile(sub_path, .{});
|
||||
var file_closed = false;
|
||||
errdefer if (!file_closed) source_file.close();
|
||||
@ -264,12 +265,15 @@ fn fmtPathFile(
|
||||
if (stat.kind == .directory)
|
||||
return error.IsDir;
|
||||
|
||||
var read_buffer: [1024]u8 = undefined;
|
||||
var file_reader: fs.File.Reader = source_file.reader(&read_buffer);
|
||||
file_reader.size = stat.size;
|
||||
|
||||
const gpa = fmt.gpa;
|
||||
const source_code = try std.zig.readSourceFileToEndAlloc(
|
||||
gpa,
|
||||
source_file,
|
||||
std.math.cast(usize, stat.size) orelse return error.FileTooBig,
|
||||
);
|
||||
const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| switch (err) {
|
||||
error.ReadFailed => return file_reader.err.?,
|
||||
else => |e| return e,
|
||||
};
|
||||
defer gpa.free(source_code);
|
||||
|
||||
source_file.close();
|
||||
@ -332,15 +336,13 @@ fn fmtPathFile(
|
||||
}
|
||||
|
||||
// As a heuristic, we make enough capacity for the same as the input source.
|
||||
fmt.out_buffer.shrinkRetainingCapacity(0);
|
||||
try fmt.out_buffer.ensureTotalCapacity(gpa, source_code.len);
|
||||
fmt.out_buffer.clearRetainingCapacity();
|
||||
try fmt.out_buffer.ensureTotalCapacity(source_code.len);
|
||||
|
||||
{
|
||||
var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &fmt.out_buffer);
|
||||
defer fmt.out_buffer = aw.toArrayList();
|
||||
try tree.render(gpa, &aw.interface, .{});
|
||||
}
|
||||
if (mem.eql(u8, fmt.out_buffer.items, source_code))
|
||||
tree.render(gpa, &fmt.out_buffer.writer, .{}) catch |err| switch (err) {
|
||||
error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
|
||||
};
|
||||
if (mem.eql(u8, fmt.out_buffer.getWritten(), source_code))
|
||||
return;
|
||||
|
||||
if (check_mode) {
|
||||
@ -350,7 +352,7 @@ fn fmtPathFile(
|
||||
var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });
|
||||
defer af.deinit();
|
||||
|
||||
try af.file.writeAll(fmt.out_buffer.items);
|
||||
try af.file.writeAll(fmt.out_buffer.getWritten());
|
||||
try af.finish();
|
||||
try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
|
||||
}
|
||||
|
||||
@ -205,7 +205,6 @@ pub fn createEmpty(
|
||||
const target = &comp.root_mod.resolved_target.result;
|
||||
const output_mode = comp.config.output_mode;
|
||||
const optimize_mode = comp.root_mod.optimize_mode;
|
||||
const is_native_os = comp.root_mod.resolved_target.is_native_os;
|
||||
|
||||
const obj_file_ext: []const u8 = switch (target.ofmt) {
|
||||
.coff => "obj",
|
||||
@ -234,7 +233,7 @@ pub fn createEmpty(
|
||||
.gc_sections = gc_sections,
|
||||
.print_gc_sections = options.print_gc_sections,
|
||||
.stack_size = stack_size,
|
||||
.allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
|
||||
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
|
||||
.file = null,
|
||||
.build_id = options.build_id,
|
||||
},
|
||||
|
||||
45
src/main.zig
45
src/main.zig
@ -65,8 +65,10 @@ pub fn wasi_cwd() std.os.wasi.fd_t {
|
||||
|
||||
const fatal = std.process.fatal;
|
||||
|
||||
/// This can be global since stdin is a singleton.
|
||||
var stdin_buffer: [4096]u8 align(std.heap.page_size_min) = undefined;
|
||||
/// This can be global since stdout is a singleton.
|
||||
var stdio_buffer: [4096]u8 = undefined;
|
||||
var stdout_buffer: [4096]u8 align(std.heap.page_size_min) = undefined;
|
||||
|
||||
/// Shaming all the locations that inappropriately use an O(N) search algorithm.
|
||||
/// Please delete this and fix the compilation errors!
|
||||
@ -3561,10 +3563,12 @@ fn buildOutputType(
|
||||
switch (listen) {
|
||||
.none => {},
|
||||
.stdio => {
|
||||
var stdin_reader = fs.File.stdin().reader(&stdin_buffer);
|
||||
var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
|
||||
try serve(
|
||||
comp,
|
||||
.stdin(),
|
||||
.stdout(),
|
||||
&stdin_reader.interface,
|
||||
&stdout_writer.interface,
|
||||
test_exec_args.items,
|
||||
self_exe_path,
|
||||
arg_mode,
|
||||
@ -3584,10 +3588,13 @@ fn buildOutputType(
|
||||
const conn = try server.accept();
|
||||
defer conn.stream.close();
|
||||
|
||||
var input = conn.stream.reader(&stdin_buffer);
|
||||
var output = conn.stream.writer(&stdout_buffer);
|
||||
|
||||
try serve(
|
||||
comp,
|
||||
.{ .handle = conn.stream.handle },
|
||||
.{ .handle = conn.stream.handle },
|
||||
input.interface(),
|
||||
&output.interface,
|
||||
test_exec_args.items,
|
||||
self_exe_path,
|
||||
arg_mode,
|
||||
@ -4053,8 +4060,8 @@ fn saveState(comp: *Compilation, incremental: bool) void {
|
||||
|
||||
fn serve(
|
||||
comp: *Compilation,
|
||||
in: fs.File,
|
||||
out: fs.File,
|
||||
in: *std.Io.Reader,
|
||||
out: *std.Io.Writer,
|
||||
test_exec_args: []const ?[]const u8,
|
||||
self_exe_path: ?[]const u8,
|
||||
arg_mode: ArgMode,
|
||||
@ -4064,12 +4071,10 @@ fn serve(
|
||||
const gpa = comp.gpa;
|
||||
|
||||
var server = try Server.init(.{
|
||||
.gpa = gpa,
|
||||
.in = in,
|
||||
.out = out,
|
||||
.zig_version = build_options.version,
|
||||
});
|
||||
defer server.deinit();
|
||||
|
||||
var child_pid: ?std.process.Child.Id = null;
|
||||
|
||||
@ -5491,10 +5496,10 @@ fn jitCmd(
|
||||
defer comp.destroy();
|
||||
|
||||
if (options.server) {
|
||||
var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
|
||||
var server: std.zig.Server = .{
|
||||
.out = fs.File.stdout(),
|
||||
.out = &stdout_writer.interface,
|
||||
.in = undefined, // won't be receiving messages
|
||||
.receive_fifo = undefined, // won't be receiving messages
|
||||
};
|
||||
|
||||
try comp.update(root_prog_node);
|
||||
@ -6058,7 +6063,7 @@ fn cmdAstCheck(
|
||||
};
|
||||
} else fs.File.stdin();
|
||||
defer if (zig_source_path != null) f.close();
|
||||
var file_reader: fs.File.Reader = f.reader(&stdio_buffer);
|
||||
var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
|
||||
break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| {
|
||||
fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
|
||||
};
|
||||
@ -6076,7 +6081,7 @@ fn cmdAstCheck(
|
||||
|
||||
const tree = try Ast.parse(arena, source, mode);
|
||||
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
|
||||
const stdout_bw = &stdout_writer.interface;
|
||||
switch (mode) {
|
||||
.zig => {
|
||||
@ -6291,7 +6296,7 @@ fn detectNativeCpuWithLLVM(
|
||||
}
|
||||
|
||||
fn printCpu(cpu: std.Target.Cpu) !void {
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
|
||||
const stdout_bw = &stdout_writer.interface;
|
||||
|
||||
if (cpu.model.llvm_name) |llvm_name| {
|
||||
@ -6340,7 +6345,7 @@ fn cmdDumpLlvmInts(
|
||||
const dl = tm.createTargetDataLayout();
|
||||
const context = llvm.Context.create();
|
||||
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
|
||||
const stdout_bw = &stdout_writer.interface;
|
||||
for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
|
||||
const int_type = context.intType(bits);
|
||||
@ -6369,7 +6374,7 @@ fn cmdDumpZir(
|
||||
defer f.close();
|
||||
|
||||
const zir = try Zcu.loadZirCache(arena, f);
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
|
||||
const stdout_bw = &stdout_writer.interface;
|
||||
{
|
||||
const instruction_bytes = zir.instructions.len *
|
||||
@ -6416,7 +6421,7 @@ fn cmdChangelist(
|
||||
var f = fs.cwd().openFile(old_source_path, .{}) catch |err|
|
||||
fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
|
||||
defer f.close();
|
||||
var file_reader: fs.File.Reader = f.reader(&stdio_buffer);
|
||||
var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
|
||||
break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|
|
||||
fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
|
||||
};
|
||||
@ -6424,7 +6429,7 @@ fn cmdChangelist(
|
||||
var f = fs.cwd().openFile(new_source_path, .{}) catch |err|
|
||||
fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
|
||||
defer f.close();
|
||||
var file_reader: fs.File.Reader = f.reader(&stdio_buffer);
|
||||
var file_reader: fs.File.Reader = f.reader(&stdin_buffer);
|
||||
break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err|
|
||||
fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
|
||||
};
|
||||
@ -6456,7 +6461,7 @@ fn cmdChangelist(
|
||||
var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
|
||||
try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
|
||||
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
|
||||
var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
|
||||
const stdout_bw = &stdout_writer.interface;
|
||||
{
|
||||
try stdout_bw.print("Instruction mappings:\n", .{});
|
||||
@ -6916,7 +6921,7 @@ fn cmdFetch(
|
||||
|
||||
const name = switch (save) {
|
||||
.no => {
|
||||
var stdout = fs.File.stdout().writerStreaming(&stdio_buffer);
|
||||
var stdout = fs.File.stdout().writerStreaming(&stdout_buffer);
|
||||
try stdout.interface.print("{s}\n", .{package_hash_slice});
|
||||
try stdout.interface.flush();
|
||||
return cleanExit();
|
||||
|
||||
128
test/cases/compile_errors/@import_zon_bad_type.zig
Normal file
128
test/cases/compile_errors/@import_zon_bad_type.zig
Normal file
@ -0,0 +1,128 @@
|
||||
export fn testVoid() void {
|
||||
const f: void = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testInStruct() void {
|
||||
const f: struct { f: [*]const u8 } = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testError() void {
|
||||
const f: struct { error{foo} } = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testInUnion() void {
|
||||
const f: union(enum) { a: void, b: [*c]const u8 } = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testInVector() void {
|
||||
const f: @Vector(0, [*c]const u8) = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testInOpt() void {
|
||||
const f: *const ?[*c]const u8 = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testComptimeField() void {
|
||||
const f: struct { comptime foo: ??u8 = null } = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testEnumLiteral() void {
|
||||
const f: @TypeOf(.foo) = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testNestedOpt1() void {
|
||||
const f: ??u8 = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testNestedOpt2() void {
|
||||
const f: ?*const ?u8 = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testNestedOpt3() void {
|
||||
const f: *const ?*const ?*const u8 = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testOpt() void {
|
||||
const f: ?u8 = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
const E = enum(u8) { _ };
|
||||
export fn testNonExhaustiveEnum() void {
|
||||
const f: E = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
const U = union { foo: void };
|
||||
export fn testUntaggedUnion() void {
|
||||
const f: U = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
const EU = union(enum) { foo: void };
|
||||
export fn testTaggedUnionVoid() void {
|
||||
const f: EU = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testVisited() void {
|
||||
const V = struct {
|
||||
?f32, // Adds `?f32` to the visited list
|
||||
??f32, // `?f32` is already visited, we need to detect the nested opt anyway
|
||||
f32,
|
||||
};
|
||||
const f: V = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
export fn testMutablePointer() void {
|
||||
const f: *i32 = @import("zon/neg_inf.zon");
|
||||
_ = f;
|
||||
}
|
||||
|
||||
// error
|
||||
// imports=zon/neg_inf.zon
|
||||
//
|
||||
// tmp.zig:2:29: error: type 'void' is not available in ZON
|
||||
// tmp.zig:7:50: error: type '[*]const u8' is not available in ZON
|
||||
// tmp.zig:7:50: note: ZON does not allow many-pointers
|
||||
// tmp.zig:12:46: error: type 'error{foo}' is not available in ZON
|
||||
// tmp.zig:17:65: error: type '[*c]const u8' is not available in ZON
|
||||
// tmp.zig:17:65: note: ZON does not allow C pointers
|
||||
// tmp.zig:22:49: error: type '[*c]const u8' is not available in ZON
|
||||
// tmp.zig:22:49: note: ZON does not allow C pointers
|
||||
// tmp.zig:27:45: error: type '[*c]const u8' is not available in ZON
|
||||
// tmp.zig:27:45: note: ZON does not allow C pointers
|
||||
// tmp.zig:32:61: error: type '??u8' is not available in ZON
|
||||
// tmp.zig:32:61: note: ZON does not allow nested optionals
|
||||
// tmp.zig:42:29: error: type '??u8' is not available in ZON
|
||||
// tmp.zig:42:29: note: ZON does not allow nested optionals
|
||||
// tmp.zig:47:36: error: type '?*const ?u8' is not available in ZON
|
||||
// tmp.zig:47:36: note: ZON does not allow nested optionals
|
||||
// tmp.zig:52:50: error: type '?*const ?*const u8' is not available in ZON
|
||||
// tmp.zig:52:50: note: ZON does not allow nested optionals
|
||||
// tmp.zig:85:26: error: type '??f32' is not available in ZON
|
||||
// tmp.zig:85:26: note: ZON does not allow nested optionals
|
||||
// tmp.zig:90:29: error: type '*i32' is not available in ZON
|
||||
// tmp.zig:90:29: note: ZON does not allow mutable pointers
|
||||
// neg_inf.zon:1:1: error: expected type '@Type(.enum_literal)'
|
||||
// tmp.zig:37:38: note: imported here
|
||||
// neg_inf.zon:1:1: error: expected type '?u8'
|
||||
// tmp.zig:57:28: note: imported here
|
||||
// neg_inf.zon:1:1: error: expected type 'tmp.E'
|
||||
// tmp.zig:63:26: note: imported here
|
||||
// neg_inf.zon:1:1: error: expected type 'tmp.U'
|
||||
// tmp.zig:69:26: note: imported here
|
||||
// neg_inf.zon:1:1: error: expected type 'tmp.EU'
|
||||
// tmp.zig:75:27: note: imported here
|
||||
@ -0,0 +1,21 @@
|
||||
const C = struct {
|
||||
c: type,
|
||||
b: u32,
|
||||
};
|
||||
const S = struct {
|
||||
fn foo(b: u32, c: anytype) void {
|
||||
bar(C{ .c = c, .b = b });
|
||||
}
|
||||
fn bar(_: anytype) void {}
|
||||
};
|
||||
|
||||
pub export fn entry() void {
|
||||
S.foo(0, u32);
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
//:7:25: error: unable to resolve comptime value
|
||||
//:7:25: note: initializer of comptime-only struct 'tmp.C' must be comptime-known
|
||||
//:2:8: note: struct requires comptime because of this field
|
||||
//:2:8: note: types are not available at runtime
|
||||
26
test/cases/compile_errors/bogus_method_call_on_slice.zig
Normal file
26
test/cases/compile_errors/bogus_method_call_on_slice.zig
Normal file
@ -0,0 +1,26 @@
|
||||
var self = "aoeu";
|
||||
|
||||
fn f(m: []const u8) void {
|
||||
m.copy(u8, self[0..], m);
|
||||
}
|
||||
|
||||
export fn entry() usize {
|
||||
return @sizeOf(@TypeOf(&f));
|
||||
}
|
||||
|
||||
pub export fn entry1() void {
|
||||
.{}.bar();
|
||||
}
|
||||
|
||||
const S = struct { foo: i32 };
|
||||
pub export fn entry2() void {
|
||||
const x = S{ .foo = 1 };
|
||||
x.bar();
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :4:6: error: no field or member function named 'copy' in '[]const u8'
|
||||
// :12:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
|
||||
// :18:6: error: no field or member function named 'bar' in 'tmp.S'
|
||||
// :15:11: note: struct declared here
|
||||
12
test/cases/compile_errors/coerce_anon_struct.zig
Normal file
12
test/cases/compile_errors/coerce_anon_struct.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const A = struct { x: u32 };
|
||||
const T = struct { x: u32 };
|
||||
export fn foo() void {
|
||||
const a = A{ .x = 123 };
|
||||
_ = @as(T, a);
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :5:16: error: expected type 'tmp.T', found 'tmp.A'
|
||||
// :1:11: note: struct declared here
|
||||
// :2:11: note: struct declared here
|
||||
52
test/cases/compile_errors/redundant_try.zig
Normal file
52
test/cases/compile_errors/redundant_try.zig
Normal file
@ -0,0 +1,52 @@
|
||||
const S = struct { x: u32 = 0 };
|
||||
const T = struct { []const u8 };
|
||||
|
||||
fn test0() !void {
|
||||
const x: u8 = try 1;
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn test1() !void {
|
||||
const x: S = try .{};
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn test2() !void {
|
||||
const x: S = try S{ .x = 123 };
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn test3() !void {
|
||||
const x: S = try try S{ .x = 123 };
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn test4() !void {
|
||||
const x: T = try .{"hello"};
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn test5() !void {
|
||||
const x: error{Foo}!u32 = 123;
|
||||
_ = try try x;
|
||||
}
|
||||
|
||||
comptime {
|
||||
_ = &test0;
|
||||
_ = &test1;
|
||||
_ = &test2;
|
||||
_ = &test3;
|
||||
_ = &test4;
|
||||
_ = &test5;
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :5:23: error: expected error union type, found 'comptime_int'
|
||||
// :10:23: error: expected error union type, found '@TypeOf(.{})'
|
||||
// :15:23: error: expected error union type, found 'tmp.S'
|
||||
// :1:11: note: struct declared here
|
||||
// :20:27: error: expected error union type, found 'tmp.S'
|
||||
// :1:11: note: struct declared here
|
||||
// :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }'
|
||||
// :31:13: error: expected error union type, found 'u32'
|
||||
@ -46,14 +46,18 @@ const StructInStruct = struct { a: struct { b: u8 } };
|
||||
const UnionInStruct = struct { a: union { b: u8 } };
|
||||
const StructInUnion = union { a: struct { b: u8 } };
|
||||
const UnionInUnion = union { a: union { b: u8 } };
|
||||
const StructInTuple = struct { struct { b: u8 } };
|
||||
const UnionInTuple = struct { union { b: u8 } };
|
||||
const InnerStruct = struct { b: u8 };
|
||||
const StructInTuple = struct { a: InnerStruct };
|
||||
const InnerUnion = union { b: u8 };
|
||||
const UnionInTuple = struct { a: InnerUnion };
|
||||
|
||||
export fn nestedTypes() void {
|
||||
@compileLog(@typeName(StructInStruct));
|
||||
@compileLog(@typeName(UnionInStruct));
|
||||
@compileLog(@typeName(StructInUnion));
|
||||
@compileLog(@typeName(UnionInUnion));
|
||||
@compileLog(@typeName(StructInTuple));
|
||||
@compileLog(@typeName(UnionInTuple));
|
||||
}
|
||||
|
||||
// error
|
||||
@ -61,22 +65,24 @@ export fn nestedTypes() void {
|
||||
// :8:5: error: found compile log statement
|
||||
// :19:5: note: also here
|
||||
// :39:5: note: also here
|
||||
// :53:5: note: also here
|
||||
// :55:5: note: also here
|
||||
//
|
||||
// Compile Log Output:
|
||||
// @as(*const [15:0]u8, "tmp.namespace.S")
|
||||
// @as(*const [15:0]u8, "tmp.namespace.E")
|
||||
// @as(*const [15:0]u8, "tmp.namespace.U")
|
||||
// @as(*const [15:0]u8, "tmp.namespace.O")
|
||||
// @as(*const [19:0]u8, "tmp.localVarValue.S")
|
||||
// @as(*const [19:0]u8, "tmp.localVarValue.E")
|
||||
// @as(*const [19:0]u8, "tmp.localVarValue.U")
|
||||
// @as(*const [19:0]u8, "tmp.localVarValue.O")
|
||||
// @as(*const [11:0]u8, "tmp.MakeS()")
|
||||
// @as(*const [11:0]u8, "tmp.MakeE()")
|
||||
// @as(*const [11:0]u8, "tmp.MakeU()")
|
||||
// @as(*const [11:0]u8, "tmp.MakeO()")
|
||||
// @as(*const [18:0]u8, "tmp.StructInStruct")
|
||||
// @as(*const [17:0]u8, "tmp.UnionInStruct")
|
||||
// @as(*const [17:0]u8, "tmp.StructInUnion")
|
||||
// @as(*const [16:0]u8, "tmp.UnionInUnion")
|
||||
//Compile Log Output:
|
||||
//@as(*const [15:0]u8, "tmp.namespace.S")
|
||||
//@as(*const [15:0]u8, "tmp.namespace.E")
|
||||
//@as(*const [15:0]u8, "tmp.namespace.U")
|
||||
//@as(*const [15:0]u8, "tmp.namespace.O")
|
||||
//@as(*const [19:0]u8, "tmp.localVarValue.S")
|
||||
//@as(*const [19:0]u8, "tmp.localVarValue.E")
|
||||
//@as(*const [19:0]u8, "tmp.localVarValue.U")
|
||||
//@as(*const [19:0]u8, "tmp.localVarValue.O")
|
||||
//@as(*const [11:0]u8, "tmp.MakeS()")
|
||||
//@as(*const [11:0]u8, "tmp.MakeE()")
|
||||
//@as(*const [11:0]u8, "tmp.MakeU()")
|
||||
//@as(*const [11:0]u8, "tmp.MakeO()")
|
||||
//@as(*const [18:0]u8, "tmp.StructInStruct")
|
||||
//@as(*const [17:0]u8, "tmp.UnionInStruct")
|
||||
//@as(*const [17:0]u8, "tmp.StructInUnion")
|
||||
//@as(*const [16:0]u8, "tmp.UnionInUnion")
|
||||
//@as(*const [17:0]u8, "tmp.StructInTuple")
|
||||
//@as(*const [16:0]u8, "tmp.UnionInTuple")
|
||||
|
||||
@ -800,8 +800,6 @@ const TestManifestConfigDefaults = struct {
|
||||
}
|
||||
// Windows
|
||||
defaults = defaults ++ "x86_64-windows" ++ ",";
|
||||
// Wasm
|
||||
defaults = defaults ++ "wasm32-wasi";
|
||||
break :blk defaults;
|
||||
};
|
||||
} else if (std.mem.eql(u8, key, "output_mode")) {
|
||||
|
||||
@ -1335,15 +1335,16 @@ const test_targets = blk: {
|
||||
|
||||
// WASI Targets
|
||||
|
||||
.{
|
||||
.target = .{
|
||||
.cpu_arch = .wasm32,
|
||||
.os_tag = .wasi,
|
||||
.abi = .none,
|
||||
},
|
||||
.use_llvm = false,
|
||||
.use_lld = false,
|
||||
},
|
||||
// TODO: lowerTry for pointers
|
||||
//.{
|
||||
// .target = .{
|
||||
// .cpu_arch = .wasm32,
|
||||
// .os_tag = .wasi,
|
||||
// .abi = .none,
|
||||
// },
|
||||
// .use_llvm = false,
|
||||
// .use_lld = false,
|
||||
//},
|
||||
.{
|
||||
.target = .{
|
||||
.cpu_arch = .wasm32,
|
||||
|
||||
@ -120,7 +120,7 @@ pub fn main() !void {
|
||||
error_bundle.renderToStdErr(color.renderOptions());
|
||||
}
|
||||
|
||||
const formatted_output = try tree.render(allocator);
|
||||
const formatted_output = try tree.renderAlloc(allocator);
|
||||
_ = try std.fs.File.stdout().write(formatted_output);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user