authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-27 20:05:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-07 22:43:51-07:00
log0e37ff0d591dd75ceec9208196bec29efaec607a
treec126fa823a1f3864e9c363aac70e3a3db0219957
parent0b3f0124dc33403d329fb8ee63a93215d9af1f1e

std.fmt: breaking API changes

added adapter to AnyWriter and GenericWriter to help bridge the gap between old and new API make std.testing.expectFmt work at compile-time std.fmt no longer has a dependency on std.unicode. Formatted printing was never properly unicode-aware. Now it no longer pretends to be. Breakage/deprecations: * std.fs.File.reader -> std.fs.File.deprecatedReader * std.fs.File.writer -> std.fs.File.deprecatedWriter * std.io.GenericReader -> std.io.Reader * std.io.GenericWriter -> std.io.Writer * std.io.AnyReader -> std.io.Reader * std.io.AnyWriter -> std.io.Writer * std.fmt.format -> std.fmt.deprecatedFormat * std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape * std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape * std.fmt.fmtSliceHexLower -> {x} * std.fmt.fmtSliceHexUpper -> {X} * std.fmt.fmtIntSizeDec -> {B} * std.fmt.fmtIntSizeBin -> {Bi} * std.fmt.fmtDuration -> {D} * std.fmt.fmtDurationSigned -> {D} * {} -> {f} when there is a format method * format method signature - anytype -> *std.io.Writer - inferred error set -> error{WriteFailed} - options -> (deleted) * std.fmt.Formatted - now takes context type explicitly - no fmt string

162 files changed, 6074 insertions(+), 7536 deletions(-)

CMakeLists.txt-1
......@@ -436,7 +436,6 @@ set(ZIG_STAGE2_SOURCES
436436 lib/std/elf.zig
437437 lib/std/fifo.zig
438438 lib/std/fmt.zig
439 lib/std/fmt/format_float.zig
440439 lib/std/fmt/parse_float.zig
441440 lib/std/fs.zig
442441 lib/std/fs/AtomicFile.zig
build.zig+3-3
......@@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void {
279279
280280 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
281281 if (zig_version.order(ancestor_ver) != .gt) {
282 std.debug.print("Zig version '{}' must be greater than tagged ancestor '{}'\n", .{ zig_version, ancestor_ver });
282 std.debug.print("Zig version '{f}' must be greater than tagged ancestor '{f}'\n", .{ zig_version, ancestor_ver });
283283 std.process.exit(1);
284284 }
285285
......@@ -1449,7 +1449,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
14491449 }
14501450
14511451 var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {
1452 std.debug.panic("unable to open '{}doc/langref' directory: {s}", .{
1452 std.debug.panic("unable to open '{f}doc/langref' directory: {s}", .{
14531453 b.build_root, @errorName(err),
14541454 });
14551455 };
......@@ -1470,7 +1470,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
14701470 // in a temporary directory
14711471 "--cache-root", b.cache_root.path orelse ".",
14721472 });
1473 cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });
1473 cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
14741474 cmd.addArgs(&.{"-i"});
14751475 cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name})));
14761476
lib/compiler/aro/aro/Compilation.zig+1-1
......@@ -1432,7 +1432,7 @@ fn getFileContents(comp: *Compilation, path: []const u8, limit: ?u32) ![]const u
14321432 defer buf.deinit();
14331433
14341434 const max = limit orelse std.math.maxInt(u32);
1435 file.reader().readAllArrayList(&buf, max) catch |e| switch (e) {
1435 file.deprecatedReader().readAllArrayList(&buf, max) catch |e| switch (e) {
14361436 error.StreamTooLong => if (limit == null) return e,
14371437 else => return e,
14381438 };
lib/compiler/aro/aro/Diagnostics.zig+8-18
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const assert = std.debug.assert;
23const Allocator = mem.Allocator;
34const mem = std.mem;
45const Source = @import("Source.zig");
......@@ -443,18 +444,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
443444 printRt(m, prop.msg, .{"{s}"}, .{&str});
444445 } else {
445446 var buf: [3]u8 = undefined;
446 const str = std.fmt.bufPrint(&buf, "x{x}", .{std.fmt.fmtSliceHexLower(&.{msg.extra.invalid_escape.char})}) catch unreachable;
447 const str = std.fmt.bufPrint(&buf, "x{x}", .{&.{msg.extra.invalid_escape.char}}) catch unreachable;
447448 printRt(m, prop.msg, .{"{s}"}, .{str});
448449 }
449450 },
450451 .normalized => {
451452 const f = struct {
452 pub fn f(
453 bytes: []const u8,
454 comptime _: []const u8,
455 _: std.fmt.FormatOptions,
456 writer: anytype,
457 ) !void {
453 pub fn f(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
458454 var it: std.unicode.Utf8Iterator = .{
459455 .bytes = bytes,
460456 .i = 0,
......@@ -464,22 +460,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
464460 try writer.writeByte(@intCast(codepoint));
465461 } else if (codepoint < 0xFFFF) {
466462 try writer.writeAll("\\u");
467 try std.fmt.formatInt(codepoint, 16, .upper, .{
468 .fill = '0',
469 .width = 4,
470 }, writer);
463 try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 4 });
471464 } else {
472465 try writer.writeAll("\\U");
473 try std.fmt.formatInt(codepoint, 16, .upper, .{
474 .fill = '0',
475 .width = 8,
476 }, writer);
466 try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 8 });
477467 }
478468 }
479469 }
480470 }.f;
481 printRt(m, prop.msg, .{"{s}"}, .{
482 std.fmt.Formatter(f){ .data = msg.extra.normalized },
471 printRt(m, prop.msg, .{"{f}"}, .{
472 std.fmt.Formatter([]const u8, f){ .data = msg.extra.normalized },
483473 });
484474 },
485475 .none, .offset => m.write(prop.msg),
......@@ -541,7 +531,7 @@ const MsgWriter = struct {
541531 fn init(config: std.io.tty.Config) MsgWriter {
542532 std.debug.lockStdErr();
543533 return .{
544 .w = std.io.bufferedWriter(std.fs.File.stderr().writer()),
534 .w = std.io.bufferedWriter(std.fs.File.stderr().deprecatedWriter()),
545535 .config = config,
546536 };
547537 }
lib/compiler/aro/aro/Driver.zig+6-6
......@@ -591,7 +591,7 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_
591591 var macro_buf = std.ArrayList(u8).init(d.comp.gpa);
592592 defer macro_buf.deinit();
593593
594 const std_out = std.fs.File.stdout().writer();
594 const std_out = std.fs.File.stdout().deprecatedWriter();
595595 if (try parseArgs(d, std_out, macro_buf.writer(), args)) return;
596596
597597 const linking = !(d.only_preprocess or d.only_syntax or d.only_compile or d.only_preprocess_and_compile);
......@@ -689,7 +689,7 @@ fn processSource(
689689 std.fs.File.stdout();
690690 defer if (d.output_name != null) file.close();
691691
692 var buf_w = std.io.bufferedWriter(file.writer());
692 var buf_w = std.io.bufferedWriter(file.deprecatedWriter());
693693
694694 pp.prettyPrintTokens(buf_w.writer(), dump_mode) catch |er|
695695 return d.fatal("unable to write result: {s}", .{errorDescription(er)});
......@@ -705,7 +705,7 @@ fn processSource(
705705
706706 if (d.verbose_ast) {
707707 const stdout = std.fs.File.stdout();
708 var buf_writer = std.io.bufferedWriter(stdout.writer());
708 var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter());
709709 tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {};
710710 buf_writer.flush() catch {};
711711 }
......@@ -735,7 +735,7 @@ fn processSource(
735735
736736 if (d.verbose_ir) {
737737 const stdout = std.fs.File.stdout();
738 var buf_writer = std.io.bufferedWriter(stdout.writer());
738 var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter());
739739 ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {};
740740 buf_writer.flush() catch {};
741741 }
......@@ -806,10 +806,10 @@ fn processSource(
806806}
807807
808808fn dumpLinkerArgs(items: []const []const u8) !void {
809 const stdout = std.fs.File.stdout().writer();
809 const stdout = std.fs.File.stdout().deprecatedWriter();
810810 for (items, 0..) |item, i| {
811811 if (i > 0) try stdout.writeByte(' ');
812 try stdout.print("\"{}\"", .{std.zig.fmtEscapes(item)});
812 try stdout.print("\"{f}\"", .{std.zig.fmtString(item)});
813813 }
814814 try stdout.writeByte('\n');
815815}
lib/compiler/aro/aro/Parser.zig+5-5
......@@ -500,8 +500,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_
500500
501501 const w = p.strings.writer();
502502 const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes;
503 try w.print("call to '{s}' declared with attribute error: {}", .{
504 p.tokSlice(@"error".__name_tok), std.zig.fmtEscapes(msg_str),
503 try w.print("call to '{s}' declared with attribute error: {f}", .{
504 p.tokSlice(@"error".__name_tok), std.zig.fmtString(msg_str),
505505 });
506506 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
507507 try p.errStr(.error_attribute, usage_tok, str);
......@@ -512,8 +512,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_
512512
513513 const w = p.strings.writer();
514514 const msg_str = p.comp.interner.get(warning.msg.ref()).bytes;
515 try w.print("call to '{s}' declared with attribute warning: {}", .{
516 p.tokSlice(warning.__name_tok), std.zig.fmtEscapes(msg_str),
515 try w.print("call to '{s}' declared with attribute warning: {f}", .{
516 p.tokSlice(warning.__name_tok), std.zig.fmtString(msg_str),
517517 });
518518 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
519519 try p.errStr(.warning_attribute, usage_tok, str);
......@@ -542,7 +542,7 @@ fn errDeprecated(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, msg: ?Valu
542542 try w.writeAll(reason);
543543 if (msg) |m| {
544544 const str = p.comp.interner.get(m.ref()).bytes;
545 try w.print(": {}", .{std.zig.fmtEscapes(str)});
545 try w.print(": {f}", .{std.zig.fmtString(str)});
546546 }
547547 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
548548 return p.errStr(tag, tok_i, str);
lib/compiler/aro/aro/Preprocessor.zig+3-2
......@@ -811,7 +811,7 @@ fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args:
811811 const source = pp.comp.getSource(raw.source);
812812 const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start });
813813
814 const stderr = std.fs.File.stderr().writer();
814 const stderr = std.fs.File.stderr().deprecatedWriter();
815815 var buf_writer = std.io.bufferedWriter(stderr);
816816 const writer = buf_writer.writer();
817817 defer buf_writer.flush() catch {};
......@@ -3262,7 +3262,8 @@ fn printLinemarker(
32623262 // containing the same bytes as the input regardless of encoding.
32633263 else => {
32643264 try w.writeAll("\\x");
3265 try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, w);
3265 // TODO try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });
3266 try w.print("{x:0>2}", .{byte});
32663267 },
32673268 };
32683269 try w.writeByte('"');
lib/compiler/aro/aro/Value.zig+1-1
......@@ -982,7 +982,7 @@ pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: any
982982 const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];
983983 try w.writeByte('"');
984984 switch (size) {
985 .@"1" => try w.print("{}", .{std.zig.fmtEscapes(without_null)}),
985 .@"1" => try w.print("{f}", .{std.zig.fmtString(without_null)}),
986986 .@"2" => {
987987 var items: [2]u16 = undefined;
988988 var i: usize = 0;
lib/compiler/aro/backend/Object/Elf.zig+1-1
......@@ -171,7 +171,7 @@ pub fn addRelocation(elf: *Elf, name: []const u8, section_kind: Object.Section,
171171/// strtab
172172/// section headers
173173pub fn finish(elf: *Elf, file: std.fs.File) !void {
174 var buf_writer = std.io.bufferedWriter(file.writer());
174 var buf_writer = std.io.bufferedWriter(file.deprecatedWriter());
175175 const w = buf_writer.writer();
176176
177177 var num_sections: std.elf.Elf64_Half = additional_sections;
lib/compiler/aro_translate_c/ast.zig+6-6
......@@ -849,7 +849,7 @@ const Context = struct {
849849 fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
850850 if (std.zig.primitives.isPrimitive(bytes))
851851 return c.addTokenFmt(.identifier, "@\"{s}\"", .{bytes});
852 return c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(bytes)});
852 return c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(bytes, .{ .allow_primitive = true })});
853853 }
854854
855855 fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
......@@ -1201,7 +1201,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12011201
12021202 const compile_error_tok = try c.addToken(.builtin, "@compileError");
12031203 _ = try c.addToken(.l_paren, "(");
1204 const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(payload.mangled)});
1204 const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(payload.mangled)});
12051205 const err_msg = try c.addNode(.{
12061206 .tag = .string_literal,
12071207 .main_token = err_msg_tok,
......@@ -2116,7 +2116,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
21162116 defer c.gpa.free(members);
21172117
21182118 for (payload.fields, 0..) |field, i| {
2119 const name_tok = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field.name)});
2119 const name_tok = try c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true })});
21202120 _ = try c.addToken(.colon, ":");
21212121 const type_expr = try renderNode(c, field.type);
21222122
......@@ -2205,7 +2205,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
22052205 .main_token = try c.addToken(.period, "."),
22062206 .data = .{ .node_and_token = .{
22072207 lhs,
2208 try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}),
2208 try c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true })}),
22092209 } },
22102210 });
22112211}
......@@ -2681,7 +2681,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
26812681 _ = try c.addToken(.l_paren, "(");
26822682 const res = try c.addNode(.{
26832683 .tag = .string_literal,
2684 .main_token = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(some)}),
2684 .main_token = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(some)}),
26852685 .data = undefined,
26862686 });
26872687 _ = try c.addToken(.r_paren, ")");
......@@ -2765,7 +2765,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
27652765 _ = try c.addToken(.l_paren, "(");
27662766 const res = try c.addNode(.{
27672767 .tag = .string_literal,
2768 .main_token = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(some)}),
2768 .main_token = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(some)}),
27692769 .data = undefined,
27702770 });
27712771 _ = try c.addToken(.r_paren, ")");
lib/compiler/build_runner.zig+29-29
......@@ -365,7 +365,7 @@ pub fn main() !void {
365365 .data = buffer.items,
366366 .flags = .{ .exclusive = true },
367367 }) catch |err| {
368 fatal("unable to write configuration results to '{}{s}': {s}", .{
368 fatal("unable to write configuration results to '{f}{s}': {s}", .{
369369 local_cache_directory, tmp_sub_path, @errorName(err),
370370 });
371371 };
......@@ -378,7 +378,7 @@ pub fn main() !void {
378378
379379 validateSystemLibraryOptions(builder);
380380
381 const stdout_writer = std.fs.File.stdout().writer();
381 const stdout_writer = std.fs.File.stdout().deprecatedWriter();
382382
383383 if (help_menu)
384384 return usage(builder, stdout_writer);
......@@ -704,14 +704,14 @@ fn runStepNames(
704704 ttyconf.setColor(stderr, .cyan) catch {};
705705 stderr.writeAll("Build Summary:") catch {};
706706 ttyconf.setColor(stderr, .reset) catch {};
707 stderr.writer().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
708 if (skipped_count > 0) stderr.writer().print("; {d} skipped", .{skipped_count}) catch {};
709 if (failure_count > 0) stderr.writer().print("; {d} failed", .{failure_count}) catch {};
707 stderr.deprecatedWriter().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
708 if (skipped_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{skipped_count}) catch {};
709 if (failure_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{failure_count}) catch {};
710710
711 if (test_count > 0) stderr.writer().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};
712 if (test_skip_count > 0) stderr.writer().print("; {d} skipped", .{test_skip_count}) catch {};
713 if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};
714 if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};
711 if (test_count > 0) stderr.deprecatedWriter().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};
712 if (test_skip_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{test_skip_count}) catch {};
713 if (test_fail_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{test_fail_count}) catch {};
714 if (test_leak_count > 0) stderr.deprecatedWriter().print("; {d} leaked", .{test_leak_count}) catch {};
715715
716716 stderr.writeAll("\n") catch {};
717717
......@@ -820,10 +820,10 @@ fn printStepStatus(
820820 try stderr.writeAll(" cached");
821821 } else if (s.test_results.test_count > 0) {
822822 const pass_count = s.test_results.passCount();
823 try stderr.writer().print(" {d} passed", .{pass_count});
823 try stderr.deprecatedWriter().print(" {d} passed", .{pass_count});
824824 if (s.test_results.skip_count > 0) {
825825 try ttyconf.setColor(stderr, .yellow);
826 try stderr.writer().print(" {d} skipped", .{s.test_results.skip_count});
826 try stderr.deprecatedWriter().print(" {d} skipped", .{s.test_results.skip_count});
827827 }
828828 } else {
829829 try stderr.writeAll(" success");
......@@ -832,15 +832,15 @@ fn printStepStatus(
832832 if (s.result_duration_ns) |ns| {
833833 try ttyconf.setColor(stderr, .dim);
834834 if (ns >= std.time.ns_per_min) {
835 try stderr.writer().print(" {d}m", .{ns / std.time.ns_per_min});
835 try stderr.deprecatedWriter().print(" {d}m", .{ns / std.time.ns_per_min});
836836 } else if (ns >= std.time.ns_per_s) {
837 try stderr.writer().print(" {d}s", .{ns / std.time.ns_per_s});
837 try stderr.deprecatedWriter().print(" {d}s", .{ns / std.time.ns_per_s});
838838 } else if (ns >= std.time.ns_per_ms) {
839 try stderr.writer().print(" {d}ms", .{ns / std.time.ns_per_ms});
839 try stderr.deprecatedWriter().print(" {d}ms", .{ns / std.time.ns_per_ms});
840840 } else if (ns >= std.time.ns_per_us) {
841 try stderr.writer().print(" {d}us", .{ns / std.time.ns_per_us});
841 try stderr.deprecatedWriter().print(" {d}us", .{ns / std.time.ns_per_us});
842842 } else {
843 try stderr.writer().print(" {d}ns", .{ns});
843 try stderr.deprecatedWriter().print(" {d}ns", .{ns});
844844 }
845845 try ttyconf.setColor(stderr, .reset);
846846 }
......@@ -848,13 +848,13 @@ fn printStepStatus(
848848 const rss = s.result_peak_rss;
849849 try ttyconf.setColor(stderr, .dim);
850850 if (rss >= 1000_000_000) {
851 try stderr.writer().print(" MaxRSS:{d}G", .{rss / 1000_000_000});
851 try stderr.deprecatedWriter().print(" MaxRSS:{d}G", .{rss / 1000_000_000});
852852 } else if (rss >= 1000_000) {
853 try stderr.writer().print(" MaxRSS:{d}M", .{rss / 1000_000});
853 try stderr.deprecatedWriter().print(" MaxRSS:{d}M", .{rss / 1000_000});
854854 } else if (rss >= 1000) {
855 try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000});
855 try stderr.deprecatedWriter().print(" MaxRSS:{d}K", .{rss / 1000});
856856 } else {
857 try stderr.writer().print(" MaxRSS:{d}B", .{rss});
857 try stderr.deprecatedWriter().print(" MaxRSS:{d}B", .{rss});
858858 }
859859 try ttyconf.setColor(stderr, .reset);
860860 }
......@@ -866,7 +866,7 @@ fn printStepStatus(
866866 if (skip == .skipped_oom) {
867867 try stderr.writeAll(" (not enough memory)");
868868 try ttyconf.setColor(stderr, .dim);
869 try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
869 try stderr.deprecatedWriter().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
870870 try ttyconf.setColor(stderr, .yellow);
871871 }
872872 try stderr.writeAll("\n");
......@@ -883,18 +883,18 @@ fn printStepFailure(
883883) !void {
884884 if (s.result_error_bundle.errorMessageCount() > 0) {
885885 try ttyconf.setColor(stderr, .red);
886 try stderr.writer().print(" {d} errors\n", .{
886 try stderr.deprecatedWriter().print(" {d} errors\n", .{
887887 s.result_error_bundle.errorMessageCount(),
888888 });
889889 try ttyconf.setColor(stderr, .reset);
890890 } else if (!s.test_results.isSuccess()) {
891 try stderr.writer().print(" {d}/{d} passed", .{
891 try stderr.deprecatedWriter().print(" {d}/{d} passed", .{
892892 s.test_results.passCount(), s.test_results.test_count,
893893 });
894894 if (s.test_results.fail_count > 0) {
895895 try stderr.writeAll(", ");
896896 try ttyconf.setColor(stderr, .red);
897 try stderr.writer().print("{d} failed", .{
897 try stderr.deprecatedWriter().print("{d} failed", .{
898898 s.test_results.fail_count,
899899 });
900900 try ttyconf.setColor(stderr, .reset);
......@@ -902,7 +902,7 @@ fn printStepFailure(
902902 if (s.test_results.skip_count > 0) {
903903 try stderr.writeAll(", ");
904904 try ttyconf.setColor(stderr, .yellow);
905 try stderr.writer().print("{d} skipped", .{
905 try stderr.deprecatedWriter().print("{d} skipped", .{
906906 s.test_results.skip_count,
907907 });
908908 try ttyconf.setColor(stderr, .reset);
......@@ -910,7 +910,7 @@ fn printStepFailure(
910910 if (s.test_results.leak_count > 0) {
911911 try stderr.writeAll(", ");
912912 try ttyconf.setColor(stderr, .red);
913 try stderr.writer().print("{d} leaked", .{
913 try stderr.deprecatedWriter().print("{d} leaked", .{
914914 s.test_results.leak_count,
915915 });
916916 try ttyconf.setColor(stderr, .reset);
......@@ -992,7 +992,7 @@ fn printTreeStep(
992992 if (s.dependencies.items.len == 0) {
993993 try stderr.writeAll(" (reused)\n");
994994 } else {
995 try stderr.writer().print(" (+{d} more reused dependencies)\n", .{
995 try stderr.deprecatedWriter().print(" (+{d} more reused dependencies)\n", .{
996996 s.dependencies.items.len,
997997 });
998998 }
......@@ -1209,7 +1209,7 @@ pub fn printErrorMessages(
12091209 var indent: usize = 0;
12101210 while (step_stack.pop()) |s| : (indent += 1) {
12111211 if (indent > 0) {
1212 try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3);
1212 try stderr.deprecatedWriter().writeByteNTimes(' ', (indent - 1) * 3);
12131213 try printChildNodePrefix(stderr, ttyconf);
12141214 }
12151215
......@@ -1231,7 +1231,7 @@ pub fn printErrorMessages(
12311231 }
12321232
12331233 if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {
1234 try failing_step.result_error_bundle.renderToWriter(options, stderr.writer());
1234 try failing_step.result_error_bundle.renderToWriter(options, stderr.deprecatedWriter());
12351235 }
12361236
12371237 for (failing_step.result_error_msgs.items) |msg| {
lib/compiler/libc.zig+3-3
......@@ -40,7 +40,7 @@ pub fn main() !void {
4040 const arg = args[i];
4141 if (mem.startsWith(u8, arg, "-")) {
4242 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
43 const stdout = std.fs.File.stdout().writer();
43 const stdout = std.fs.File.stdout().deprecatedWriter();
4444 try stdout.writeAll(usage_libc);
4545 return std.process.cleanExit();
4646 } else if (mem.eql(u8, arg, "-target")) {
......@@ -97,7 +97,7 @@ pub fn main() !void {
9797 fatal("no include dirs detected for target {s}", .{zig_target});
9898 }
9999
100 var bw = std.io.bufferedWriter(std.fs.File.stdout().writer());
100 var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
101101 var writer = bw.writer();
102102 for (libc_dirs.libc_include_dir_list) |include_dir| {
103103 try writer.writeAll(include_dir);
......@@ -125,7 +125,7 @@ pub fn main() !void {
125125 };
126126 defer libc.deinit(gpa);
127127
128 var bw = std.io.bufferedWriter(std.fs.File.stdout().writer());
128 var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
129129 try libc.render(bw.writer());
130130 try bw.flush();
131131 }
lib/compiler/objcopy.zig+3-3
......@@ -635,11 +635,11 @@ const HexWriter = struct {
635635 const payload_bytes = self.getPayloadBytes();
636636 assert(payload_bytes.len <= MAX_PAYLOAD_LEN);
637637
638 const line = try std.fmt.bufPrint(&outbuf, ":{0X:0>2}{1X:0>4}{2X:0>2}{3s}{4X:0>2}" ++ linesep, .{
638 const line = try std.fmt.bufPrint(&outbuf, ":{0X:0>2}{1X:0>4}{2X:0>2}{3X}{4X:0>2}" ++ linesep, .{
639639 @as(u8, @intCast(payload_bytes.len)),
640640 self.address,
641641 @intFromEnum(self.payload),
642 std.fmt.fmtSliceHexUpper(payload_bytes),
642 payload_bytes,
643643 self.checksum(),
644644 });
645645 try file.writeAll(line);
......@@ -1495,7 +1495,7 @@ const ElfFileHelper = struct {
14951495 if (size < prefix.len) return null;
14961496
14971497 try in_file.seekTo(offset);
1498 var section_reader = std.io.limitedReader(in_file.reader(), size);
1498 var section_reader = std.io.limitedReader(in_file.deprecatedReader(), size);
14991499
15001500 // allocate as large as decompressed data. if the compression doesn't fit, keep the data uncompressed.
15011501 const compressed_data = try allocator.alignedAlloc(u8, .@"8", @intCast(size));
lib/compiler/reduce.zig+1-1
......@@ -68,7 +68,7 @@ pub fn main() !void {
6868 const arg = args[i];
6969 if (mem.startsWith(u8, arg, "-")) {
7070 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
71 const stdout = std.fs.File.stdout().writer();
71 const stdout = std.fs.File.stdout().deprecatedWriter();
7272 try stdout.writeAll(usage);
7373 return std.process.cleanExit();
7474 } else if (mem.eql(u8, arg, "--")) {
lib/compiler/resinator/cli.zig+1-1
......@@ -127,7 +127,7 @@ pub const Diagnostics = struct {
127127 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.io.tty.Config) void {
128128 std.debug.lockStdErr();
129129 defer std.debug.unlockStdErr();
130 const stderr = std.fs.File.stderr().writer();
130 const stderr = std.fs.File.stderr().deprecatedWriter();
131131 self.renderToWriter(args, stderr, config) catch return;
132132 }
133133
lib/compiler/resinator/compile.zig+9-9
......@@ -570,7 +570,7 @@ pub const Compiler = struct {
570570 switch (predefined_type) {
571571 .GROUP_ICON, .GROUP_CURSOR => {
572572 // Check for animated icon first
573 if (ani.isAnimatedIcon(file.reader())) {
573 if (ani.isAnimatedIcon(file.deprecatedReader())) {
574574 // Animated icons are just put into the resource unmodified,
575575 // and the resource type changes to ANIICON/ANICURSOR
576576
......@@ -586,14 +586,14 @@ pub const Compiler = struct {
586586
587587 try header.write(writer, self.errContext(node.id));
588588 try file.seekTo(0);
589 try writeResourceData(writer, file.reader(), header.data_size);
589 try writeResourceData(writer, file.deprecatedReader(), header.data_size);
590590 return;
591591 }
592592
593593 // isAnimatedIcon moved the file cursor so reset to the start
594594 try file.seekTo(0);
595595
596 const icon_dir = ico.read(self.allocator, file.reader(), try file.getEndPos()) catch |err| switch (err) {
596 const icon_dir = ico.read(self.allocator, file.deprecatedReader(), try file.getEndPos()) catch |err| switch (err) {
597597 error.OutOfMemory => |e| return e,
598598 else => |e| {
599599 return self.iconReadError(
......@@ -672,7 +672,7 @@ pub const Compiler = struct {
672672 }
673673
674674 try file.seekTo(entry.data_offset_from_start_of_file);
675 var header_bytes = file.reader().readBytesNoEof(16) catch {
675 var header_bytes = file.deprecatedReader().readBytesNoEof(16) catch {
676676 return self.iconReadError(
677677 error.UnexpectedEOF,
678678 filename_utf8,
......@@ -803,7 +803,7 @@ pub const Compiler = struct {
803803 }
804804
805805 try file.seekTo(entry.data_offset_from_start_of_file);
806 try writeResourceDataNoPadding(writer, file.reader(), entry.data_size_in_bytes);
806 try writeResourceDataNoPadding(writer, file.deprecatedReader(), entry.data_size_in_bytes);
807807 try writeDataPadding(writer, full_data_size);
808808
809809 if (self.state.icon_id == std.math.maxInt(u16)) {
......@@ -859,7 +859,7 @@ pub const Compiler = struct {
859859 header.applyMemoryFlags(node.common_resource_attributes, self.source);
860860 const file_size = try file.getEndPos();
861861
862 const bitmap_info = bmp.read(file.reader(), file_size) catch |err| {
862 const bitmap_info = bmp.read(file.deprecatedReader(), file_size) catch |err| {
863863 const filename_string_index = try self.diagnostics.putString(filename_utf8);
864864 return self.addErrorDetailsAndFail(.{
865865 .err = .bmp_read_error,
......@@ -922,7 +922,7 @@ pub const Compiler = struct {
922922 header.data_size = bmp_bytes_to_write;
923923 try header.write(writer, self.errContext(node.id));
924924 try file.seekTo(bmp.file_header_len);
925 const file_reader = file.reader();
925 const file_reader = file.deprecatedReader();
926926 try writeResourceDataNoPadding(writer, file_reader, bitmap_info.dib_header_size);
927927 if (bitmap_info.getBitmasksByteLen() > 0) {
928928 try writeResourceDataNoPadding(writer, file_reader, bitmap_info.getBitmasksByteLen());
......@@ -968,7 +968,7 @@ pub const Compiler = struct {
968968 header.data_size = @intCast(file_size);
969969 try header.write(writer, self.errContext(node.id));
970970
971 var header_slurping_reader = headerSlurpingReader(148, file.reader());
971 var header_slurping_reader = headerSlurpingReader(148, file.deprecatedReader());
972972 try writeResourceData(writer, header_slurping_reader.reader(), header.data_size);
973973
974974 try self.state.font_dir.add(self.arena, FontDir.Font{
......@@ -1002,7 +1002,7 @@ pub const Compiler = struct {
10021002 // We now know that the data size will fit in a u32
10031003 header.data_size = @intCast(data_size);
10041004 try header.write(writer, self.errContext(node.id));
1005 try writeResourceData(writer, file.reader(), header.data_size);
1005 try writeResourceData(writer, file.deprecatedReader(), header.data_size);
10061006 }
10071007
10081008 fn iconReadError(
lib/compiler/resinator/errors.zig+11-14
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const assert = std.debug.assert;
23const Token = @import("lex.zig").Token;
34const SourceMappings = @import("source_mapping.zig").SourceMappings;
45const utils = @import("utils.zig");
......@@ -63,7 +64,7 @@ pub const Diagnostics = struct {
6364 pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.io.tty.Config, source_mappings: ?SourceMappings) void {
6465 std.debug.lockStdErr();
6566 defer std.debug.unlockStdErr();
66 const stderr = std.fs.File.stderr().writer();
67 const stderr = std.fs.File.stderr().deprecatedWriter();
6768 for (self.errors.items) |err_details| {
6869 renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
6970 }
......@@ -409,15 +410,7 @@ pub const ErrorDetails = struct {
409410 failed_to_open_cwd,
410411 };
411412
412 fn formatToken(
413 ctx: TokenFormatContext,
414 comptime fmt: []const u8,
415 options: std.fmt.FormatOptions,
416 writer: anytype,
417 ) !void {
418 _ = fmt;
419 _ = options;
420
413 fn formatToken(ctx: TokenFormatContext, writer: *std.io.Writer) std.io.Writer.Error!void {
421414 switch (ctx.token.id) {
422415 .eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),
423416 else => {},
......@@ -441,7 +434,7 @@ pub const ErrorDetails = struct {
441434 code_page: SupportedCodePage,
442435 };
443436
444 fn fmtToken(self: ErrorDetails, source: []const u8) std.fmt.Formatter(formatToken) {
437 fn fmtToken(self: ErrorDetails, source: []const u8) std.fmt.Formatter(TokenFormatContext, formatToken) {
445438 return .{ .data = .{
446439 .token = self.token,
447440 .code_page = self.code_page,
......@@ -466,10 +459,14 @@ pub const ErrorDetails = struct {
466459 .hint => return,
467460 },
468461 .illegal_byte => {
469 return writer.print("character '{s}' is not allowed", .{std.fmt.fmtSliceEscapeUpper(self.token.slice(source))});
462 return writer.print("character '{f}' is not allowed", .{
463 std.ascii.hexEscape(self.token.slice(source), .upper),
464 });
470465 },
471466 .illegal_byte_outside_string_literals => {
472 return writer.print("character '{s}' is not allowed outside of string literals", .{std.fmt.fmtSliceEscapeUpper(self.token.slice(source))});
467 return writer.print("character '{f}' is not allowed outside of string literals", .{
468 std.ascii.hexEscape(self.token.slice(source), .upper),
469 });
473470 },
474471 .illegal_codepoint_outside_string_literals => {
475472 // This is somewhat hacky, but we know that:
......@@ -1106,7 +1103,7 @@ const CorrespondingLines = struct {
11061103 .code_page = err_details.code_page,
11071104 };
11081105 corresponding_lines.buffered_reader = BufferedReaderType{
1109 .unbuffered_reader = corresponding_lines.file.reader(),
1106 .unbuffered_reader = corresponding_lines.file.deprecatedReader(),
11101107 };
11111108 errdefer corresponding_lines.deinit();
11121109
lib/compiler/resinator/lex.zig+3-1
......@@ -237,7 +237,9 @@ pub const Lexer = struct {
237237 }
238238
239239 pub fn dump(self: *Self, token: *const Token) void {
240 std.debug.print("{s}:{d}: {s}\n", .{ @tagName(token.id), token.line_number, std.fmt.fmtSliceEscapeLower(token.slice(self.buffer)) });
240 std.debug.print("{s}:{d}: {f}\n", .{
241 @tagName(token.id), token.line_number, std.ascii.hexEscape(token.slice(self.buffer), .lower),
242 });
241243 }
242244
243245 pub const LexMethod = enum {
lib/compiler/resinator/main.zig+6-6
......@@ -29,7 +29,7 @@ pub fn main() !void {
2929 defer std.process.argsFree(allocator, args);
3030
3131 if (args.len < 2) {
32 try renderErrorMessage(stderr.writer(), stderr_config, .err, "expected zig lib dir as first argument", .{});
32 try renderErrorMessage(stderr.deprecatedWriter(), stderr_config, .err, "expected zig lib dir as first argument", .{});
3333 std.process.exit(1);
3434 }
3535 const zig_lib_dir = args[1];
......@@ -82,14 +82,14 @@ pub fn main() !void {
8282
8383 if (options.print_help_and_exit) {
8484 const stdout = std.fs.File.stdout();
85 try cli.writeUsage(stdout.writer(), "zig rc");
85 try cli.writeUsage(stdout.deprecatedWriter(), "zig rc");
8686 return;
8787 }
8888
8989 // Don't allow verbose when integrating with Zig via stdout
9090 options.verbose = false;
9191
92 const stdout_writer = std.fs.File.stdout().writer();
92 const stdout_writer = std.fs.File.stdout().deprecatedWriter();
9393 if (options.verbose) {
9494 try options.dumpVerbose(stdout_writer);
9595 try stdout_writer.writeByte('\n');
......@@ -290,7 +290,7 @@ pub fn main() !void {
290290 };
291291 defer depfile.close();
292292
293 const depfile_writer = depfile.writer();
293 const depfile_writer = depfile.deprecatedWriter();
294294 var depfile_buffered_writer = std.io.bufferedWriter(depfile_writer);
295295 switch (options.depfile_fmt) {
296296 .json => {
......@@ -645,7 +645,7 @@ const ErrorHandler = union(enum) {
645645 },
646646 .tty => {
647647 // extra newline to separate this line from the aro errors
648 try renderErrorMessage(std.fs.File.stderr().writer(), self.tty, .err, "{s}\n", .{fail_msg});
648 try renderErrorMessage(std.fs.File.stderr().deprecatedWriter(), self.tty, .err, "{s}\n", .{fail_msg});
649649 aro.Diagnostics.render(comp, self.tty);
650650 },
651651 }
......@@ -690,7 +690,7 @@ const ErrorHandler = union(enum) {
690690 try server.serveErrorBundle(error_bundle);
691691 },
692692 .tty => {
693 try renderErrorMessage(std.fs.File.stderr().writer(), self.tty, msg_type, format, args);
693 try renderErrorMessage(std.fs.File.stderr().deprecatedWriter(), self.tty, msg_type, format, args);
694694 },
695695 }
696696 }
lib/compiler/resinator/res.zig+13-31
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const assert = std.debug.assert;
23const rc = @import("rc.zig");
34const ResourceType = rc.ResourceType;
45const CommonResourceAttributes = rc.CommonResourceAttributes;
......@@ -163,14 +164,8 @@ pub const Language = packed struct(u16) {
163164 return @bitCast(self);
164165 }
165166
166 pub fn format(
167 language: Language,
168 comptime fmt: []const u8,
169 options: std.fmt.FormatOptions,
170 out_stream: anytype,
171 ) !void {
172 _ = fmt;
173 _ = options;
167 pub fn format(language: Language, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
168 comptime assert(fmt.len == 0);
174169 const language_id = language.asInt();
175170 const language_name = language_name: {
176171 if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {
......@@ -181,7 +176,7 @@ pub const Language = packed struct(u16) {
181176 }
182177 break :language_name "<UNKNOWN>";
183178 };
184 try out_stream.print("{s} (0x{X})", .{ language_name, language_id });
179 try w.print("{s} (0x{X})", .{ language_name, language_id });
185180 }
186181};
187182
......@@ -445,47 +440,34 @@ pub const NameOrOrdinal = union(enum) {
445440 }
446441 }
447442
448 pub fn format(
449 self: NameOrOrdinal,
450 comptime fmt: []const u8,
451 options: std.fmt.FormatOptions,
452 out_stream: anytype,
453 ) !void {
454 _ = fmt;
455 _ = options;
443 pub fn format(self: NameOrOrdinal, w: *std.io.Writer, comptime fmt: []const u8) !void {
444 comptime assert(fmt.len == 0);
456445 switch (self) {
457446 .name => |name| {
458 try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});
447 try w.print("{s}", .{std.unicode.fmtUtf16Le(name)});
459448 },
460449 .ordinal => |ordinal| {
461 try out_stream.print("{d}", .{ordinal});
450 try w.print("{d}", .{ordinal});
462451 },
463452 }
464453 }
465454
466 fn formatResourceType(
467 self: NameOrOrdinal,
468 comptime fmt: []const u8,
469 options: std.fmt.FormatOptions,
470 out_stream: anytype,
471 ) !void {
472 _ = fmt;
473 _ = options;
455 fn formatResourceType(self: NameOrOrdinal, w: *std.io.Writer) std.io.Writer.Error!void {
474456 switch (self) {
475457 .name => |name| {
476 try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});
458 try w.print("{s}", .{std.unicode.fmtUtf16Le(name)});
477459 },
478460 .ordinal => |ordinal| {
479461 if (std.enums.tagName(RT, @enumFromInt(ordinal))) |predefined_type_name| {
480 try out_stream.print("{s}", .{predefined_type_name});
462 try w.print("{s}", .{predefined_type_name});
481463 } else {
482 try out_stream.print("{d}", .{ordinal});
464 try w.print("{d}", .{ordinal});
483465 }
484466 },
485467 }
486468 }
487469
488 pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(formatResourceType) {
470 pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(NameOrOrdinal, formatResourceType) {
489471 return .{ .data = type_value };
490472 }
491473};
lib/compiler/test_runner.zig+1-1
......@@ -328,7 +328,7 @@ pub fn mainSimple() anyerror!void {
328328 passed += 1;
329329 }
330330 if (enable_print and print_summary) {
331 stderr.writer().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
331 stderr.deprecatedWriter().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
332332 }
333333 if (failed != 0) std.process.exit(1);
334334}
lib/docs/wasm/markdown.zig+1-1
......@@ -160,7 +160,7 @@ fn mainImpl() !void {
160160 var doc = try parser.endInput();
161161 defer doc.deinit(gpa);
162162
163 var stdout_buf = std.io.bufferedWriter(std.fs.File.stdout().writer());
163 var stdout_buf = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
164164 try doc.render(stdout_buf.writer());
165165 try stdout_buf.flush();
166166}
lib/docs/wasm/markdown/renderer.zig+3-9
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const Document = @import("Document.zig");
33const Node = Document.Node;
4const assert = std.debug.assert;
45
56/// A Markdown document renderer.
67///
......@@ -229,18 +230,11 @@ pub fn renderInlineNodeText(
229230 }
230231}
231232
232pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter(formatHtml) {
233pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) {
233234 return .{ .data = bytes };
234235}
235236
236fn formatHtml(
237 bytes: []const u8,
238 comptime fmt: []const u8,
239 options: std.fmt.FormatOptions,
240 writer: anytype,
241) !void {
242 _ = fmt;
243 _ = options;
237fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
244238 for (bytes) |b| {
245239 switch (b) {
246240 '<' => try writer.writeAll("&lt;"),
lib/init/src/root.zig+1-1
......@@ -5,7 +5,7 @@ pub fn bufferedPrint() !void {
55 // Stdout is for the actual output of your application, for example if you
66 // are implementing gzip, then only the compressed bytes should be sent to
77 // stdout, not any debugging messages.
8 const stdout_file = std.fs.File.stdout().writer();
8 const stdout_file = std.fs.File.stdout().deprecatedWriter();
99 // Buffering can improve performance significantly in print-heavy programs.
1010 var bw = std.io.bufferedWriter(stdout_file);
1111 const stdout = bw.writer();
lib/std/Build.zig+6-6
......@@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8
17451745 return true;
17461746 },
17471747 .lazy_path, .lazy_path_list => {
1748 log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });
1748 log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{f}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });
17491749 return true;
17501750 },
17511751 }
......@@ -2059,7 +2059,7 @@ pub fn runAllowFail(
20592059 try Step.handleVerbose2(b, null, child.env_map, argv);
20602060 try child.spawn();
20612061
2062 const stdout = child.stdout.?.reader().readAllAlloc(b.allocator, max_output_size) catch {
2062 const stdout = child.stdout.?.deprecatedReader().readAllAlloc(b.allocator, max_output_size) catch {
20632063 return error.ReadFailure;
20642064 };
20652065 errdefer b.allocator.free(stdout);
......@@ -2770,7 +2770,7 @@ fn dumpBadDirnameHelp(
27702770 defer debug.unlockStdErr();
27712771
27722772 const stderr: fs.File = .stderr();
2773 const w = stderr.writer();
2773 const w = stderr.deprecatedWriter();
27742774 try w.print(msg, args);
27752775
27762776 const tty_config = std.io.tty.detectConfig(stderr);
......@@ -2785,7 +2785,7 @@ fn dumpBadDirnameHelp(
27852785
27862786 if (asking_step) |as| {
27872787 tty_config.setColor(w, .red) catch {};
2788 try stderr.writer().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
2788 try stderr.deprecatedWriter().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
27892789 tty_config.setColor(w, .reset) catch {};
27902790
27912791 as.dump(stderr);
......@@ -2803,7 +2803,7 @@ pub fn dumpBadGetPathHelp(
28032803 src_builder: *Build,
28042804 asking_step: ?*Step,
28052805) anyerror!void {
2806 const w = stderr.writer();
2806 const w = stderr.deprecatedWriter();
28072807 try w.print(
28082808 \\getPath() was called on a GeneratedFile that wasn't built yet.
28092809 \\ source package path: {s}
......@@ -2822,7 +2822,7 @@ pub fn dumpBadGetPathHelp(
28222822 s.dump(stderr);
28232823 if (asking_step) |as| {
28242824 tty_config.setColor(w, .red) catch {};
2825 try stderr.writer().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
2825 try stderr.deprecatedWriter().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
28262826 tty_config.setColor(w, .reset) catch {};
28272827
28282828 as.dump(stderr);
lib/std/Build/Cache.zig+30-38
......@@ -68,7 +68,7 @@ const PrefixedPath = struct {
6868
6969fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
7070 const gpa = cache.gpa;
71 const resolved_path = try fs.path.resolve(gpa, &[_][]const u8{file_path});
71 const resolved_path = try fs.path.resolve(gpa, &.{file_path});
7272 errdefer gpa.free(resolved_path);
7373 return findPrefixResolved(cache, resolved_path);
7474}
......@@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3);
132132/// Initial state with random bytes, that can be copied.
133133/// Refresh this with new random bytes when the manifest
134134/// format is modified in a non-backwards-compatible way.
135pub const hasher_init: Hasher = Hasher.init(&[_]u8{
135pub const hasher_init: Hasher = Hasher.init(&.{
136136 0x33, 0x52, 0xa2, 0x84,
137137 0xcf, 0x17, 0x56, 0x57,
138138 0x01, 0xbb, 0xcd, 0xe4,
......@@ -286,11 +286,8 @@ pub const HashHelper = struct {
286286
287287pub fn binToHex(bin_digest: BinDigest) HexDigest {
288288 var out_digest: HexDigest = undefined;
289 _ = fmt.bufPrint(
290 &out_digest,
291 "{s}",
292 .{fmt.fmtSliceHexLower(&bin_digest)},
293 ) catch unreachable;
289 var w: std.io.Writer = .fixed(&out_digest);
290 w.printHex(&bin_digest, .lower) catch unreachable;
294291 return out_digest;
295292}
296293
......@@ -337,7 +334,6 @@ pub const Manifest = struct {
337334 manifest_create: fs.File.OpenError,
338335 manifest_read: fs.File.ReadError,
339336 manifest_lock: fs.File.LockError,
340 manifest_seek: fs.File.SeekError,
341337 file_open: FileOp,
342338 file_stat: FileOp,
343339 file_read: FileOp,
......@@ -611,12 +607,6 @@ pub const Manifest = struct {
611607 var file = self.files.pop().?;
612608 file.key.deinit(self.cache.gpa);
613609 }
614 // Also, seek the file back to the start.
615 self.manifest_file.?.seekTo(0) catch |err| {
616 self.diagnostic = .{ .manifest_seek = err };
617 return error.CacheCheckFailed;
618 };
619
620610 switch (try self.hitWithCurrentLock()) {
621611 .hit => break :hit,
622612 .miss => |m| break :digests m.file_digests_populated,
......@@ -661,9 +651,8 @@ pub const Manifest = struct {
661651 return true;
662652 }
663653
664 /// Assumes that `self.hash.hasher` has been updated only with the original digest, that
665 /// `self.files` contains only the original input files, and that `self.manifest_file.?` is
666 /// seeked to the start of the file.
654 /// Assumes that `self.hash.hasher` has been updated only with the original digest and that
655 /// `self.files` contains only the original input files.
667656 fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) {
668657 hit,
669658 miss: struct {
......@@ -672,12 +661,13 @@ pub const Manifest = struct {
672661 } {
673662 const gpa = self.cache.gpa;
674663 const input_file_count = self.files.entries.len;
675
676 const file_contents = self.manifest_file.?.reader().readAllAlloc(gpa, manifest_file_size_max) catch |err| switch (err) {
664 var manifest_reader = self.manifest_file.?.reader(&.{}); // Reads positionally from zero.
665 const limit: std.io.Limit = .limited(manifest_file_size_max);
666 const file_contents = manifest_reader.interface.allocRemaining(gpa, limit) catch |err| switch (err) {
677667 error.OutOfMemory => return error.OutOfMemory,
678668 error.StreamTooLong => return error.OutOfMemory,
679 else => |e| {
680 self.diagnostic = .{ .manifest_read = e };
669 error.ReadFailed => {
670 self.diagnostic = .{ .manifest_read = manifest_reader.err.? };
681671 return error.CacheCheckFailed;
682672 },
683673 };
......@@ -1063,14 +1053,17 @@ pub const Manifest = struct {
10631053 }
10641054
10651055 fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
1066 const dep_file_contents = try dir.readFileAlloc(self.cache.gpa, dep_file_basename, manifest_file_size_max);
1067 defer self.cache.gpa.free(dep_file_contents);
1056 const gpa = self.cache.gpa;
1057 const dep_file_contents = try dir.readFileAlloc(gpa, dep_file_basename, manifest_file_size_max);
1058 defer gpa.free(dep_file_contents);
10681059
1069 var error_buf = std.ArrayList(u8).init(self.cache.gpa);
1070 defer error_buf.deinit();
1060 var error_buf: std.ArrayListUnmanaged(u8) = .empty;
1061 defer error_buf.deinit(gpa);
10711062
1072 var it: DepTokenizer = .{ .bytes = dep_file_contents };
1063 var resolve_buf: std.ArrayListUnmanaged(u8) = .empty;
1064 defer resolve_buf.deinit(gpa);
10731065
1066 var it: DepTokenizer = .{ .bytes = dep_file_contents };
10741067 while (it.next()) |token| {
10751068 switch (token) {
10761069 // We don't care about targets, we only want the prereqs
......@@ -1080,16 +1073,14 @@ pub const Manifest = struct {
10801073 _ = try self.addFile(file_path, null);
10811074 } else try self.addFilePost(file_path),
10821075 .prereq_must_resolve => {
1083 var resolve_buf = std.ArrayList(u8).init(self.cache.gpa);
1084 defer resolve_buf.deinit();
1085
1086 try token.resolve(resolve_buf.writer());
1076 resolve_buf.clearRetainingCapacity();
1077 try token.resolve(gpa, &resolve_buf);
10871078 if (self.manifest_file == null) {
10881079 _ = try self.addFile(resolve_buf.items, null);
10891080 } else try self.addFilePost(resolve_buf.items);
10901081 },
10911082 else => |err| {
1092 try err.printError(error_buf.writer());
1083 try err.printError(gpa, &error_buf);
10931084 log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items });
10941085 return error.InvalidDepFile;
10951086 },
......@@ -1127,24 +1118,25 @@ pub const Manifest = struct {
11271118 if (self.manifest_dirty) {
11281119 self.manifest_dirty = false;
11291120
1130 var contents = std.ArrayList(u8).init(self.cache.gpa);
1131 defer contents.deinit();
1121 const gpa = self.cache.gpa;
1122 var contents: std.ArrayListUnmanaged(u8) = .empty;
1123 defer contents.deinit(gpa);
11321124
1133 const writer = contents.writer();
1134 try writer.writeAll(manifest_header ++ "\n");
1125 try contents.appendSlice(gpa, manifest_header ++ "\n");
11351126 for (self.files.keys()) |file| {
1136 try writer.print("{d} {d} {d} {} {d} {s}\n", .{
1127 try contents.print(gpa, "{d} {d} {d} {x} {d} {s}\n", .{
11371128 file.stat.size,
11381129 file.stat.inode,
11391130 file.stat.mtime,
1140 fmt.fmtSliceHexLower(&file.bin_digest),
1131 &file.bin_digest,
11411132 file.prefixed_path.prefix,
11421133 file.prefixed_path.sub_path,
11431134 });
11441135 }
11451136
11461137 try manifest_file.setEndPos(contents.items.len);
1147 try manifest_file.pwriteAll(contents.items, 0);
1138 var pos: usize = 0;
1139 while (pos < contents.items.len) pos += try manifest_file.pwrite(contents.items[pos..], pos);
11481140 }
11491141
11501142 if (self.want_shared_lock) {
lib/std/Build/Cache/DepTokenizer.zig+43-158
......@@ -7,6 +7,7 @@ state: State = .lhs,
77const std = @import("std");
88const testing = std.testing;
99const assert = std.debug.assert;
10const Allocator = std.mem.Allocator;
1011
1112pub fn next(self: *Tokenizer) ?Token {
1213 var start = self.index;
......@@ -362,7 +363,7 @@ pub const Token = union(enum) {
362363 };
363364
364365 /// Resolve escapes in target or prereq. Only valid with .target_must_resolve or .prereq_must_resolve.
365 pub fn resolve(self: Token, writer: anytype) @TypeOf(writer).Error!void {
366 pub fn resolve(self: Token, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!void {
366367 switch (self) {
367368 .target_must_resolve => |bytes| {
368369 var state: enum { start, escape, dollar } = .start;
......@@ -372,27 +373,27 @@ pub const Token = union(enum) {
372373 switch (c) {
373374 '\\' => state = .escape,
374375 '$' => state = .dollar,
375 else => try writer.writeByte(c),
376 else => try list.append(gpa, c),
376377 }
377378 },
378379 .escape => {
379380 switch (c) {
380381 ' ', '#', '\\' => {},
381382 '$' => {
382 try writer.writeByte('\\');
383 try list.append(gpa, '\\');
383384 state = .dollar;
384385 continue;
385386 },
386 else => try writer.writeByte('\\'),
387 else => try list.append(gpa, '\\'),
387388 }
388 try writer.writeByte(c);
389 try list.append(gpa, c);
389390 state = .start;
390391 },
391392 .dollar => {
392 try writer.writeByte('$');
393 try list.append(gpa, '$');
393394 switch (c) {
394395 '$' => {},
395 else => try writer.writeByte(c),
396 else => try list.append(gpa, c),
396397 }
397398 state = .start;
398399 },
......@@ -406,19 +407,19 @@ pub const Token = union(enum) {
406407 .start => {
407408 switch (c) {
408409 '\\' => state = .escape,
409 else => try writer.writeByte(c),
410 else => try list.append(gpa, c),
410411 }
411412 },
412413 .escape => {
413414 switch (c) {
414415 ' ' => {},
415416 '\\' => {
416 try writer.writeByte(c);
417 try list.append(gpa, c);
417418 continue;
418419 },
419 else => try writer.writeByte('\\'),
420 else => try list.append(gpa, '\\'),
420421 }
421 try writer.writeByte(c);
422 try list.append(gpa, c);
422423 state = .start;
423424 },
424425 }
......@@ -428,20 +429,20 @@ pub const Token = union(enum) {
428429 }
429430 }
430431
431 pub fn printError(self: Token, writer: anytype) @TypeOf(writer).Error!void {
432 pub fn printError(self: Token, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!void {
432433 switch (self) {
433434 .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error
434435 .incomplete_quoted_prerequisite,
435436 .incomplete_target,
436437 => |index_and_bytes| {
437 try writer.print("{s} '", .{self.errStr()});
438 try list.print(gpa, "{s} '", .{self.errStr()});
438439 if (self == .incomplete_target) {
439440 const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };
440 try tmp.resolve(writer);
441 try tmp.resolve(gpa, list);
441442 } else {
442 try printCharValues(writer, index_and_bytes.bytes);
443 try printCharValues(gpa, list, index_and_bytes.bytes);
443444 }
444 try writer.print("' at position {d}", .{index_and_bytes.index});
445 try list.print(gpa, "' at position {d}", .{index_and_bytes.index});
445446 },
446447 .invalid_target,
447448 .bad_target_escape,
......@@ -450,9 +451,9 @@ pub const Token = union(enum) {
450451 .incomplete_escape,
451452 .expected_colon,
452453 => |index_and_char| {
453 try writer.writeAll("illegal char ");
454 try printUnderstandableChar(writer, index_and_char.char);
455 try writer.print(" at position {d}: {s}", .{ index_and_char.index, self.errStr() });
454 try list.appendSlice(gpa, "illegal char ");
455 try printUnderstandableChar(gpa, list, index_and_char.char);
456 try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() });
456457 },
457458 }
458459 }
......@@ -1026,41 +1027,41 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
10261027 defer arena_allocator.deinit();
10271028
10281029 var it: Tokenizer = .{ .bytes = input };
1029 var buffer = std.ArrayList(u8).init(arena);
1030 var resolve_buf = std.ArrayList(u8).init(arena);
1030 var buffer: std.ArrayListUnmanaged(u8) = .empty;
1031 var resolve_buf: std.ArrayListUnmanaged(u8) = .empty;
10311032 var i: usize = 0;
10321033 while (it.next()) |token| {
1033 if (i != 0) try buffer.appendSlice("\n");
1034 if (i != 0) try buffer.appendSlice(arena, "\n");
10341035 switch (token) {
10351036 .target, .prereq => |bytes| {
1036 try buffer.appendSlice(@tagName(token));
1037 try buffer.appendSlice(" = {");
1037 try buffer.appendSlice(arena, @tagName(token));
1038 try buffer.appendSlice(arena, " = {");
10381039 for (bytes) |b| {
1039 try buffer.append(printable_char_tab[b]);
1040 try buffer.append(arena, printable_char_tab[b]);
10401041 }
1041 try buffer.appendSlice("}");
1042 try buffer.appendSlice(arena, "}");
10421043 },
10431044 .target_must_resolve => {
1044 try buffer.appendSlice("target = {");
1045 try token.resolve(resolve_buf.writer());
1045 try buffer.appendSlice(arena, "target = {");
1046 try token.resolve(arena, &resolve_buf);
10461047 for (resolve_buf.items) |b| {
1047 try buffer.append(printable_char_tab[b]);
1048 try buffer.append(arena, printable_char_tab[b]);
10481049 }
10491050 resolve_buf.items.len = 0;
1050 try buffer.appendSlice("}");
1051 try buffer.appendSlice(arena, "}");
10511052 },
10521053 .prereq_must_resolve => {
1053 try buffer.appendSlice("prereq = {");
1054 try token.resolve(resolve_buf.writer());
1054 try buffer.appendSlice(arena, "prereq = {");
1055 try token.resolve(arena, &resolve_buf);
10551056 for (resolve_buf.items) |b| {
1056 try buffer.append(printable_char_tab[b]);
1057 try buffer.append(arena, printable_char_tab[b]);
10571058 }
10581059 resolve_buf.items.len = 0;
1059 try buffer.appendSlice("}");
1060 try buffer.appendSlice(arena, "}");
10601061 },
10611062 else => {
1062 try buffer.appendSlice("ERROR: ");
1063 try token.printError(buffer.writer());
1063 try buffer.appendSlice(arena, "ERROR: ");
1064 try token.printError(arena, &buffer);
10641065 break;
10651066 },
10661067 }
......@@ -1072,134 +1073,18 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
10721073 return;
10731074 }
10741075
1075 const out = std.fs.File.stderr().writer();
1076
1077 try out.writeAll("\n");
1078 try printSection(out, "<<<< input", input);
1079 try printSection(out, "==== expect", expect);
1080 try printSection(out, ">>>> got", buffer.items);
1081 try printRuler(out);
1082
1083 try testing.expect(false);
1084}
1085
1086fn printSection(out: anytype, label: []const u8, bytes: []const u8) !void {
1087 try printLabel(out, label, bytes);
1088 try hexDump(out, bytes);
1089 try printRuler(out);
1090 try out.writeAll(bytes);
1091 try out.writeAll("\n");
1092}
1093
1094fn printLabel(out: anytype, label: []const u8, bytes: []const u8) !void {
1095 var buf: [80]u8 = undefined;
1096 const text = try std.fmt.bufPrint(buf[0..], "{s} {d} bytes ", .{ label, bytes.len });
1097 try out.writeAll(text);
1098 var i: usize = text.len;
1099 const end = 79;
1100 while (i < end) : (i += 1) {
1101 try out.writeAll(&[_]u8{label[0]});
1102 }
1103 try out.writeAll("\n");
1104}
1105
1106fn printRuler(out: anytype) !void {
1107 var i: usize = 0;
1108 const end = 79;
1109 while (i < end) : (i += 1) {
1110 try out.writeAll("-");
1111 }
1112 try out.writeAll("\n");
1113}
1114
1115fn hexDump(out: anytype, bytes: []const u8) !void {
1116 const n16 = bytes.len >> 4;
1117 var line: usize = 0;
1118 var offset: usize = 0;
1119 while (line < n16) : (line += 1) {
1120 try hexDump16(out, offset, bytes[offset..][0..16]);
1121 offset += 16;
1122 }
1123
1124 const n = bytes.len & 0x0f;
1125 if (n > 0) {
1126 try printDecValue(out, offset, 8);
1127 try out.writeAll(":");
1128 try out.writeAll(" ");
1129 const end1 = @min(offset + n, offset + 8);
1130 for (bytes[offset..end1]) |b| {
1131 try out.writeAll(" ");
1132 try printHexValue(out, b, 2);
1133 }
1134 const end2 = offset + n;
1135 if (end2 > end1) {
1136 try out.writeAll(" ");
1137 for (bytes[end1..end2]) |b| {
1138 try out.writeAll(" ");
1139 try printHexValue(out, b, 2);
1140 }
1141 }
1142 const short = 16 - n;
1143 var i: usize = 0;
1144 while (i < short) : (i += 1) {
1145 try out.writeAll(" ");
1146 }
1147 if (end2 > end1) {
1148 try out.writeAll(" |");
1149 } else {
1150 try out.writeAll(" |");
1151 }
1152 try printCharValues(out, bytes[offset..end2]);
1153 try out.writeAll("|\n");
1154 offset += n;
1155 }
1156
1157 try printDecValue(out, offset, 8);
1158 try out.writeAll(":");
1159 try out.writeAll("\n");
1076 try testing.expectEqualStrings(expect, buffer.items);
11601077}
11611078
1162fn hexDump16(out: anytype, offset: usize, bytes: []const u8) !void {
1163 try printDecValue(out, offset, 8);
1164 try out.writeAll(":");
1165 try out.writeAll(" ");
1166 for (bytes[0..8]) |b| {
1167 try out.writeAll(" ");
1168 try printHexValue(out, b, 2);
1169 }
1170 try out.writeAll(" ");
1171 for (bytes[8..16]) |b| {
1172 try out.writeAll(" ");
1173 try printHexValue(out, b, 2);
1174 }
1175 try out.writeAll(" |");
1176 try printCharValues(out, bytes);
1177 try out.writeAll("|\n");
1178}
1179
1180fn printDecValue(out: anytype, value: u64, width: u8) !void {
1181 var buffer: [20]u8 = undefined;
1182 const len = std.fmt.formatIntBuf(buffer[0..], value, 10, .lower, .{ .width = width, .fill = '0' });
1183 try out.writeAll(buffer[0..len]);
1184}
1185
1186fn printHexValue(out: anytype, value: u64, width: u8) !void {
1187 var buffer: [16]u8 = undefined;
1188 const len = std.fmt.formatIntBuf(buffer[0..], value, 16, .lower, .{ .width = width, .fill = '0' });
1189 try out.writeAll(buffer[0..len]);
1190}
1191
1192fn printCharValues(out: anytype, bytes: []const u8) !void {
1193 for (bytes) |b| {
1194 try out.writeAll(&[_]u8{printable_char_tab[b]});
1195 }
1079fn printCharValues(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), bytes: []const u8) !void {
1080 for (bytes) |b| try list.append(gpa, printable_char_tab[b]);
11961081}
11971082
1198fn printUnderstandableChar(out: anytype, char: u8) !void {
1083fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), char: u8) !void {
11991084 if (std.ascii.isPrint(char)) {
1200 try out.print("'{c}'", .{char});
1085 try list.print(gpa, "'{c}'", .{char});
12011086 } else {
1202 try out.print("\\x{X:0>2}", .{char});
1087 try list.print(gpa, "\\x{X:0>2}", .{char});
12031088 }
12041089}
12051090
lib/std/Build/Cache/Directory.zig+3-8
......@@ -1,5 +1,6 @@
11const Directory = @This();
22const std = @import("../../std.zig");
3const assert = std.debug.assert;
34const fs = std.fs;
45const fmt = std.fmt;
56const Allocator = std.mem.Allocator;
......@@ -55,14 +56,8 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
5556 self.* = undefined;
5657}
5758
58pub fn format(
59 self: Directory,
60 comptime fmt_string: []const u8,
61 options: fmt.FormatOptions,
62 writer: anytype,
63) !void {
64 _ = options;
65 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);
59pub fn format(self: Directory, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
60 comptime assert(f.len == 0);
6661 if (self.path) |p| {
6762 try writer.writeAll(p);
6863 try writer.writeAll(fs.path.sep_str);
lib/std/Build/Cache/Path.zig+20-25
......@@ -1,3 +1,10 @@
1const Path = @This();
2const std = @import("../../std.zig");
3const assert = std.debug.assert;
4const fs = std.fs;
5const Allocator = std.mem.Allocator;
6const Cache = std.Build.Cache;
7
18root_dir: Cache.Directory,
29/// The path, relative to the root dir, that this `Path` represents.
310/// Empty string means the root_dir is the path.
......@@ -133,38 +140,32 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {
133140}
134141
135142pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {
136 return std.fmt.allocPrint(allocator, "{}", .{p});
143 return std.fmt.allocPrint(allocator, "{f}", .{p});
137144}
138145
139146pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
140 return std.fmt.allocPrintZ(allocator, "{}", .{p});
147 return std.fmt.allocPrintSentinel(allocator, "{f}", .{p}, 0);
141148}
142149
143pub fn format(
144 self: Path,
145 comptime fmt_string: []const u8,
146 options: std.fmt.FormatOptions,
147 writer: anytype,
148) !void {
149 if (fmt_string.len == 1) {
150pub fn format(self: Path, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
151 if (f.len == 1) {
150152 // Quote-escape the string.
151 const stringEscape = std.zig.stringEscape;
152 const f = switch (fmt_string[0]) {
153 'q' => "",
154 '\'' => "\'",
155 else => @compileError("unsupported format string: " ++ fmt_string),
153 const zigEscape = switch (f[0]) {
154 'q' => std.zig.stringEscape,
155 '\'' => std.zig.charEscape,
156 else => @compileError("unsupported format string: " ++ f),
156157 };
157158 if (self.root_dir.path) |p| {
158 try stringEscape(p, f, options, writer);
159 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, f, options, writer);
159 try zigEscape(p, writer);
160 if (self.sub_path.len > 0) try zigEscape(fs.path.sep_str, writer);
160161 }
161162 if (self.sub_path.len > 0) {
162 try stringEscape(self.sub_path, f, options, writer);
163 try zigEscape(self.sub_path, writer);
163164 }
164165 return;
165166 }
166 if (fmt_string.len > 0)
167 std.fmt.invalidFmtError(fmt_string, self);
167 if (f.len > 0)
168 std.fmt.invalidFmtError(f, self);
168169 if (std.fs.path.isAbsolute(self.sub_path)) {
169170 try writer.writeAll(self.sub_path);
170171 return;
......@@ -223,9 +224,3 @@ pub const TableAdapter = struct {
223224 return a.eql(b);
224225 }
225226};
226
227const Path = @This();
228const std = @import("../../std.zig");
229const fs = std.fs;
230const Allocator = std.mem.Allocator;
231const Cache = std.Build.Cache;
lib/std/Build/Fuzz/WebServer.zig+9-9
......@@ -170,7 +170,7 @@ fn serveFile(
170170 // We load the file with every request so that the user can make changes to the file
171171 // and refresh the HTML page without restarting this server.
172172 const file_contents = ws.zig_lib_directory.handle.readFileAlloc(gpa, name, 10 * 1024 * 1024) catch |err| {
173 log.err("failed to read '{}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });
173 log.err("failed to read '{f}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });
174174 return error.AlreadyReported;
175175 };
176176 defer gpa.free(file_contents);
......@@ -251,10 +251,10 @@ fn buildWasmBinary(
251251 "-fsingle-threaded", //
252252 "--dep", "Walk", //
253253 "--dep", "html_render", //
254 try std.fmt.allocPrint(arena, "-Mroot={}", .{main_src_path}), //
255 try std.fmt.allocPrint(arena, "-MWalk={}", .{walk_src_path}), //
254 try std.fmt.allocPrint(arena, "-Mroot={f}", .{main_src_path}), //
255 try std.fmt.allocPrint(arena, "-MWalk={f}", .{walk_src_path}), //
256256 "--dep", "Walk", //
257 try std.fmt.allocPrint(arena, "-Mhtml_render={}", .{html_render_src_path}), //
257 try std.fmt.allocPrint(arena, "-Mhtml_render={f}", .{html_render_src_path}), //
258258 "--listen=-",
259259 });
260260
......@@ -526,7 +526,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
526526
527527 for (deduped_paths) |joined_path| {
528528 var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
529 log.err("failed to open {}: {s}", .{ joined_path, @errorName(err) });
529 log.err("failed to open {f}: {s}", .{ joined_path, @errorName(err) });
530530 continue;
531531 };
532532 defer file.close();
......@@ -604,7 +604,7 @@ fn prepareTables(
604604
605605 const rebuilt_exe_path = run_step.rebuilt_executable.?;
606606 var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {
607 log.err("step '{s}': failed to load debug information for '{}': {s}", .{
607 log.err("step '{s}': failed to load debug information for '{f}': {s}", .{
608608 run_step.step.name, rebuilt_exe_path, @errorName(err),
609609 });
610610 return error.AlreadyReported;
......@@ -616,7 +616,7 @@ fn prepareTables(
616616 .sub_path = "v/" ++ std.fmt.hex(coverage_id),
617617 };
618618 var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| {
619 log.err("step '{s}': failed to load coverage file '{}': {s}", .{
619 log.err("step '{s}': failed to load coverage file '{f}': {s}", .{
620620 run_step.step.name, coverage_file_path, @errorName(err),
621621 });
622622 return error.AlreadyReported;
......@@ -624,7 +624,7 @@ fn prepareTables(
624624 defer coverage_file.close();
625625
626626 const file_size = coverage_file.getEndPos() catch |err| {
627 log.err("unable to check len of coverage file '{}': {s}", .{ coverage_file_path, @errorName(err) });
627 log.err("unable to check len of coverage file '{f}': {s}", .{ coverage_file_path, @errorName(err) });
628628 return error.AlreadyReported;
629629 };
630630
......@@ -636,7 +636,7 @@ fn prepareTables(
636636 coverage_file.handle,
637637 0,
638638 ) catch |err| {
639 log.err("failed to map coverage file '{}': {s}", .{ coverage_file_path, @errorName(err) });
639 log.err("failed to map coverage file '{f}': {s}", .{ coverage_file_path, @errorName(err) });
640640 return error.AlreadyReported;
641641 };
642642 gop.value_ptr.mapped_memory = mapped_memory;
lib/std/Build/Module.zig+1-1
......@@ -186,7 +186,7 @@ pub const IncludeDir = union(enum) {
186186 .embed_path => |lazy_path| {
187187 // Special case: this is a single arg.
188188 const resolved = lazy_path.getPath3(b, asking_step);
189 const arg = b.fmt("--embed-dir={}", .{resolved});
189 const arg = b.fmt("--embed-dir={f}", .{resolved});
190190 return zig_args.append(arg);
191191 },
192192 };
lib/std/Build/Step.zig+5-4
......@@ -287,7 +287,8 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
287287
288288/// For debugging purposes, prints identifying information about this Step.
289289pub fn dump(step: *Step, file: std.fs.File) void {
290 const w = file.writer();
290 var fw = file.writer(&.{});
291 const w = &fw.interface;
291292 const tty_config = std.io.tty.detectConfig(file);
292293 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
293294 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
......@@ -482,9 +483,9 @@ pub fn evalZigProcess(
482483pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
483484 const b = s.owner;
484485 const src_path = src_lazy_path.getPath3(b, s);
485 try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{}", .{src_path}), dest_path });
486 try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{f}", .{src_path}), dest_path });
486487 return src_path.root_dir.handle.updateFile(src_path.sub_path, std.fs.cwd(), dest_path, .{}) catch |err| {
487 return s.fail("unable to update file from '{}' to '{s}': {s}", .{
488 return s.fail("unable to update file from '{f}' to '{s}': {s}", .{
488489 src_path, dest_path, @errorName(err),
489490 });
490491 };
......@@ -821,7 +822,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac
821822 switch (err) {
822823 error.CacheCheckFailed => switch (man.diagnostic) {
823824 .none => unreachable,
824 .manifest_create, .manifest_read, .manifest_lock, .manifest_seek => |e| return s.fail("failed to check cache: {s} {s}", .{
825 .manifest_create, .manifest_read, .manifest_lock => |e| return s.fail("failed to check cache: {s} {s}", .{
825826 @tagName(man.diagnostic), @errorName(e),
826827 }),
827828 .file_open, .file_stat, .file_read, .file_hash => |op| {
lib/std/Build/Step/CheckObject.zig+562-680
......@@ -6,6 +6,7 @@ const macho = std.macho;
66const math = std.math;
77const mem = std.mem;
88const testing = std.testing;
9const Writer = std.io.Writer;
910
1011const CheckObject = @This();
1112
......@@ -28,14 +29,14 @@ pub fn create(
2829 const gpa = owner.allocator;
2930 const check_object = gpa.create(CheckObject) catch @panic("OOM");
3031 check_object.* = .{
31 .step = Step.init(.{
32 .step = .init(.{
3233 .id = base_id,
3334 .name = "CheckObject",
3435 .owner = owner,
3536 .makeFn = make,
3637 }),
3738 .source = source.dupe(owner),
38 .checks = std.ArrayList(Check).init(gpa),
39 .checks = .init(gpa),
3940 .obj_format = obj_format,
4041 };
4142 check_object.source.addStepDependencies(&check_object.step);
......@@ -74,13 +75,13 @@ const Action = struct {
7475 b: *std.Build,
7576 step: *Step,
7677 haystack: []const u8,
77 global_vars: anytype,
78 global_vars: *std.StringHashMap(u64),
7879 ) !bool {
7980 assert(act.tag == .extract);
8081 const hay = mem.trim(u8, haystack, " ");
8182 const phrase = mem.trim(u8, act.phrase.resolve(b, step), " ");
8283
83 var candidate_vars = std.ArrayList(struct { name: []const u8, value: u64 }).init(b.allocator);
84 var candidate_vars: std.ArrayList(struct { name: []const u8, value: u64 }) = .init(b.allocator);
8485 var hay_it = mem.tokenizeScalar(u8, hay, ' ');
8586 var needle_it = mem.tokenizeScalar(u8, phrase, ' ');
8687
......@@ -153,11 +154,11 @@ const Action = struct {
153154 /// Will return true if the `phrase` is correctly parsed into an RPN program and
154155 /// its reduced, computed value compares using `op` with the expected value, either
155156 /// a literal or another extracted variable.
156 fn computeCmp(act: Action, b: *std.Build, step: *Step, global_vars: anytype) !bool {
157 fn computeCmp(act: Action, b: *std.Build, step: *Step, global_vars: std.StringHashMap(u64)) !bool {
157158 const gpa = step.owner.allocator;
158159 const phrase = act.phrase.resolve(b, step);
159 var op_stack = std.ArrayList(enum { add, sub, mod, mul }).init(gpa);
160 var values = std.ArrayList(u64).init(gpa);
160 var op_stack: std.ArrayList(enum { add, sub, mod, mul }) = .init(gpa);
161 var values: std.ArrayList(u64) = .init(gpa);
161162
162163 var it = mem.tokenizeScalar(u8, phrase, ' ');
163164 while (it.next()) |next| {
......@@ -230,17 +231,15 @@ const ComputeCompareExpected = struct {
230231 },
231232
232233 pub fn format(
233 value: @This(),
234 value: ComputeCompareExpected,
235 bw: *Writer,
234236 comptime fmt: []const u8,
235 options: std.fmt.FormatOptions,
236 writer: anytype,
237237 ) !void {
238238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
239 _ = options;
240 try writer.print("{s} ", .{@tagName(value.op)});
239 try bw.print("{s} ", .{@tagName(value.op)});
241240 switch (value.value) {
242 .variable => |name| try writer.writeAll(name),
243 .literal => |x| try writer.print("{x}", .{x}),
241 .variable => |name| try bw.writeAll(name),
242 .literal => |x| try bw.print("{x}", .{x}),
244243 }
245244 }
246245};
......@@ -248,56 +247,63 @@ const ComputeCompareExpected = struct {
248247const Check = struct {
249248 kind: Kind,
250249 payload: Payload,
251 data: std.ArrayList(u8),
252 actions: std.ArrayList(Action),
250 allocator: Allocator,
251 data: std.ArrayListUnmanaged(u8),
252 actions: std.ArrayListUnmanaged(Action),
253253
254254 fn create(allocator: Allocator, kind: Kind) Check {
255255 return .{
256256 .kind = kind,
257257 .payload = .{ .none = {} },
258 .data = std.ArrayList(u8).init(allocator),
259 .actions = std.ArrayList(Action).init(allocator),
258 .allocator = allocator,
259 .data = .empty,
260 .actions = .empty,
260261 };
261262 }
262263
263 fn dumpSection(allocator: Allocator, name: [:0]const u8) Check {
264 var check = Check.create(allocator, .dump_section);
264 fn dumpSection(gpa: Allocator, name: [:0]const u8) Check {
265 var check = Check.create(gpa, .dump_section);
265266 const off: u32 = @intCast(check.data.items.len);
266 check.data.writer().print("{s}\x00", .{name}) catch @panic("OOM");
267 check.data.print(gpa, "{s}\x00", .{name}) catch @panic("OOM");
267268 check.payload = .{ .dump_section = off };
268269 return check;
269270 }
270271
271272 fn extract(check: *Check, phrase: SearchPhrase) void {
272 check.actions.append(.{
273 const gpa = check.allocator;
274 check.actions.append(gpa, .{
273275 .tag = .extract,
274276 .phrase = phrase,
275277 }) catch @panic("OOM");
276278 }
277279
278280 fn exact(check: *Check, phrase: SearchPhrase) void {
279 check.actions.append(.{
281 const gpa = check.allocator;
282 check.actions.append(gpa, .{
280283 .tag = .exact,
281284 .phrase = phrase,
282285 }) catch @panic("OOM");
283286 }
284287
285288 fn contains(check: *Check, phrase: SearchPhrase) void {
286 check.actions.append(.{
289 const gpa = check.allocator;
290 check.actions.append(gpa, .{
287291 .tag = .contains,
288292 .phrase = phrase,
289293 }) catch @panic("OOM");
290294 }
291295
292296 fn notPresent(check: *Check, phrase: SearchPhrase) void {
293 check.actions.append(.{
297 const gpa = check.allocator;
298 check.actions.append(gpa, .{
294299 .tag = .not_present,
295300 .phrase = phrase,
296301 }) catch @panic("OOM");
297302 }
298303
299304 fn computeCmp(check: *Check, phrase: SearchPhrase, expected: ComputeCompareExpected) void {
300 check.actions.append(.{
305 const gpa = check.allocator;
306 check.actions.append(gpa, .{
301307 .tag = .compute_cmp,
302308 .phrase = phrase,
303309 .expected = expected,
......@@ -565,9 +571,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
565571 null,
566572 .of(u64),
567573 null,
568 ) catch |err| return step.fail("unable to read '{'}': {s}", .{ src_path, @errorName(err) });
574 ) catch |err| return step.fail("unable to read '{f'}': {s}", .{ src_path, @errorName(err) });
569575
570 var vars = std.StringHashMap(u64).init(gpa);
576 var vars: std.StringHashMap(u64) = .init(gpa);
571577 for (check_object.checks.items) |chk| {
572578 if (chk.kind == .compute_compare) {
573579 assert(chk.actions.items.len == 1);
......@@ -581,7 +587,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
581587 return step.fail(
582588 \\
583589 \\========= comparison failed for action: ===========
584 \\{s} {}
590 \\{s} {f}
585591 \\===================================================
586592 , .{ act.phrase.resolve(b, step), act.expected.? });
587593 }
......@@ -600,7 +606,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
600606 // we either format message string with escaped codes, or not to aid debugging
601607 // the failed test.
602608 const fmtMessageString = struct {
603 fn fmtMessageString(kind: Check.Kind, msg: []const u8) std.fmt.Formatter(formatMessageString) {
609 fn fmtMessageString(kind: Check.Kind, msg: []const u8) std.fmt.Formatter(Ctx, formatMessageString) {
604610 return .{ .data = .{
605611 .kind = kind,
606612 .msg = msg,
......@@ -612,17 +618,10 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
612618 msg: []const u8,
613619 };
614620
615 fn formatMessageString(
616 ctx: Ctx,
617 comptime unused_fmt_string: []const u8,
618 options: std.fmt.FormatOptions,
619 writer: anytype,
620 ) !void {
621 _ = unused_fmt_string;
622 _ = options;
621 fn formatMessageString(ctx: Ctx, w: *Writer) !void {
623622 switch (ctx.kind) {
624 .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),
625 else => try writer.writeAll(ctx.msg),
623 .dump_section => try w.print("{f}", .{std.ascii.hexEscape(ctx.msg, .lower)}),
624 else => try w.writeAll(ctx.msg),
626625 }
627626 }
628627 }.fmtMessageString;
......@@ -637,11 +636,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
637636 return step.fail(
638637 \\
639638 \\========= expected to find: ==========================
640 \\{s}
639 \\{f}
641640 \\========= but parsed file does not contain it: =======
642 \\{s}
641 \\{f}
643642 \\========= file path: =================================
644 \\{}
643 \\{f}
645644 , .{
646645 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
647646 fmtMessageString(chk.kind, output),
......@@ -657,11 +656,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
657656 return step.fail(
658657 \\
659658 \\========= expected to find: ==========================
660 \\*{s}*
659 \\*{f}*
661660 \\========= but parsed file does not contain it: =======
662 \\{s}
661 \\{f}
663662 \\========= file path: =================================
664 \\{}
663 \\{f}
665664 , .{
666665 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
667666 fmtMessageString(chk.kind, output),
......@@ -676,11 +675,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
676675 return step.fail(
677676 \\
678677 \\========= expected not to find: ===================
679 \\{s}
678 \\{f}
680679 \\========= but parsed file does contain it: ========
681 \\{s}
680 \\{f}
682681 \\========= file path: ==============================
683 \\{}
682 \\{f}
684683 , .{
685684 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
686685 fmtMessageString(chk.kind, output),
......@@ -696,13 +695,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
696695 return step.fail(
697696 \\
698697 \\========= expected to find and extract: ==============
699 \\{s}
698 \\{f}
700699 \\========= but parsed file does not contain it: =======
701 \\{s}
700 \\{f}
702701 \\========= file path: ==============================
703 \\{}
702 \\{f}
704703 , .{
705 act.phrase.resolve(b, step),
704 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
706705 fmtMessageString(chk.kind, output),
707706 src_path,
708707 });
......@@ -755,14 +754,14 @@ const MachODumper = struct {
755754 },
756755 .SYMTAB => {
757756 const lc = cmd.cast(macho.symtab_command).?;
758 const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(ctx.data.ptr + lc.symoff))[0..lc.nsyms];
757 const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(ctx.data[lc.symoff..].ptr))[0..lc.nsyms];
759758 const strtab = ctx.data[lc.stroff..][0..lc.strsize];
760759 try ctx.symtab.appendUnalignedSlice(ctx.gpa, symtab);
761760 try ctx.strtab.appendSlice(ctx.gpa, strtab);
762761 },
763762 .DYSYMTAB => {
764763 const lc = cmd.cast(macho.dysymtab_command).?;
765 const indexes = @as([*]align(1) const u32, @ptrCast(ctx.data.ptr + lc.indirectsymoff))[0..lc.nindirectsyms];
764 const indexes = @as([*]align(1) const u32, @ptrCast(ctx.data[lc.indirectsymoff..].ptr))[0..lc.nindirectsyms];
766765 try ctx.indsymtab.appendUnalignedSlice(ctx.gpa, indexes);
767766 },
768767 .LOAD_DYLIB,
......@@ -780,7 +779,7 @@ const MachODumper = struct {
780779
781780 fn getString(ctx: ObjectContext, off: u32) [:0]const u8 {
782781 assert(off < ctx.strtab.items.len);
783 return mem.sliceTo(@as([*:0]const u8, @ptrCast(ctx.strtab.items.ptr + off)), 0);
782 return mem.sliceTo(@as([*:0]const u8, @ptrCast(ctx.strtab.items[off..].ptr)), 0);
784783 }
785784
786785 fn getLoadCommandIterator(ctx: ObjectContext) macho.LoadCommandIterator {
......@@ -810,7 +809,7 @@ const MachODumper = struct {
810809 return null;
811810 }
812811
813 fn dumpHeader(hdr: macho.mach_header_64, writer: anytype) !void {
812 fn dumpHeader(hdr: macho.mach_header_64, bw: *Writer) !void {
814813 const cputype = switch (hdr.cputype) {
815814 macho.CPU_TYPE_ARM64 => "ARM64",
816815 macho.CPU_TYPE_X86_64 => "X86_64",
......@@ -831,7 +830,7 @@ const MachODumper = struct {
831830 else => "Unknown",
832831 };
833832
834 try writer.print(
833 try bw.print(
835834 \\header
836835 \\cputype {s}
837836 \\filetype {s}
......@@ -846,41 +845,41 @@ const MachODumper = struct {
846845 });
847846
848847 if (hdr.flags > 0) {
849 if (hdr.flags & macho.MH_NOUNDEFS != 0) try writer.writeAll(" NOUNDEFS");
850 if (hdr.flags & macho.MH_INCRLINK != 0) try writer.writeAll(" INCRLINK");
851 if (hdr.flags & macho.MH_DYLDLINK != 0) try writer.writeAll(" DYLDLINK");
852 if (hdr.flags & macho.MH_BINDATLOAD != 0) try writer.writeAll(" BINDATLOAD");
853 if (hdr.flags & macho.MH_PREBOUND != 0) try writer.writeAll(" PREBOUND");
854 if (hdr.flags & macho.MH_SPLIT_SEGS != 0) try writer.writeAll(" SPLIT_SEGS");
855 if (hdr.flags & macho.MH_LAZY_INIT != 0) try writer.writeAll(" LAZY_INIT");
856 if (hdr.flags & macho.MH_TWOLEVEL != 0) try writer.writeAll(" TWOLEVEL");
857 if (hdr.flags & macho.MH_FORCE_FLAT != 0) try writer.writeAll(" FORCE_FLAT");
858 if (hdr.flags & macho.MH_NOMULTIDEFS != 0) try writer.writeAll(" NOMULTIDEFS");
859 if (hdr.flags & macho.MH_NOFIXPREBINDING != 0) try writer.writeAll(" NOFIXPREBINDING");
860 if (hdr.flags & macho.MH_PREBINDABLE != 0) try writer.writeAll(" PREBINDABLE");
861 if (hdr.flags & macho.MH_ALLMODSBOUND != 0) try writer.writeAll(" ALLMODSBOUND");
862 if (hdr.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) try writer.writeAll(" SUBSECTIONS_VIA_SYMBOLS");
863 if (hdr.flags & macho.MH_CANONICAL != 0) try writer.writeAll(" CANONICAL");
864 if (hdr.flags & macho.MH_WEAK_DEFINES != 0) try writer.writeAll(" WEAK_DEFINES");
865 if (hdr.flags & macho.MH_BINDS_TO_WEAK != 0) try writer.writeAll(" BINDS_TO_WEAK");
866 if (hdr.flags & macho.MH_ALLOW_STACK_EXECUTION != 0) try writer.writeAll(" ALLOW_STACK_EXECUTION");
867 if (hdr.flags & macho.MH_ROOT_SAFE != 0) try writer.writeAll(" ROOT_SAFE");
868 if (hdr.flags & macho.MH_SETUID_SAFE != 0) try writer.writeAll(" SETUID_SAFE");
869 if (hdr.flags & macho.MH_NO_REEXPORTED_DYLIBS != 0) try writer.writeAll(" NO_REEXPORTED_DYLIBS");
870 if (hdr.flags & macho.MH_PIE != 0) try writer.writeAll(" PIE");
871 if (hdr.flags & macho.MH_DEAD_STRIPPABLE_DYLIB != 0) try writer.writeAll(" DEAD_STRIPPABLE_DYLIB");
872 if (hdr.flags & macho.MH_HAS_TLV_DESCRIPTORS != 0) try writer.writeAll(" HAS_TLV_DESCRIPTORS");
873 if (hdr.flags & macho.MH_NO_HEAP_EXECUTION != 0) try writer.writeAll(" NO_HEAP_EXECUTION");
874 if (hdr.flags & macho.MH_APP_EXTENSION_SAFE != 0) try writer.writeAll(" APP_EXTENSION_SAFE");
875 if (hdr.flags & macho.MH_NLIST_OUTOFSYNC_WITH_DYLDINFO != 0) try writer.writeAll(" NLIST_OUTOFSYNC_WITH_DYLDINFO");
848 if (hdr.flags & macho.MH_NOUNDEFS != 0) try bw.writeAll(" NOUNDEFS");
849 if (hdr.flags & macho.MH_INCRLINK != 0) try bw.writeAll(" INCRLINK");
850 if (hdr.flags & macho.MH_DYLDLINK != 0) try bw.writeAll(" DYLDLINK");
851 if (hdr.flags & macho.MH_BINDATLOAD != 0) try bw.writeAll(" BINDATLOAD");
852 if (hdr.flags & macho.MH_PREBOUND != 0) try bw.writeAll(" PREBOUND");
853 if (hdr.flags & macho.MH_SPLIT_SEGS != 0) try bw.writeAll(" SPLIT_SEGS");
854 if (hdr.flags & macho.MH_LAZY_INIT != 0) try bw.writeAll(" LAZY_INIT");
855 if (hdr.flags & macho.MH_TWOLEVEL != 0) try bw.writeAll(" TWOLEVEL");
856 if (hdr.flags & macho.MH_FORCE_FLAT != 0) try bw.writeAll(" FORCE_FLAT");
857 if (hdr.flags & macho.MH_NOMULTIDEFS != 0) try bw.writeAll(" NOMULTIDEFS");
858 if (hdr.flags & macho.MH_NOFIXPREBINDING != 0) try bw.writeAll(" NOFIXPREBINDING");
859 if (hdr.flags & macho.MH_PREBINDABLE != 0) try bw.writeAll(" PREBINDABLE");
860 if (hdr.flags & macho.MH_ALLMODSBOUND != 0) try bw.writeAll(" ALLMODSBOUND");
861 if (hdr.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) try bw.writeAll(" SUBSECTIONS_VIA_SYMBOLS");
862 if (hdr.flags & macho.MH_CANONICAL != 0) try bw.writeAll(" CANONICAL");
863 if (hdr.flags & macho.MH_WEAK_DEFINES != 0) try bw.writeAll(" WEAK_DEFINES");
864 if (hdr.flags & macho.MH_BINDS_TO_WEAK != 0) try bw.writeAll(" BINDS_TO_WEAK");
865 if (hdr.flags & macho.MH_ALLOW_STACK_EXECUTION != 0) try bw.writeAll(" ALLOW_STACK_EXECUTION");
866 if (hdr.flags & macho.MH_ROOT_SAFE != 0) try bw.writeAll(" ROOT_SAFE");
867 if (hdr.flags & macho.MH_SETUID_SAFE != 0) try bw.writeAll(" SETUID_SAFE");
868 if (hdr.flags & macho.MH_NO_REEXPORTED_DYLIBS != 0) try bw.writeAll(" NO_REEXPORTED_DYLIBS");
869 if (hdr.flags & macho.MH_PIE != 0) try bw.writeAll(" PIE");
870 if (hdr.flags & macho.MH_DEAD_STRIPPABLE_DYLIB != 0) try bw.writeAll(" DEAD_STRIPPABLE_DYLIB");
871 if (hdr.flags & macho.MH_HAS_TLV_DESCRIPTORS != 0) try bw.writeAll(" HAS_TLV_DESCRIPTORS");
872 if (hdr.flags & macho.MH_NO_HEAP_EXECUTION != 0) try bw.writeAll(" NO_HEAP_EXECUTION");
873 if (hdr.flags & macho.MH_APP_EXTENSION_SAFE != 0) try bw.writeAll(" APP_EXTENSION_SAFE");
874 if (hdr.flags & macho.MH_NLIST_OUTOFSYNC_WITH_DYLDINFO != 0) try bw.writeAll(" NLIST_OUTOFSYNC_WITH_DYLDINFO");
876875 }
877876
878 try writer.writeByte('\n');
877 try bw.writeByte('\n');
879878 }
880879
881 fn dumpLoadCommand(lc: macho.LoadCommandIterator.LoadCommand, index: usize, writer: anytype) !void {
880 fn dumpLoadCommand(lc: macho.LoadCommandIterator.LoadCommand, index: usize, bw: *Writer) !void {
882881 // print header first
883 try writer.print(
882 try bw.print(
884883 \\LC {d}
885884 \\cmd {s}
886885 \\cmdsize {d}
......@@ -889,8 +888,8 @@ const MachODumper = struct {
889888 switch (lc.cmd()) {
890889 .SEGMENT_64 => {
891890 const seg = lc.cast(macho.segment_command_64).?;
892 try writer.writeByte('\n');
893 try writer.print(
891 try bw.writeByte('\n');
892 try bw.print(
894893 \\segname {s}
895894 \\vmaddr {x}
896895 \\vmsize {x}
......@@ -905,8 +904,8 @@ const MachODumper = struct {
905904 });
906905
907906 for (lc.getSections()) |sect| {
908 try writer.writeByte('\n');
909 try writer.print(
907 try bw.writeByte('\n');
908 try bw.print(
910909 \\sectname {s}
911910 \\addr {x}
912911 \\size {x}
......@@ -928,8 +927,8 @@ const MachODumper = struct {
928927 .REEXPORT_DYLIB,
929928 => {
930929 const dylib = lc.cast(macho.dylib_command).?;
931 try writer.writeByte('\n');
932 try writer.print(
930 try bw.writeByte('\n');
931 try bw.print(
933932 \\name {s}
934933 \\timestamp {d}
935934 \\current version {x}
......@@ -944,16 +943,16 @@ const MachODumper = struct {
944943
945944 .MAIN => {
946945 const main = lc.cast(macho.entry_point_command).?;
947 try writer.writeByte('\n');
948 try writer.print(
946 try bw.writeByte('\n');
947 try bw.print(
949948 \\entryoff {x}
950949 \\stacksize {x}
951950 , .{ main.entryoff, main.stacksize });
952951 },
953952
954953 .RPATH => {
955 try writer.writeByte('\n');
956 try writer.print(
954 try bw.writeByte('\n');
955 try bw.print(
957956 \\path {s}
958957 , .{
959958 lc.getRpathPathName(),
......@@ -962,8 +961,8 @@ const MachODumper = struct {
962961
963962 .UUID => {
964963 const uuid = lc.cast(macho.uuid_command).?;
965 try writer.writeByte('\n');
966 try writer.print("uuid {x}", .{std.fmt.fmtSliceHexLower(&uuid.uuid)});
964 try bw.writeByte('\n');
965 try bw.print("uuid {x}", .{&uuid.uuid});
967966 },
968967
969968 .DATA_IN_CODE,
......@@ -971,8 +970,8 @@ const MachODumper = struct {
971970 .CODE_SIGNATURE,
972971 => {
973972 const llc = lc.cast(macho.linkedit_data_command).?;
974 try writer.writeByte('\n');
975 try writer.print(
973 try bw.writeByte('\n');
974 try bw.print(
976975 \\dataoff {x}
977976 \\datasize {x}
978977 , .{ llc.dataoff, llc.datasize });
......@@ -980,8 +979,8 @@ const MachODumper = struct {
980979
981980 .DYLD_INFO_ONLY => {
982981 const dlc = lc.cast(macho.dyld_info_command).?;
983 try writer.writeByte('\n');
984 try writer.print(
982 try bw.writeByte('\n');
983 try bw.print(
985984 \\rebaseoff {x}
986985 \\rebasesize {x}
987986 \\bindoff {x}
......@@ -1008,8 +1007,8 @@ const MachODumper = struct {
10081007
10091008 .SYMTAB => {
10101009 const slc = lc.cast(macho.symtab_command).?;
1011 try writer.writeByte('\n');
1012 try writer.print(
1010 try bw.writeByte('\n');
1011 try bw.print(
10131012 \\symoff {x}
10141013 \\nsyms {x}
10151014 \\stroff {x}
......@@ -1024,8 +1023,8 @@ const MachODumper = struct {
10241023
10251024 .DYSYMTAB => {
10261025 const dlc = lc.cast(macho.dysymtab_command).?;
1027 try writer.writeByte('\n');
1028 try writer.print(
1026 try bw.writeByte('\n');
1027 try bw.print(
10291028 \\ilocalsym {x}
10301029 \\nlocalsym {x}
10311030 \\iextdefsym {x}
......@@ -1048,8 +1047,8 @@ const MachODumper = struct {
10481047
10491048 .BUILD_VERSION => {
10501049 const blc = lc.cast(macho.build_version_command).?;
1051 try writer.writeByte('\n');
1052 try writer.print(
1050 try bw.writeByte('\n');
1051 try bw.print(
10531052 \\platform {s}
10541053 \\minos {d}.{d}.{d}
10551054 \\sdk {d}.{d}.{d}
......@@ -1065,12 +1064,12 @@ const MachODumper = struct {
10651064 blc.ntools,
10661065 });
10671066 for (lc.getBuildVersionTools()) |tool| {
1068 try writer.writeByte('\n');
1067 try bw.writeByte('\n');
10691068 switch (tool.tool) {
1070 .CLANG, .SWIFT, .LD, .LLD, .ZIG => try writer.print("tool {s}\n", .{@tagName(tool.tool)}),
1071 else => |x| try writer.print("tool {d}\n", .{@intFromEnum(x)}),
1069 .CLANG, .SWIFT, .LD, .LLD, .ZIG => try bw.print("tool {s}\n", .{@tagName(tool.tool)}),
1070 else => |x| try bw.print("tool {d}\n", .{@intFromEnum(x)}),
10721071 }
1073 try writer.print(
1072 try bw.print(
10741073 \\version {d}.{d}.{d}
10751074 , .{
10761075 tool.version >> 16,
......@@ -1086,8 +1085,8 @@ const MachODumper = struct {
10861085 .VERSION_MIN_TVOS,
10871086 => {
10881087 const vlc = lc.cast(macho.version_min_command).?;
1089 try writer.writeByte('\n');
1090 try writer.print(
1088 try bw.writeByte('\n');
1089 try bw.print(
10911090 \\version {d}.{d}.{d}
10921091 \\sdk {d}.{d}.{d}
10931092 , .{
......@@ -1104,8 +1103,8 @@ const MachODumper = struct {
11041103 }
11051104 }
11061105
1107 fn dumpSymtab(ctx: ObjectContext, writer: anytype) !void {
1108 try writer.writeAll(symtab_label ++ "\n");
1106 fn dumpSymtab(ctx: ObjectContext, bw: *Writer) !void {
1107 try bw.writeAll(symtab_label ++ "\n");
11091108
11101109 for (ctx.symtab.items) |sym| {
11111110 const sym_name = ctx.getString(sym.n_strx);
......@@ -1120,32 +1119,32 @@ const MachODumper = struct {
11201119 macho.N_STSYM => "STSYM",
11211120 else => "UNKNOWN STAB",
11221121 };
1123 try writer.print("{x}", .{sym.n_value});
1122 try bw.print("{x}", .{sym.n_value});
11241123 if (sym.n_sect > 0) {
11251124 const sect = ctx.sections.items[sym.n_sect - 1];
1126 try writer.print(" ({s},{s})", .{ sect.segName(), sect.sectName() });
1125 try bw.print(" ({s},{s})", .{ sect.segName(), sect.sectName() });
11271126 }
1128 try writer.print(" {s} (stab) {s}\n", .{ tt, sym_name });
1127 try bw.print(" {s} (stab) {s}\n", .{ tt, sym_name });
11291128 } else if (sym.sect()) {
11301129 const sect = ctx.sections.items[sym.n_sect - 1];
1131 try writer.print("{x} ({s},{s})", .{
1130 try bw.print("{x} ({s},{s})", .{
11321131 sym.n_value,
11331132 sect.segName(),
11341133 sect.sectName(),
11351134 });
1136 if (sym.n_desc & macho.REFERENCED_DYNAMICALLY != 0) try writer.writeAll(" [referenced dynamically]");
1137 if (sym.weakDef()) try writer.writeAll(" weak");
1138 if (sym.weakRef()) try writer.writeAll(" weakref");
1135 if (sym.n_desc & macho.REFERENCED_DYNAMICALLY != 0) try bw.writeAll(" [referenced dynamically]");
1136 if (sym.weakDef()) try bw.writeAll(" weak");
1137 if (sym.weakRef()) try bw.writeAll(" weakref");
11391138 if (sym.ext()) {
1140 if (sym.pext()) try writer.writeAll(" private");
1141 try writer.writeAll(" external");
1142 } else if (sym.pext()) try writer.writeAll(" (was private external)");
1143 try writer.print(" {s}\n", .{sym_name});
1139 if (sym.pext()) try bw.writeAll(" private");
1140 try bw.writeAll(" external");
1141 } else if (sym.pext()) try bw.writeAll(" (was private external)");
1142 try bw.print(" {s}\n", .{sym_name});
11441143 } else if (sym.tentative()) {
11451144 const alignment = (sym.n_desc >> 8) & 0x0F;
1146 try writer.print(" 0x{x:0>16} (common) (alignment 2^{d})", .{ sym.n_value, alignment });
1147 if (sym.ext()) try writer.writeAll(" external");
1148 try writer.print(" {s}\n", .{sym_name});
1145 try bw.print(" 0x{x:0>16} (common) (alignment 2^{d})", .{ sym.n_value, alignment });
1146 if (sym.ext()) try bw.writeAll(" external");
1147 try bw.print(" {s}\n", .{sym_name});
11491148 } else if (sym.undf()) {
11501149 const ordinal = @divFloor(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);
11511150 const import_name = blk: {
......@@ -1164,10 +1163,10 @@ const MachODumper = struct {
11641163 const ext = mem.lastIndexOfScalar(u8, basename, '.') orelse basename.len;
11651164 break :blk basename[0..ext];
11661165 };
1167 try writer.writeAll("(undefined)");
1168 if (sym.weakRef()) try writer.writeAll(" weakref");
1169 if (sym.ext()) try writer.writeAll(" external");
1170 try writer.print(" {s} (from {s})\n", .{
1166 try bw.writeAll("(undefined)");
1167 if (sym.weakRef()) try bw.writeAll(" weakref");
1168 if (sym.ext()) try bw.writeAll(" external");
1169 try bw.print(" {s} (from {s})\n", .{
11711170 sym_name,
11721171 import_name,
11731172 });
......@@ -1175,8 +1174,8 @@ const MachODumper = struct {
11751174 }
11761175 }
11771176
1178 fn dumpIndirectSymtab(ctx: ObjectContext, writer: anytype) !void {
1179 try writer.writeAll(indirect_symtab_label ++ "\n");
1177 fn dumpIndirectSymtab(ctx: ObjectContext, bw: *Writer) !void {
1178 try bw.writeAll(indirect_symtab_label ++ "\n");
11801179
11811180 var sects_buffer: [3]macho.section_64 = undefined;
11821181 const sects = blk: {
......@@ -1214,35 +1213,33 @@ const MachODumper = struct {
12141213 break :blk @sizeOf(u64);
12151214 };
12161215
1217 try writer.print("{s},{s}\n", .{ sect.segName(), sect.sectName() });
1218 try writer.print("nentries {d}\n", .{end - start});
1216 try bw.print("{s},{s}\n", .{ sect.segName(), sect.sectName() });
1217 try bw.print("nentries {d}\n", .{end - start});
12191218 for (ctx.indsymtab.items[start..end], 0..) |index, j| {
12201219 const sym = ctx.symtab.items[index];
12211220 const addr = sect.addr + entry_size * j;
1222 try writer.print("0x{x} {d} {s}\n", .{ addr, index, ctx.getString(sym.n_strx) });
1221 try bw.print("0x{x} {d} {s}\n", .{ addr, index, ctx.getString(sym.n_strx) });
12231222 }
12241223 }
12251224 }
12261225
1227 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, writer: anytype) !void {
1228 var rebases = std.ArrayList(u64).init(ctx.gpa);
1226 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1227 var rebases: std.ArrayList(u64) = .init(ctx.gpa);
12291228 defer rebases.deinit();
12301229 try ctx.parseRebaseInfo(data, &rebases);
12311230 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
12321231 for (rebases.items) |addr| {
1233 try writer.print("0x{x}\n", .{addr});
1232 try bw.print("0x{x}\n", .{addr});
12341233 }
12351234 }
12361235
12371236 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
1238 var stream = std.io.fixedBufferStream(data);
1239 var creader = std.io.countingReader(stream.reader());
1240 const reader = creader.reader();
1237 var br: std.io.Reader = .fixed(data);
12411238
12421239 var seg_id: ?u8 = null;
12431240 var offset: u64 = 0;
12441241 while (true) {
1245 const byte = reader.readByte() catch break;
1242 const byte = br.takeByte() catch break;
12461243 const opc = byte & macho.REBASE_OPCODE_MASK;
12471244 const imm = byte & macho.REBASE_IMMEDIATE_MASK;
12481245 switch (opc) {
......@@ -1250,17 +1247,17 @@ const MachODumper = struct {
12501247 macho.REBASE_OPCODE_SET_TYPE_IMM => {},
12511248 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
12521249 seg_id = imm;
1253 offset = try std.leb.readUleb128(u64, reader);
1250 offset = try br.takeLeb128(u64);
12541251 },
12551252 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {
12561253 offset += imm * @sizeOf(u64);
12571254 },
12581255 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {
1259 const addend = try std.leb.readUleb128(u64, reader);
1256 const addend = try br.takeLeb128(u64);
12601257 offset += addend;
12611258 },
12621259 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {
1263 const addend = try std.leb.readUleb128(u64, reader);
1260 const addend = try br.takeLeb128(u64);
12641261 const seg = ctx.segments.items[seg_id.?];
12651262 const addr = seg.vmaddr + offset;
12661263 try rebases.append(addr);
......@@ -1277,11 +1274,11 @@ const MachODumper = struct {
12771274 ntimes = imm;
12781275 },
12791276 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {
1280 ntimes = try std.leb.readUleb128(u64, reader);
1277 ntimes = try br.takeLeb128(u64);
12811278 },
12821279 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {
1283 ntimes = try std.leb.readUleb128(u64, reader);
1284 skip = try std.leb.readUleb128(u64, reader);
1280 ntimes = try br.takeLeb128(u64);
1281 skip = try br.takeLeb128(u64);
12851282 },
12861283 else => unreachable,
12871284 }
......@@ -1323,8 +1320,8 @@ const MachODumper = struct {
13231320 };
13241321 };
13251322
1326 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, writer: anytype) !void {
1327 var bindings = std.ArrayList(Binding).init(ctx.gpa);
1323 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1324 var bindings: std.ArrayList(Binding) = .init(ctx.gpa);
13281325 defer {
13291326 for (bindings.items) |*b| {
13301327 b.deinit(ctx.gpa);
......@@ -1334,22 +1331,20 @@ const MachODumper = struct {
13341331 try ctx.parseBindInfo(data, &bindings);
13351332 mem.sort(Binding, bindings.items, {}, Binding.lessThan);
13361333 for (bindings.items) |binding| {
1337 try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });
1338 try writer.writeAll(" (");
1334 try bw.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });
1335 try bw.writeAll(" (");
13391336 switch (binding.tag) {
1340 .self => try writer.writeAll("self"),
1341 .exe => try writer.writeAll("main executable"),
1342 .flat => try writer.writeAll("flat lookup"),
1343 .ord => try writer.writeAll(std.fs.path.basename(ctx.imports.items[binding.ordinal - 1])),
1337 .self => try bw.writeAll("self"),
1338 .exe => try bw.writeAll("main executable"),
1339 .flat => try bw.writeAll("flat lookup"),
1340 .ord => try bw.writeAll(std.fs.path.basename(ctx.imports.items[binding.ordinal - 1])),
13441341 }
1345 try writer.print(") {s}\n", .{binding.name});
1342 try bw.print(") {s}\n", .{binding.name});
13461343 }
13471344 }
13481345
13491346 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
1350 var stream = std.io.fixedBufferStream(data);
1351 var creader = std.io.countingReader(stream.reader());
1352 const reader = creader.reader();
1347 var br: std.io.Reader = .fixed(data);
13531348
13541349 var seg_id: ?u8 = null;
13551350 var tag: Binding.Tag = .self;
......@@ -1357,11 +1352,10 @@ const MachODumper = struct {
13571352 var offset: u64 = 0;
13581353 var addend: i64 = 0;
13591354
1360 var name_buf = std.ArrayList(u8).init(ctx.gpa);
1355 var name_buf: std.ArrayList(u8) = .init(ctx.gpa);
13611356 defer name_buf.deinit();
13621357
1363 while (true) {
1364 const byte = reader.readByte() catch break;
1358 while (br.takeByte()) |byte| {
13651359 const opc = byte & macho.BIND_OPCODE_MASK;
13661360 const imm = byte & macho.BIND_IMMEDIATE_MASK;
13671361 switch (opc) {
......@@ -1382,18 +1376,19 @@ const MachODumper = struct {
13821376 },
13831377 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
13841378 seg_id = imm;
1385 offset = try std.leb.readUleb128(u64, reader);
1379 offset = try br.takeLeb128(u64);
13861380 },
13871381 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
13881382 name_buf.clearRetainingCapacity();
1389 try reader.readUntilDelimiterArrayList(&name_buf, 0, std.math.maxInt(u32));
1383 if (true) @panic("TODO fix this");
1384 //try reader.readUntilDelimiterArrayList(&name_buf, 0, std.math.maxInt(u32));
13901385 try name_buf.append(0);
13911386 },
13921387 macho.BIND_OPCODE_SET_ADDEND_SLEB => {
1393 addend = try std.leb.readIleb128(i64, reader);
1388 addend = try br.takeLeb128(i64);
13941389 },
13951390 macho.BIND_OPCODE_ADD_ADDR_ULEB => {
1396 const x = try std.leb.readUleb128(u64, reader);
1391 const x = try br.takeLeb128(u64);
13971392 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));
13981393 },
13991394 macho.BIND_OPCODE_DO_BIND,
......@@ -1408,14 +1403,14 @@ const MachODumper = struct {
14081403 switch (opc) {
14091404 macho.BIND_OPCODE_DO_BIND => {},
14101405 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
1411 add_addr = try std.leb.readUleb128(u64, reader);
1406 add_addr = try br.takeLeb128(u64);
14121407 },
14131408 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
14141409 add_addr = imm * @sizeOf(u64);
14151410 },
14161411 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
1417 count = try std.leb.readUleb128(u64, reader);
1418 skip = try std.leb.readUleb128(u64, reader);
1412 count = try br.takeLeb128(u64);
1413 skip = try br.takeLeb128(u64);
14191414 },
14201415 else => unreachable,
14211416 }
......@@ -1436,18 +1431,18 @@ const MachODumper = struct {
14361431 },
14371432 else => break,
14381433 }
1439 }
1434 } else |_| {}
14401435 }
14411436
1442 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, writer: anytype) !void {
1437 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
14431438 const seg = ctx.getSegmentByName("__TEXT") orelse return;
14441439
14451440 var arena = std.heap.ArenaAllocator.init(ctx.gpa);
14461441 defer arena.deinit();
14471442
1448 var exports = std.ArrayList(Export).init(arena.allocator());
1449 var it = TrieIterator{ .data = data };
1450 try parseTrieNode(arena.allocator(), &it, "", &exports);
1443 var exports: std.ArrayList(Export) = .init(arena.allocator());
1444 var br: std.io.Reader = .fixed(data);
1445 try parseTrieNode(arena.allocator(), &br, "", &exports);
14511446
14521447 mem.sort(Export, exports.items, {}, Export.lessThan);
14531448
......@@ -1456,66 +1451,26 @@ const MachODumper = struct {
14561451 .@"export" => {
14571452 const info = exp.data.@"export";
14581453 if (info.kind != .regular or info.weak) {
1459 try writer.writeByte('[');
1454 try bw.writeByte('[');
14601455 }
14611456 switch (info.kind) {
14621457 .regular => {},
1463 .absolute => try writer.writeAll("ABS, "),
1464 .tlv => try writer.writeAll("THREAD_LOCAL, "),
1458 .absolute => try bw.writeAll("ABS, "),
1459 .tlv => try bw.writeAll("THREAD_LOCAL, "),
14651460 }
1466 if (info.weak) try writer.writeAll("WEAK");
1461 if (info.weak) try bw.writeAll("WEAK");
14671462 if (info.kind != .regular or info.weak) {
1468 try writer.writeAll("] ");
1463 try bw.writeAll("] ");
14691464 }
1470 try writer.print("{x} ", .{seg.vmaddr + info.vmoffset});
1465 try bw.print("{x} ", .{seg.vmaddr + info.vmoffset});
14711466 },
14721467 else => {},
14731468 }
14741469
1475 try writer.print("{s}\n", .{exp.name});
1470 try bw.print("{s}\n", .{exp.name});
14761471 }
14771472 }
14781473
1479 const TrieIterator = struct {
1480 data: []const u8,
1481 pos: usize = 0,
1482
1483 fn getStream(it: *TrieIterator) std.io.FixedBufferStream([]const u8) {
1484 return std.io.fixedBufferStream(it.data[it.pos..]);
1485 }
1486
1487 fn readUleb128(it: *TrieIterator) !u64 {
1488 var stream = it.getStream();
1489 var creader = std.io.countingReader(stream.reader());
1490 const reader = creader.reader();
1491 const value = try std.leb.readUleb128(u64, reader);
1492 it.pos += creader.bytes_read;
1493 return value;
1494 }
1495
1496 fn readString(it: *TrieIterator) ![:0]const u8 {
1497 var stream = it.getStream();
1498 const reader = stream.reader();
1499
1500 var count: usize = 0;
1501 while (true) : (count += 1) {
1502 const byte = try reader.readByte();
1503 if (byte == 0) break;
1504 }
1505
1506 const str = @as([*:0]const u8, @ptrCast(it.data.ptr + it.pos))[0..count :0];
1507 it.pos += count + 1;
1508 return str;
1509 }
1510
1511 fn readByte(it: *TrieIterator) !u8 {
1512 var stream = it.getStream();
1513 const value = try stream.reader().readByte();
1514 it.pos += 1;
1515 return value;
1516 }
1517 };
1518
15191474 const Export = struct {
15201475 name: []const u8,
15211476 tag: enum { @"export", reexport, stub_resolver },
......@@ -1555,17 +1510,17 @@ const MachODumper = struct {
15551510
15561511 fn parseTrieNode(
15571512 arena: Allocator,
1558 it: *TrieIterator,
1513 br: *std.io.Reader,
15591514 prefix: []const u8,
15601515 exports: *std.ArrayList(Export),
15611516 ) !void {
1562 const size = try it.readUleb128();
1517 const size = try br.takeLeb128(u64);
15631518 if (size > 0) {
1564 const flags = try it.readUleb128();
1519 const flags = try br.takeLeb128(u8);
15651520 switch (flags) {
15661521 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {
1567 const ord = try it.readUleb128();
1568 const name = try arena.dupe(u8, try it.readString());
1522 const ord = try br.takeLeb128(u64);
1523 const name = try br.takeSentinel(0);
15691524 try exports.append(.{
15701525 .name = if (name.len > 0) name else prefix,
15711526 .tag = .reexport,
......@@ -1573,8 +1528,8 @@ const MachODumper = struct {
15731528 });
15741529 },
15751530 macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER => {
1576 const stub_offset = try it.readUleb128();
1577 const resolver_offset = try it.readUleb128();
1531 const stub_offset = try br.takeLeb128(u64);
1532 const resolver_offset = try br.takeLeb128(u64);
15781533 try exports.append(.{
15791534 .name = prefix,
15801535 .tag = .stub_resolver,
......@@ -1585,7 +1540,7 @@ const MachODumper = struct {
15851540 });
15861541 },
15871542 else => {
1588 const vmoff = try it.readUleb128();
1543 const vmoff = try br.takeLeb128(u64);
15891544 try exports.append(.{
15901545 .name = prefix,
15911546 .tag = .@"export",
......@@ -1604,21 +1559,21 @@ const MachODumper = struct {
16041559 }
16051560 }
16061561
1607 const nedges = try it.readByte();
1562 const nedges = try br.takeByte();
16081563 for (0..nedges) |_| {
1609 const label = try it.readString();
1610 const off = try it.readUleb128();
1564 const label = try br.takeSentinel(0);
1565 const off = try br.takeLeb128(usize);
16111566 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });
1612 const curr = it.pos;
1613 it.pos = off;
1614 try parseTrieNode(arena, it, prefix_label, exports);
1615 it.pos = curr;
1567 const seek = br.seek;
1568 br.seek = off;
1569 try parseTrieNode(arena, br, prefix_label, exports);
1570 br.seek = seek;
16161571 }
16171572 }
16181573
1619 fn dumpSection(ctx: ObjectContext, sect: macho.section_64, writer: anytype) !void {
1574 fn dumpSection(ctx: ObjectContext, sect: macho.section_64, bw: *Writer) !void {
16201575 const data = ctx.data[sect.offset..][0..sect.size];
1621 try writer.print("{s}", .{data});
1576 try bw.print("{s}", .{data});
16221577 }
16231578 };
16241579
......@@ -1632,29 +1587,30 @@ const MachODumper = struct {
16321587 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };
16331588 try ctx.parse();
16341589
1635 var output = std.ArrayList(u8).init(gpa);
1636 const writer = output.writer();
1590 var aw: std.io.Writer.Allocating = .init(gpa);
1591 defer aw.deinit();
1592 const bw = &aw.interface;
16371593
16381594 switch (check.kind) {
16391595 .headers => {
1640 try ObjectContext.dumpHeader(ctx.header, writer);
1596 try ObjectContext.dumpHeader(ctx.header, bw);
16411597
16421598 var it = ctx.getLoadCommandIterator();
16431599 var i: usize = 0;
16441600 while (it.next()) |cmd| {
1645 try ObjectContext.dumpLoadCommand(cmd, i, writer);
1646 try writer.writeByte('\n');
1601 try ObjectContext.dumpLoadCommand(cmd, i, bw);
1602 try bw.writeByte('\n');
16471603
16481604 i += 1;
16491605 }
16501606 },
16511607
16521608 .symtab => if (ctx.symtab.items.len > 0) {
1653 try ctx.dumpSymtab(writer);
1609 try ctx.dumpSymtab(bw);
16541610 } else return step.fail("no symbol table found", .{}),
16551611
16561612 .indirect_symtab => if (ctx.symtab.items.len > 0 and ctx.indsymtab.items.len > 0) {
1657 try ctx.dumpIndirectSymtab(writer);
1613 try ctx.dumpIndirectSymtab(bw);
16581614 } else return step.fail("no indirect symbol table found", .{}),
16591615
16601616 .dyld_rebase,
......@@ -1669,26 +1625,26 @@ const MachODumper = struct {
16691625 switch (check.kind) {
16701626 .dyld_rebase => if (lc.rebase_size > 0) {
16711627 const data = ctx.data[lc.rebase_off..][0..lc.rebase_size];
1672 try writer.writeAll(dyld_rebase_label ++ "\n");
1673 try ctx.dumpRebaseInfo(data, writer);
1628 try bw.writeAll(dyld_rebase_label ++ "\n");
1629 try ctx.dumpRebaseInfo(data, bw);
16741630 } else return step.fail("no rebase data found", .{}),
16751631
16761632 .dyld_bind => if (lc.bind_size > 0) {
16771633 const data = ctx.data[lc.bind_off..][0..lc.bind_size];
1678 try writer.writeAll(dyld_bind_label ++ "\n");
1679 try ctx.dumpBindInfo(data, writer);
1634 try bw.writeAll(dyld_bind_label ++ "\n");
1635 try ctx.dumpBindInfo(data, bw);
16801636 } else return step.fail("no bind data found", .{}),
16811637
16821638 .dyld_weak_bind => if (lc.weak_bind_size > 0) {
16831639 const data = ctx.data[lc.weak_bind_off..][0..lc.weak_bind_size];
1684 try writer.writeAll(dyld_weak_bind_label ++ "\n");
1685 try ctx.dumpBindInfo(data, writer);
1640 try bw.writeAll(dyld_weak_bind_label ++ "\n");
1641 try ctx.dumpBindInfo(data, bw);
16861642 } else return step.fail("no weak bind data found", .{}),
16871643
16881644 .dyld_lazy_bind => if (lc.lazy_bind_size > 0) {
16891645 const data = ctx.data[lc.lazy_bind_off..][0..lc.lazy_bind_size];
1690 try writer.writeAll(dyld_lazy_bind_label ++ "\n");
1691 try ctx.dumpBindInfo(data, writer);
1646 try bw.writeAll(dyld_lazy_bind_label ++ "\n");
1647 try ctx.dumpBindInfo(data, bw);
16921648 } else return step.fail("no lazy bind data found", .{}),
16931649
16941650 else => unreachable,
......@@ -1700,8 +1656,8 @@ const MachODumper = struct {
17001656 const lc = cmd.cast(macho.dyld_info_command).?;
17011657 if (lc.export_size > 0) {
17021658 const data = ctx.data[lc.export_off..][0..lc.export_size];
1703 try writer.writeAll(exports_label ++ "\n");
1704 try ctx.dumpExportsTrie(data, writer);
1659 try bw.writeAll(exports_label ++ "\n");
1660 try ctx.dumpExportsTrie(data, bw);
17051661 break :blk;
17061662 }
17071663 }
......@@ -1709,20 +1665,20 @@ const MachODumper = struct {
17091665 },
17101666
17111667 .dump_section => {
1712 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);
1668 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items[check.payload.dump_section..].ptr)), 0);
17131669 const sep_index = mem.indexOfScalar(u8, name, ',') orelse
17141670 return step.fail("invalid section name: {s}", .{name});
17151671 const segname = name[0..sep_index];
17161672 const sectname = name[sep_index + 1 ..];
17171673 const sect = ctx.getSectionByName(segname, sectname) orelse
17181674 return step.fail("section '{s}' not found", .{name});
1719 try ctx.dumpSection(sect, writer);
1675 try ctx.dumpSection(sect, bw);
17201676 },
17211677
17221678 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),
17231679 }
17241680
1725 return output.toOwnedSlice();
1681 return aw.toOwnedSlice();
17261682 }
17271683};
17281684
......@@ -1741,161 +1697,138 @@ const ElfDumper = struct {
17411697
17421698 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
17431699 const gpa = step.owner.allocator;
1744 var stream = std.io.fixedBufferStream(bytes);
1745 const reader = stream.reader();
1700 var br: std.io.Reader = .fixed(bytes);
17461701
1747 const magic = try reader.readBytesNoEof(elf.ARMAG.len);
1748 if (!mem.eql(u8, &magic, elf.ARMAG)) {
1749 return error.InvalidArchiveMagicNumber;
1750 }
1702 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
17511703
1752 var ctx = ArchiveContext{
1704 var ctx: ArchiveContext = .{
17531705 .gpa = gpa,
17541706 .data = bytes,
1755 .strtab = &[0]u8{},
1707 .symtab = &.{},
1708 .strtab = &.{},
1709 .objects = .empty,
17561710 };
1757 defer {
1758 for (ctx.objects.items) |*object| {
1759 gpa.free(object.name);
1760 }
1761 ctx.objects.deinit(gpa);
1762 }
1711 defer ctx.deinit();
17631712
1764 while (true) {
1765 if (stream.pos >= ctx.data.len) break;
1766 if (!mem.isAligned(stream.pos, 2)) stream.pos += 1;
1767
1768 const hdr = try reader.readStruct(elf.ar_hdr);
1713 while (br.seek < bytes.len) {
1714 const hdr_seek = std.mem.alignForward(usize, br.seek, 2);
1715 br.seek = hdr_seek;
1716 const hdr = try br.takeStruct(elf.ar_hdr);
17691717
17701718 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) return error.InvalidArchiveHeaderMagicNumber;
17711719
1772 const size = try hdr.size();
1773 defer {
1774 _ = stream.seekBy(size) catch {};
1775 }
1720 const data = try br.take(try hdr.size());
17761721
17771722 if (hdr.isSymtab()) {
1778 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p32);
1723 try ctx.parseSymtab(data, .p32);
17791724 continue;
17801725 }
17811726 if (hdr.isSymtab64()) {
1782 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p64);
1727 try ctx.parseSymtab(data, .p64);
17831728 continue;
17841729 }
17851730 if (hdr.isStrtab()) {
1786 ctx.strtab = ctx.data[stream.pos..][0..size];
1731 ctx.strtab = data;
17871732 continue;
17881733 }
17891734 if (hdr.isSymdef() or hdr.isSymdefSorted()) continue;
17901735
1791 const name = if (hdr.name()) |name|
1792 try gpa.dupe(u8, name)
1793 else if (try hdr.nameOffset()) |off|
1794 try gpa.dupe(u8, ctx.getString(off))
1795 else
1796 unreachable;
1797
1798 try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size });
1736 const name = hdr.name() orelse ctx.getString((try hdr.nameOffset()).?);
1737 try ctx.objects.putNoClobber(gpa, hdr_seek, .{
1738 .name = name,
1739 .data = data,
1740 });
17991741 }
18001742
1801 var output = std.ArrayList(u8).init(gpa);
1802 const writer = output.writer();
1743 var aw: std.io.Writer.Allocating = .init(gpa);
1744 defer aw.deinit();
1745 const bw = &aw.interface;
18031746
18041747 switch (check.kind) {
1805 .archive_symtab => if (ctx.symtab.items.len > 0) {
1806 try ctx.dumpSymtab(writer);
1748 .archive_symtab => if (ctx.symtab.len > 0) {
1749 try ctx.dumpSymtab(bw);
18071750 } else return step.fail("no archive symbol table found", .{}),
18081751
1809 else => if (ctx.objects.items.len > 0) {
1810 try ctx.dumpObjects(step, check, writer);
1752 else => if (ctx.objects.count() > 0) {
1753 try ctx.dumpObjects(step, check, bw);
18111754 } else return step.fail("empty archive", .{}),
18121755 }
18131756
1814 return output.toOwnedSlice();
1757 return aw.toOwnedSlice();
18151758 }
18161759
18171760 const ArchiveContext = struct {
18181761 gpa: Allocator,
18191762 data: []const u8,
1820 symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .empty,
1763 symtab: []ArSymtabEntry,
18211764 strtab: []const u8,
1822 objects: std.ArrayListUnmanaged(struct { name: []const u8, off: usize, len: usize }) = .empty,
1765 objects: std.AutoArrayHashMapUnmanaged(usize, struct { name: []const u8, data: []const u8 }),
18231766
1824 fn parseSymtab(ctx: *ArchiveContext, raw: []const u8, ptr_width: enum { p32, p64 }) !void {
1825 var stream = std.io.fixedBufferStream(raw);
1826 const reader = stream.reader();
1767 fn deinit(ctx: *ArchiveContext) void {
1768 ctx.gpa.free(ctx.symtab);
1769 ctx.objects.deinit(ctx.gpa);
1770 }
1771
1772 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {
1773 var br: std.io.Reader = .fixed(data);
18271774 const num = switch (ptr_width) {
1828 .p32 => try reader.readInt(u32, .big),
1829 .p64 => try reader.readInt(u64, .big),
1775 .p32 => try br.takeInt(u32, .big),
1776 .p64 => try br.takeInt(u64, .big),
18301777 };
18311778 const ptr_size: usize = switch (ptr_width) {
18321779 .p32 => @sizeOf(u32),
18331780 .p64 => @sizeOf(u64),
18341781 };
1835 const strtab_off = (num + 1) * ptr_size;
1836 const strtab_len = raw.len - strtab_off;
1837 const strtab = raw[strtab_off..][0..strtab_len];
1782 _ = try br.discard(.limited(num * ptr_size));
1783 const strtab = br.buffered();
18381784
1839 try ctx.symtab.ensureTotalCapacityPrecise(ctx.gpa, num);
1785 assert(ctx.symtab.len == 0);
1786 ctx.symtab = try ctx.gpa.alloc(ArSymtabEntry, num);
18401787
18411788 var stroff: usize = 0;
1842 for (0..num) |_| {
1789 for (ctx.symtab) |*entry| {
18431790 const off = switch (ptr_width) {
1844 .p32 => try reader.readInt(u32, .big),
1845 .p64 => try reader.readInt(u64, .big),
1791 .p32 => try br.takeInt(u32, .big),
1792 .p64 => try br.takeInt(u64, .big),
18461793 };
1847 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + stroff)), 0);
1794 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab[stroff..].ptr)), 0);
18481795 stroff += name.len + 1;
1849 ctx.symtab.appendAssumeCapacity(.{ .off = off, .name = name });
1796 entry.* = .{ .off = off, .name = name };
18501797 }
18511798 }
18521799
1853 fn dumpSymtab(ctx: ArchiveContext, writer: anytype) !void {
1854 var files = std.AutoHashMap(usize, []const u8).init(ctx.gpa);
1855 defer files.deinit();
1856 try files.ensureUnusedCapacity(@intCast(ctx.objects.items.len));
1857
1858 for (ctx.objects.items) |object| {
1859 files.putAssumeCapacityNoClobber(object.off - @sizeOf(elf.ar_hdr), object.name);
1860 }
1861
1862 var symbols = std.AutoArrayHashMap(usize, std.ArrayList([]const u8)).init(ctx.gpa);
1800 fn dumpSymtab(ctx: ArchiveContext, bw: *Writer) !void {
1801 var symbols: std.AutoArrayHashMap(usize, std.ArrayList([]const u8)) = .init(ctx.gpa);
18631802 defer {
1864 for (symbols.values()) |*value| {
1865 value.deinit();
1866 }
1803 for (symbols.values()) |*value| value.deinit();
18671804 symbols.deinit();
18681805 }
18691806
1870 for (ctx.symtab.items) |entry| {
1807 for (ctx.symtab) |entry| {
18711808 const gop = try symbols.getOrPut(@intCast(entry.off));
1872 if (!gop.found_existing) {
1873 gop.value_ptr.* = std.ArrayList([]const u8).init(ctx.gpa);
1874 }
1809 if (!gop.found_existing) gop.value_ptr.* = .init(ctx.gpa);
18751810 try gop.value_ptr.append(entry.name);
18761811 }
18771812
1878 try writer.print("{s}\n", .{archive_symtab_label});
1813 try bw.print("{s}\n", .{archive_symtab_label});
18791814 for (symbols.keys(), symbols.values()) |off, values| {
1880 try writer.print("in object {s}\n", .{files.get(off).?});
1881 for (values.items) |value| {
1882 try writer.print("{s}\n", .{value});
1883 }
1815 try bw.print("in object {s}\n", .{ctx.objects.get(off).?.name});
1816 for (values.items) |value| try bw.print("{s}\n", .{value});
18841817 }
18851818 }
18861819
1887 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, writer: anytype) !void {
1888 for (ctx.objects.items) |object| {
1889 try writer.print("object {s}\n", .{object.name});
1890 const output = try parseAndDumpObject(step, check, ctx.data[object.off..][0..object.len]);
1820 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *Writer) !void {
1821 for (ctx.objects.values()) |object| {
1822 try bw.print("object {s}\n", .{object.name});
1823 const output = try parseAndDumpObject(step, check, object.data);
18911824 defer ctx.gpa.free(output);
1892 try writer.print("{s}\n", .{output});
1825 try bw.print("{s}\n", .{output});
18931826 }
18941827 }
18951828
18961829 fn getString(ctx: ArchiveContext, off: u32) []const u8 {
18971830 assert(off < ctx.strtab.len);
1898 const name = mem.sliceTo(@as([*:'\n']const u8, @ptrCast(ctx.strtab.ptr + off)), 0);
1831 const name = mem.sliceTo(@as([*:'\n']const u8, @ptrCast(ctx.strtab[off..].ptr)), 0);
18991832 return name[0 .. name.len - 1];
19001833 }
19011834
......@@ -1907,24 +1840,23 @@ const ElfDumper = struct {
19071840
19081841 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
19091842 const gpa = step.owner.allocator;
1910 var stream = std.io.fixedBufferStream(bytes);
1911 const reader = stream.reader();
1843 var br: std.io.Reader = .fixed(bytes);
19121844
1913 const hdr = try reader.readStruct(elf.Elf64_Ehdr);
1914 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {
1915 return error.InvalidMagicNumber;
1916 }
1845 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
1846 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;
19171847
1918 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];
1919 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];
1848 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes[hdr.e_shoff..].ptr))[0..hdr.e_shnum];
1849 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes[hdr.e_phoff..].ptr))[0..hdr.e_phnum];
19201850
1921 var ctx = ObjectContext{
1851 var ctx: ObjectContext = .{
19221852 .gpa = gpa,
19231853 .data = bytes,
19241854 .hdr = hdr,
19251855 .shdrs = shdrs,
19261856 .phdrs = phdrs,
19271857 .shstrtab = undefined,
1858 .symtab = .{},
1859 .dysymtab = .{},
19281860 };
19291861 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
19301862
......@@ -1955,120 +1887,121 @@ const ElfDumper = struct {
19551887 else => {},
19561888 };
19571889
1958 var output = std.ArrayList(u8).init(gpa);
1959 const writer = output.writer();
1890 var aw: std.io.Writer.Allocating = .init(gpa);
1891 defer aw.deinit();
1892 const bw = &aw.interface;
19601893
19611894 switch (check.kind) {
19621895 .headers => {
1963 try ctx.dumpHeader(writer);
1964 try ctx.dumpShdrs(writer);
1965 try ctx.dumpPhdrs(writer);
1896 try ctx.dumpHeader(bw);
1897 try ctx.dumpShdrs(bw);
1898 try ctx.dumpPhdrs(bw);
19661899 },
19671900
19681901 .symtab => if (ctx.symtab.symbols.len > 0) {
1969 try ctx.dumpSymtab(.symtab, writer);
1902 try ctx.dumpSymtab(.symtab, bw);
19701903 } else return step.fail("no symbol table found", .{}),
19711904
19721905 .dynamic_symtab => if (ctx.dysymtab.symbols.len > 0) {
1973 try ctx.dumpSymtab(.dysymtab, writer);
1906 try ctx.dumpSymtab(.dysymtab, bw);
19741907 } else return step.fail("no dynamic symbol table found", .{}),
19751908
19761909 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {
1977 try ctx.dumpDynamicSection(shndx, writer);
1910 try ctx.dumpDynamicSection(shndx, bw);
19781911 } else return step.fail("no .dynamic section found", .{}),
19791912
19801913 .dump_section => {
1981 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);
1914 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items[check.payload.dump_section..].ptr)), 0);
19821915 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});
1983 try ctx.dumpSection(shndx, writer);
1916 try ctx.dumpSection(shndx, bw);
19841917 },
19851918
19861919 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),
19871920 }
19881921
1989 return output.toOwnedSlice();
1922 return aw.toOwnedSlice();
19901923 }
19911924
19921925 const ObjectContext = struct {
19931926 gpa: Allocator,
19941927 data: []const u8,
1995 hdr: elf.Elf64_Ehdr,
1928 hdr: *align(1) const elf.Elf64_Ehdr,
19961929 shdrs: []align(1) const elf.Elf64_Shdr,
19971930 phdrs: []align(1) const elf.Elf64_Phdr,
19981931 shstrtab: []const u8,
1999 symtab: Symtab = .{},
2000 dysymtab: Symtab = .{},
1932 symtab: Symtab,
1933 dysymtab: Symtab,
20011934
2002 fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {
2003 try writer.writeAll("header\n");
2004 try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
2005 try writer.print("entry {x}\n", .{ctx.hdr.e_entry});
1935 fn dumpHeader(ctx: ObjectContext, bw: *Writer) !void {
1936 try bw.writeAll("header\n");
1937 try bw.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
1938 try bw.print("entry {x}\n", .{ctx.hdr.e_entry});
20061939 }
20071940
2008 fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {
1941 fn dumpPhdrs(ctx: ObjectContext, bw: *Writer) !void {
20091942 if (ctx.phdrs.len == 0) return;
20101943
2011 try writer.writeAll("program headers\n");
1944 try bw.writeAll("program headers\n");
20121945
20131946 for (ctx.phdrs, 0..) |phdr, phndx| {
2014 try writer.print("phdr {d}\n", .{phndx});
2015 try writer.print("type {s}\n", .{fmtPhType(phdr.p_type)});
2016 try writer.print("vaddr {x}\n", .{phdr.p_vaddr});
2017 try writer.print("paddr {x}\n", .{phdr.p_paddr});
2018 try writer.print("offset {x}\n", .{phdr.p_offset});
2019 try writer.print("memsz {x}\n", .{phdr.p_memsz});
2020 try writer.print("filesz {x}\n", .{phdr.p_filesz});
2021 try writer.print("align {x}\n", .{phdr.p_align});
1947 try bw.print("phdr {d}\n", .{phndx});
1948 try bw.print("type {f}\n", .{fmtPhType(phdr.p_type)});
1949 try bw.print("vaddr {x}\n", .{phdr.p_vaddr});
1950 try bw.print("paddr {x}\n", .{phdr.p_paddr});
1951 try bw.print("offset {x}\n", .{phdr.p_offset});
1952 try bw.print("memsz {x}\n", .{phdr.p_memsz});
1953 try bw.print("filesz {x}\n", .{phdr.p_filesz});
1954 try bw.print("align {x}\n", .{phdr.p_align});
20221955
20231956 {
20241957 const flags = phdr.p_flags;
2025 try writer.writeAll("flags");
2026 if (flags > 0) try writer.writeByte(' ');
1958 try bw.writeAll("flags");
1959 if (flags > 0) try bw.writeByte(' ');
20271960 if (flags & elf.PF_R != 0) {
2028 try writer.writeByte('R');
1961 try bw.writeByte('R');
20291962 }
20301963 if (flags & elf.PF_W != 0) {
2031 try writer.writeByte('W');
1964 try bw.writeByte('W');
20321965 }
20331966 if (flags & elf.PF_X != 0) {
2034 try writer.writeByte('E');
1967 try bw.writeByte('E');
20351968 }
20361969 if (flags & elf.PF_MASKOS != 0) {
2037 try writer.writeAll("OS");
1970 try bw.writeAll("OS");
20381971 }
20391972 if (flags & elf.PF_MASKPROC != 0) {
2040 try writer.writeAll("PROC");
1973 try bw.writeAll("PROC");
20411974 }
2042 try writer.writeByte('\n');
1975 try bw.writeByte('\n');
20431976 }
20441977 }
20451978 }
20461979
2047 fn dumpShdrs(ctx: ObjectContext, writer: anytype) !void {
1980 fn dumpShdrs(ctx: ObjectContext, bw: *Writer) !void {
20481981 if (ctx.shdrs.len == 0) return;
20491982
2050 try writer.writeAll("section headers\n");
1983 try bw.writeAll("section headers\n");
20511984
20521985 for (ctx.shdrs, 0..) |shdr, shndx| {
2053 try writer.print("shdr {d}\n", .{shndx});
2054 try writer.print("name {s}\n", .{ctx.getSectionName(shndx)});
2055 try writer.print("type {s}\n", .{fmtShType(shdr.sh_type)});
2056 try writer.print("addr {x}\n", .{shdr.sh_addr});
2057 try writer.print("offset {x}\n", .{shdr.sh_offset});
2058 try writer.print("size {x}\n", .{shdr.sh_size});
2059 try writer.print("addralign {x}\n", .{shdr.sh_addralign});
1986 try bw.print("shdr {d}\n", .{shndx});
1987 try bw.print("name {s}\n", .{ctx.getSectionName(shndx)});
1988 try bw.print("type {f}\n", .{fmtShType(shdr.sh_type)});
1989 try bw.print("addr {x}\n", .{shdr.sh_addr});
1990 try bw.print("offset {x}\n", .{shdr.sh_offset});
1991 try bw.print("size {x}\n", .{shdr.sh_size});
1992 try bw.print("addralign {x}\n", .{shdr.sh_addralign});
20601993 // TODO dump formatted sh_flags
20611994 }
20621995 }
20631996
2064 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {
1997 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, bw: *Writer) !void {
20651998 const shdr = ctx.shdrs[shndx];
20661999 const strtab = ctx.getSectionContents(shdr.sh_link);
20672000 const data = ctx.getSectionContents(shndx);
20682001 const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));
20692002 const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];
20702003
2071 try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");
2004 try bw.writeAll(ElfDumper.dynamic_section_label ++ "\n");
20722005
20732006 for (entries) |entry| {
20742007 const key = @as(u64, @bitCast(entry.d_tag));
......@@ -2109,7 +2042,7 @@ const ElfDumper = struct {
21092042 elf.DT_NULL => "NULL",
21102043 else => "UNKNOWN",
21112044 };
2112 try writer.print("{s}", .{key_str});
2045 try bw.print("{s}", .{key_str});
21132046
21142047 switch (key) {
21152048 elf.DT_NEEDED,
......@@ -2118,7 +2051,7 @@ const ElfDumper = struct {
21182051 elf.DT_RUNPATH,
21192052 => {
21202053 const name = getString(strtab, @intCast(value));
2121 try writer.print(" {s}", .{name});
2054 try bw.print(" {s}", .{name});
21222055 },
21232056
21242057 elf.DT_INIT_ARRAY,
......@@ -2136,7 +2069,7 @@ const ElfDumper = struct {
21362069 elf.DT_INIT,
21372070 elf.DT_FINI,
21382071 elf.DT_NULL,
2139 => try writer.print(" {x}", .{value}),
2072 => try bw.print(" {x}", .{value}),
21402073
21412074 elf.DT_INIT_ARRAYSZ,
21422075 elf.DT_FINI_ARRAYSZ,
......@@ -2146,77 +2079,77 @@ const ElfDumper = struct {
21462079 elf.DT_RELASZ,
21472080 elf.DT_RELAENT,
21482081 elf.DT_RELACOUNT,
2149 => try writer.print(" {d}", .{value}),
2082 => try bw.print(" {d}", .{value}),
21502083
2151 elf.DT_PLTREL => try writer.writeAll(switch (value) {
2084 elf.DT_PLTREL => try bw.writeAll(switch (value) {
21522085 elf.DT_REL => " REL",
21532086 elf.DT_RELA => " RELA",
21542087 else => " UNKNOWN",
21552088 }),
21562089
21572090 elf.DT_FLAGS => if (value > 0) {
2158 if (value & elf.DF_ORIGIN != 0) try writer.writeAll(" ORIGIN");
2159 if (value & elf.DF_SYMBOLIC != 0) try writer.writeAll(" SYMBOLIC");
2160 if (value & elf.DF_TEXTREL != 0) try writer.writeAll(" TEXTREL");
2161 if (value & elf.DF_BIND_NOW != 0) try writer.writeAll(" BIND_NOW");
2162 if (value & elf.DF_STATIC_TLS != 0) try writer.writeAll(" STATIC_TLS");
2091 if (value & elf.DF_ORIGIN != 0) try bw.writeAll(" ORIGIN");
2092 if (value & elf.DF_SYMBOLIC != 0) try bw.writeAll(" SYMBOLIC");
2093 if (value & elf.DF_TEXTREL != 0) try bw.writeAll(" TEXTREL");
2094 if (value & elf.DF_BIND_NOW != 0) try bw.writeAll(" BIND_NOW");
2095 if (value & elf.DF_STATIC_TLS != 0) try bw.writeAll(" STATIC_TLS");
21632096 },
21642097
21652098 elf.DT_FLAGS_1 => if (value > 0) {
2166 if (value & elf.DF_1_NOW != 0) try writer.writeAll(" NOW");
2167 if (value & elf.DF_1_GLOBAL != 0) try writer.writeAll(" GLOBAL");
2168 if (value & elf.DF_1_GROUP != 0) try writer.writeAll(" GROUP");
2169 if (value & elf.DF_1_NODELETE != 0) try writer.writeAll(" NODELETE");
2170 if (value & elf.DF_1_LOADFLTR != 0) try writer.writeAll(" LOADFLTR");
2171 if (value & elf.DF_1_INITFIRST != 0) try writer.writeAll(" INITFIRST");
2172 if (value & elf.DF_1_NOOPEN != 0) try writer.writeAll(" NOOPEN");
2173 if (value & elf.DF_1_ORIGIN != 0) try writer.writeAll(" ORIGIN");
2174 if (value & elf.DF_1_DIRECT != 0) try writer.writeAll(" DIRECT");
2175 if (value & elf.DF_1_TRANS != 0) try writer.writeAll(" TRANS");
2176 if (value & elf.DF_1_INTERPOSE != 0) try writer.writeAll(" INTERPOSE");
2177 if (value & elf.DF_1_NODEFLIB != 0) try writer.writeAll(" NODEFLIB");
2178 if (value & elf.DF_1_NODUMP != 0) try writer.writeAll(" NODUMP");
2179 if (value & elf.DF_1_CONFALT != 0) try writer.writeAll(" CONFALT");
2180 if (value & elf.DF_1_ENDFILTEE != 0) try writer.writeAll(" ENDFILTEE");
2181 if (value & elf.DF_1_DISPRELDNE != 0) try writer.writeAll(" DISPRELDNE");
2182 if (value & elf.DF_1_DISPRELPND != 0) try writer.writeAll(" DISPRELPND");
2183 if (value & elf.DF_1_NODIRECT != 0) try writer.writeAll(" NODIRECT");
2184 if (value & elf.DF_1_IGNMULDEF != 0) try writer.writeAll(" IGNMULDEF");
2185 if (value & elf.DF_1_NOKSYMS != 0) try writer.writeAll(" NOKSYMS");
2186 if (value & elf.DF_1_NOHDR != 0) try writer.writeAll(" NOHDR");
2187 if (value & elf.DF_1_EDITED != 0) try writer.writeAll(" EDITED");
2188 if (value & elf.DF_1_NORELOC != 0) try writer.writeAll(" NORELOC");
2189 if (value & elf.DF_1_SYMINTPOSE != 0) try writer.writeAll(" SYMINTPOSE");
2190 if (value & elf.DF_1_GLOBAUDIT != 0) try writer.writeAll(" GLOBAUDIT");
2191 if (value & elf.DF_1_SINGLETON != 0) try writer.writeAll(" SINGLETON");
2192 if (value & elf.DF_1_STUB != 0) try writer.writeAll(" STUB");
2193 if (value & elf.DF_1_PIE != 0) try writer.writeAll(" PIE");
2099 if (value & elf.DF_1_NOW != 0) try bw.writeAll(" NOW");
2100 if (value & elf.DF_1_GLOBAL != 0) try bw.writeAll(" GLOBAL");
2101 if (value & elf.DF_1_GROUP != 0) try bw.writeAll(" GROUP");
2102 if (value & elf.DF_1_NODELETE != 0) try bw.writeAll(" NODELETE");
2103 if (value & elf.DF_1_LOADFLTR != 0) try bw.writeAll(" LOADFLTR");
2104 if (value & elf.DF_1_INITFIRST != 0) try bw.writeAll(" INITFIRST");
2105 if (value & elf.DF_1_NOOPEN != 0) try bw.writeAll(" NOOPEN");
2106 if (value & elf.DF_1_ORIGIN != 0) try bw.writeAll(" ORIGIN");
2107 if (value & elf.DF_1_DIRECT != 0) try bw.writeAll(" DIRECT");
2108 if (value & elf.DF_1_TRANS != 0) try bw.writeAll(" TRANS");
2109 if (value & elf.DF_1_INTERPOSE != 0) try bw.writeAll(" INTERPOSE");
2110 if (value & elf.DF_1_NODEFLIB != 0) try bw.writeAll(" NODEFLIB");
2111 if (value & elf.DF_1_NODUMP != 0) try bw.writeAll(" NODUMP");
2112 if (value & elf.DF_1_CONFALT != 0) try bw.writeAll(" CONFALT");
2113 if (value & elf.DF_1_ENDFILTEE != 0) try bw.writeAll(" ENDFILTEE");
2114 if (value & elf.DF_1_DISPRELDNE != 0) try bw.writeAll(" DISPRELDNE");
2115 if (value & elf.DF_1_DISPRELPND != 0) try bw.writeAll(" DISPRELPND");
2116 if (value & elf.DF_1_NODIRECT != 0) try bw.writeAll(" NODIRECT");
2117 if (value & elf.DF_1_IGNMULDEF != 0) try bw.writeAll(" IGNMULDEF");
2118 if (value & elf.DF_1_NOKSYMS != 0) try bw.writeAll(" NOKSYMS");
2119 if (value & elf.DF_1_NOHDR != 0) try bw.writeAll(" NOHDR");
2120 if (value & elf.DF_1_EDITED != 0) try bw.writeAll(" EDITED");
2121 if (value & elf.DF_1_NORELOC != 0) try bw.writeAll(" NORELOC");
2122 if (value & elf.DF_1_SYMINTPOSE != 0) try bw.writeAll(" SYMINTPOSE");
2123 if (value & elf.DF_1_GLOBAUDIT != 0) try bw.writeAll(" GLOBAUDIT");
2124 if (value & elf.DF_1_SINGLETON != 0) try bw.writeAll(" SINGLETON");
2125 if (value & elf.DF_1_STUB != 0) try bw.writeAll(" STUB");
2126 if (value & elf.DF_1_PIE != 0) try bw.writeAll(" PIE");
21942127 },
21952128
2196 else => try writer.print(" {x}", .{value}),
2129 else => try bw.print(" {x}", .{value}),
21972130 }
2198 try writer.writeByte('\n');
2131 try bw.writeByte('\n');
21992132 }
22002133 }
22012134
2202 fn dumpSymtab(ctx: ObjectContext, comptime @"type": enum { symtab, dysymtab }, writer: anytype) !void {
2135 fn dumpSymtab(ctx: ObjectContext, comptime @"type": enum { symtab, dysymtab }, bw: *Writer) !void {
22032136 const symtab = switch (@"type") {
22042137 .symtab => ctx.symtab,
22052138 .dysymtab => ctx.dysymtab,
22062139 };
22072140
2208 try writer.writeAll(switch (@"type") {
2141 try bw.writeAll(switch (@"type") {
22092142 .symtab => symtab_label,
22102143 .dysymtab => dynamic_symtab_label,
22112144 } ++ "\n");
22122145
22132146 for (symtab.symbols, 0..) |sym, index| {
2214 try writer.print("{x} {x}", .{ sym.st_value, sym.st_size });
2147 try bw.print("{x} {x}", .{ sym.st_value, sym.st_size });
22152148
22162149 {
22172150 if (elf.SHN_LORESERVE <= sym.st_shndx and sym.st_shndx < elf.SHN_HIRESERVE) {
22182151 if (elf.SHN_LOPROC <= sym.st_shndx and sym.st_shndx < elf.SHN_HIPROC) {
2219 try writer.print(" LO+{d}", .{sym.st_shndx - elf.SHN_LOPROC});
2152 try bw.print(" LO+{d}", .{sym.st_shndx - elf.SHN_LOPROC});
22202153 } else {
22212154 const sym_ndx = switch (sym.st_shndx) {
22222155 elf.SHN_ABS => "ABS",
......@@ -2224,12 +2157,12 @@ const ElfDumper = struct {
22242157 elf.SHN_LIVEPATCH => "LIV",
22252158 else => "UNK",
22262159 };
2227 try writer.print(" {s}", .{sym_ndx});
2160 try bw.print(" {s}", .{sym_ndx});
22282161 }
22292162 } else if (sym.st_shndx == elf.SHN_UNDEF) {
2230 try writer.writeAll(" UND");
2163 try bw.writeAll(" UND");
22312164 } else {
2232 try writer.print(" {x}", .{sym.st_shndx});
2165 try bw.print(" {x}", .{sym.st_shndx});
22332166 }
22342167 }
22352168
......@@ -2246,12 +2179,12 @@ const ElfDumper = struct {
22462179 elf.STT_NUM => "NUM",
22472180 elf.STT_GNU_IFUNC => "IFUNC",
22482181 else => if (elf.STT_LOPROC <= tt and tt < elf.STT_HIPROC) {
2249 break :blk try writer.print(" LOPROC+{d}", .{tt - elf.STT_LOPROC});
2182 break :blk try bw.print(" LOPROC+{d}", .{tt - elf.STT_LOPROC});
22502183 } else if (elf.STT_LOOS <= tt and tt < elf.STT_HIOS) {
2251 break :blk try writer.print(" LOOS+{d}", .{tt - elf.STT_LOOS});
2184 break :blk try bw.print(" LOOS+{d}", .{tt - elf.STT_LOOS});
22522185 } else "UNK",
22532186 };
2254 try writer.print(" {s}", .{sym_type});
2187 try bw.print(" {s}", .{sym_type});
22552188 }
22562189
22572190 blk: {
......@@ -2262,28 +2195,28 @@ const ElfDumper = struct {
22622195 elf.STB_WEAK => "WEAK",
22632196 elf.STB_NUM => "NUM",
22642197 else => if (elf.STB_LOPROC <= bind and bind < elf.STB_HIPROC) {
2265 break :blk try writer.print(" LOPROC+{d}", .{bind - elf.STB_LOPROC});
2198 break :blk try bw.print(" LOPROC+{d}", .{bind - elf.STB_LOPROC});
22662199 } else if (elf.STB_LOOS <= bind and bind < elf.STB_HIOS) {
2267 break :blk try writer.print(" LOOS+{d}", .{bind - elf.STB_LOOS});
2200 break :blk try bw.print(" LOOS+{d}", .{bind - elf.STB_LOOS});
22682201 } else "UNKNOWN",
22692202 };
2270 try writer.print(" {s}", .{sym_bind});
2203 try bw.print(" {s}", .{sym_bind});
22712204 }
22722205
22732206 const sym_vis = @as(elf.STV, @enumFromInt(@as(u2, @truncate(sym.st_other))));
2274 try writer.print(" {s}", .{@tagName(sym_vis)});
2207 try bw.print(" {s}", .{@tagName(sym_vis)});
22752208
22762209 const sym_name = switch (sym.st_type()) {
22772210 elf.STT_SECTION => ctx.getSectionName(sym.st_shndx),
22782211 else => symtab.getName(index).?,
22792212 };
2280 try writer.print(" {s}\n", .{sym_name});
2213 try bw.print(" {s}\n", .{sym_name});
22812214 }
22822215 }
22832216
2284 fn dumpSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {
2217 fn dumpSection(ctx: ObjectContext, shndx: usize, bw: *Writer) !void {
22852218 const data = ctx.getSectionContents(shndx);
2286 try writer.print("{s}", .{data});
2219 try bw.print("{s}", .{data});
22872220 }
22882221
22892222 inline fn getSectionName(ctx: ObjectContext, shndx: usize) []const u8 {
......@@ -2321,22 +2254,15 @@ const ElfDumper = struct {
23212254 };
23222255
23232256 fn getString(strtab: []const u8, off: u32) []const u8 {
2324 assert(off < strtab.len);
2325 return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0);
2257 const str = strtab[off..];
2258 return str[0..std.mem.indexOfScalar(u8, str, 0).?];
23262259 }
23272260
2328 fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) {
2261 fn fmtShType(sh_type: u32) std.fmt.Formatter(u32, formatShType) {
23292262 return .{ .data = sh_type };
23302263 }
23312264
2332 fn formatShType(
2333 sh_type: u32,
2334 comptime unused_fmt_string: []const u8,
2335 options: std.fmt.FormatOptions,
2336 writer: anytype,
2337 ) !void {
2338 _ = unused_fmt_string;
2339 _ = options;
2265 fn formatShType(sh_type: u32, w: *Writer) Writer.Error!void {
23402266 const name = switch (sh_type) {
23412267 elf.SHT_NULL => "NULL",
23422268 elf.SHT_PROGBITS => "PROGBITS",
......@@ -2362,28 +2288,21 @@ const ElfDumper = struct {
23622288 elf.SHT_GNU_VERNEED => "VERNEED",
23632289 elf.SHT_GNU_VERSYM => "VERSYM",
23642290 else => if (elf.SHT_LOOS <= sh_type and sh_type < elf.SHT_HIOS) {
2365 return try writer.print("LOOS+0x{x}", .{sh_type - elf.SHT_LOOS});
2291 return try w.print("LOOS+0x{x}", .{sh_type - elf.SHT_LOOS});
23662292 } else if (elf.SHT_LOPROC <= sh_type and sh_type < elf.SHT_HIPROC) {
2367 return try writer.print("LOPROC+0x{x}", .{sh_type - elf.SHT_LOPROC});
2293 return try w.print("LOPROC+0x{x}", .{sh_type - elf.SHT_LOPROC});
23682294 } else if (elf.SHT_LOUSER <= sh_type and sh_type < elf.SHT_HIUSER) {
2369 return try writer.print("LOUSER+0x{x}", .{sh_type - elf.SHT_LOUSER});
2295 return try w.print("LOUSER+0x{x}", .{sh_type - elf.SHT_LOUSER});
23702296 } else "UNKNOWN",
23712297 };
2372 try writer.writeAll(name);
2298 try w.writeAll(name);
23732299 }
23742300
2375 fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) {
2301 fn fmtPhType(ph_type: u32) std.fmt.Formatter(u32, formatPhType) {
23762302 return .{ .data = ph_type };
23772303 }
23782304
2379 fn formatPhType(
2380 ph_type: u32,
2381 comptime unused_fmt_string: []const u8,
2382 options: std.fmt.FormatOptions,
2383 writer: anytype,
2384 ) !void {
2385 _ = unused_fmt_string;
2386 _ = options;
2305 fn formatPhType(ph_type: u32, w: *Writer) Writer.Error!void {
23872306 const p_type = switch (ph_type) {
23882307 elf.PT_NULL => "NULL",
23892308 elf.PT_LOAD => "LOAD",
......@@ -2398,12 +2317,12 @@ const ElfDumper = struct {
23982317 elf.PT_GNU_STACK => "GNU_STACK",
23992318 elf.PT_GNU_RELRO => "GNU_RELRO",
24002319 else => if (elf.PT_LOOS <= ph_type and ph_type < elf.PT_HIOS) {
2401 return try writer.print("LOOS+0x{x}", .{ph_type - elf.PT_LOOS});
2320 return try w.print("LOOS+0x{x}", .{ph_type - elf.PT_LOOS});
24022321 } else if (elf.PT_LOPROC <= ph_type and ph_type < elf.PT_HIPROC) {
2403 return try writer.print("LOPROC+0x{x}", .{ph_type - elf.PT_LOPROC});
2322 return try w.print("LOPROC+0x{x}", .{ph_type - elf.PT_LOPROC});
24042323 } else "UNKNOWN",
24052324 };
2406 try writer.writeAll(p_type);
2325 try w.writeAll(p_type);
24072326 }
24082327};
24092328
......@@ -2412,49 +2331,39 @@ const WasmDumper = struct {
24122331
24132332 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
24142333 const gpa = step.owner.allocator;
2415 var fbs = std.io.fixedBufferStream(bytes);
2416 const reader = fbs.reader();
2334 var br: std.io.Reader = .fixed(bytes);
24172335
2418 const buf = try reader.readBytesNoEof(8);
2419 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) {
2420 return error.InvalidMagicByte;
2421 }
2422 if (!mem.eql(u8, buf[4..], &std.wasm.version)) {
2423 return error.UnsupportedWasmVersion;
2424 }
2336 const buf = try br.takeArray(8);
2337 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;
2338 if (!mem.eql(u8, buf[4..8], &std.wasm.version)) return error.UnsupportedWasmVersion;
2339
2340 var aw: std.io.Writer.Allocating = .init(gpa);
2341 defer aw.deinit();
2342 const bw = &aw.interface;
24252343
2426 var output = std.ArrayList(u8).init(gpa);
2427 defer output.deinit();
2428 parseAndDumpInner(step, check, bytes, &fbs, &output) catch |err| switch (err) {
2429 error.EndOfStream => try output.appendSlice("\n<UnexpectedEndOfStream>"),
2344 parseAndDumpInner(step, check, &br, bw) catch |err| switch (err) {
2345 error.EndOfStream => try bw.writeAll("\n<UnexpectedEndOfStream>"),
24302346 else => |e| return e,
24312347 };
2432 return output.toOwnedSlice();
2348 return aw.toOwnedSlice();
24332349 }
24342350
24352351 fn parseAndDumpInner(
24362352 step: *Step,
24372353 check: Check,
2438 bytes: []const u8,
2439 fbs: *std.io.FixedBufferStream([]const u8),
2440 output: *std.ArrayList(u8),
2354 br: *std.io.Reader,
2355 bw: *Writer,
24412356 ) !void {
2442 const reader = fbs.reader();
2443 const writer = output.writer();
2444
2357 var section_br: std.io.Reader = undefined;
24452358 switch (check.kind) {
2446 .headers => {
2447 while (reader.readByte()) |current_byte| {
2448 const section = std.enums.fromInt(std.wasm.Section, current_byte) orelse {
2449 return step.fail("Found invalid section id '{d}'", .{current_byte});
2450 };
2451
2452 const section_length = try std.leb.readUleb128(u32, reader);
2453 try parseAndDumpSection(step, section, bytes[fbs.pos..][0..section_length], writer);
2454 fbs.pos += section_length;
2455 } else |_| {} // reached end of stream
2359 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
2360 section_br = .fixed(try br.take(try br.takeLeb128(u32)));
2361 try parseAndDumpSection(step, section, &section_br, bw);
2362 } else |err| switch (err) {
2363 error.InvalidEnumTag => return step.fail("invalid section id", .{}),
2364 error.EndOfStream => {},
2365 else => |e| return e,
24562366 },
2457
24582367 else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),
24592368 }
24602369 }
......@@ -2462,16 +2371,13 @@ const WasmDumper = struct {
24622371 fn parseAndDumpSection(
24632372 step: *Step,
24642373 section: std.wasm.Section,
2465 data: []const u8,
2466 writer: anytype,
2374 br: *std.io.Reader,
2375 bw: *Writer,
24672376 ) !void {
2468 var fbs = std.io.fixedBufferStream(data);
2469 const reader = fbs.reader();
2470
2471 try writer.print(
2377 try bw.print(
24722378 \\Section {s}
24732379 \\size {d}
2474 , .{ @tagName(section), data.len });
2380 , .{ @tagName(section), br.buffer.len });
24752381
24762382 switch (section) {
24772383 .type,
......@@ -2485,96 +2391,83 @@ const WasmDumper = struct {
24852391 .code,
24862392 .data,
24872393 => {
2488 const entries = try std.leb.readUleb128(u32, reader);
2489 try writer.print("\nentries {d}\n", .{entries});
2490 try parseSection(step, section, data[fbs.pos..], entries, writer);
2394 const entries = try br.takeLeb128(u32);
2395 try bw.print("\nentries {d}\n", .{entries});
2396 try parseSection(step, section, br, entries, bw);
24912397 },
24922398 .custom => {
2493 const name_length = try std.leb.readUleb128(u32, reader);
2494 const name = data[fbs.pos..][0..name_length];
2495 fbs.pos += name_length;
2496 try writer.print("\nname {s}\n", .{name});
2399 const name = try br.take(try br.takeLeb128(u32));
2400 try bw.print("\nname {s}\n", .{name});
24972401
24982402 if (mem.eql(u8, name, "name")) {
2499 try parseDumpNames(step, reader, writer, data);
2403 try parseDumpNames(step, br, bw);
25002404 } else if (mem.eql(u8, name, "producers")) {
2501 try parseDumpProducers(reader, writer, data);
2405 try parseDumpProducers(br, bw);
25022406 } else if (mem.eql(u8, name, "target_features")) {
2503 try parseDumpFeatures(reader, writer, data);
2407 try parseDumpFeatures(br, bw);
25042408 }
25052409 // TODO: Implement parsing and dumping other custom sections (such as relocations)
25062410 },
25072411 .start => {
2508 const start = try std.leb.readUleb128(u32, reader);
2509 try writer.print("\nstart {d}\n", .{start});
2412 const start = try br.takeLeb128(u32);
2413 try bw.print("\nstart {d}\n", .{start});
25102414 },
25112415 .data_count => {
2512 const count = try std.leb.readUleb128(u32, reader);
2513 try writer.print("\ncount {d}\n", .{count});
2416 const count = try br.takeLeb128(u32);
2417 try bw.print("\ncount {d}\n", .{count});
25142418 },
25152419 else => {}, // skip unknown sections
25162420 }
25172421 }
25182422
2519 fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, writer: anytype) !void {
2520 var fbs = std.io.fixedBufferStream(data);
2521 const reader = fbs.reader();
2522
2423 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.Reader, entries: u32, bw: *Writer) !void {
25232424 switch (section) {
25242425 .type => {
25252426 var i: u32 = 0;
25262427 while (i < entries) : (i += 1) {
2527 const func_type = try reader.readByte();
2428 const func_type = try br.takeByte();
25282429 if (func_type != std.wasm.function_type) {
25292430 return step.fail("expected function type, found byte '{d}'", .{func_type});
25302431 }
2531 const params = try std.leb.readUleb128(u32, reader);
2532 try writer.print("params {d}\n", .{params});
2432 const params = try br.takeLeb128(u32);
2433 try bw.print("params {d}\n", .{params});
25332434 var index: u32 = 0;
25342435 while (index < params) : (index += 1) {
2535 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
2436 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
25362437 } else index = 0;
2537 const returns = try std.leb.readUleb128(u32, reader);
2538 try writer.print("returns {d}\n", .{returns});
2438 const returns = try br.takeLeb128(u32);
2439 try bw.print("returns {d}\n", .{returns});
25392440 while (index < returns) : (index += 1) {
2540 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
2441 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
25412442 }
25422443 }
25432444 },
25442445 .import => {
25452446 var i: u32 = 0;
25462447 while (i < entries) : (i += 1) {
2547 const module_name_len = try std.leb.readUleb128(u32, reader);
2548 const module_name = data[fbs.pos..][0..module_name_len];
2549 fbs.pos += module_name_len;
2550 const name_len = try std.leb.readUleb128(u32, reader);
2551 const name = data[fbs.pos..][0..name_len];
2552 fbs.pos += name_len;
2553
2554 const kind = std.enums.fromInt(std.wasm.ExternalKind, try reader.readByte()) orelse {
2555 return step.fail("invalid import kind", .{});
2448 const module_name = try br.take(try br.takeLeb128(u32));
2449 const name = try br.take(try br.takeLeb128(u32));
2450 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2451 error.InvalidEnumTag => return step.fail("invalid import kind", .{}),
2452 else => |e| return e,
25562453 };
25572454
2558 try writer.print(
2455 try bw.print(
25592456 \\module {s}
25602457 \\name {s}
25612458 \\kind {s}
25622459 , .{ module_name, name, @tagName(kind) });
2563 try writer.writeByte('\n');
2460 try bw.writeByte('\n');
25642461 switch (kind) {
2565 .function => {
2566 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2567 },
2568 .memory => {
2569 try parseDumpLimits(reader, writer);
2570 },
2462 .function => try bw.print("index {d}\n", .{try br.takeLeb128(u32)}),
2463 .memory => try parseDumpLimits(br, bw),
25712464 .global => {
2572 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
2573 try writer.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u32, reader)});
2465 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2466 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u32)});
25742467 },
25752468 .table => {
2576 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);
2577 try parseDumpLimits(reader, writer);
2469 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2470 try parseDumpLimits(br, bw);
25782471 },
25792472 }
25802473 }
......@@ -2582,60 +2475,58 @@ const WasmDumper = struct {
25822475 .function => {
25832476 var i: u32 = 0;
25842477 while (i < entries) : (i += 1) {
2585 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2478 try bw.print("index {d}\n", .{try br.takeLeb128(u32)});
25862479 }
25872480 },
25882481 .table => {
25892482 var i: u32 = 0;
25902483 while (i < entries) : (i += 1) {
2591 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);
2592 try parseDumpLimits(reader, writer);
2484 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2485 try parseDumpLimits(br, bw);
25932486 }
25942487 },
25952488 .memory => {
25962489 var i: u32 = 0;
25972490 while (i < entries) : (i += 1) {
2598 try parseDumpLimits(reader, writer);
2491 try parseDumpLimits(br, bw);
25992492 }
26002493 },
26012494 .global => {
26022495 var i: u32 = 0;
26032496 while (i < entries) : (i += 1) {
2604 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
2605 try writer.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u1, reader)});
2606 try parseDumpInit(step, reader, writer);
2497 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2498 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u1)});
2499 try parseDumpInit(step, br, bw);
26072500 }
26082501 },
26092502 .@"export" => {
26102503 var i: u32 = 0;
26112504 while (i < entries) : (i += 1) {
2612 const name_len = try std.leb.readUleb128(u32, reader);
2613 const name = data[fbs.pos..][0..name_len];
2614 fbs.pos += name_len;
2615 const kind_byte = try std.leb.readUleb128(u8, reader);
2616 const kind = std.enums.fromInt(std.wasm.ExternalKind, kind_byte) orelse {
2617 return step.fail("invalid export kind value '{d}'", .{kind_byte});
2505 const name = try br.take(try br.takeLeb128(u32));
2506 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2507 error.InvalidEnumTag => return step.fail("invalid export kind value", .{}),
2508 else => |e| return e,
26182509 };
2619 const index = try std.leb.readUleb128(u32, reader);
2620 try writer.print(
2510 const index = try br.takeLeb128(u32);
2511 try bw.print(
26212512 \\name {s}
26222513 \\kind {s}
26232514 \\index {d}
26242515 , .{ name, @tagName(kind), index });
2625 try writer.writeByte('\n');
2516 try bw.writeByte('\n');
26262517 }
26272518 },
26282519 .element => {
26292520 var i: u32 = 0;
26302521 while (i < entries) : (i += 1) {
2631 try writer.print("table index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2632 try parseDumpInit(step, reader, writer);
2522 try bw.print("table index {d}\n", .{try br.takeLeb128(u32)});
2523 try parseDumpInit(step, br, bw);
26332524
2634 const function_indexes = try std.leb.readUleb128(u32, reader);
2525 const function_indexes = try br.takeLeb128(u32);
26352526 var function_index: u32 = 0;
2636 try writer.print("indexes {d}\n", .{function_indexes});
2527 try bw.print("indexes {d}\n", .{function_indexes});
26372528 while (function_index < function_indexes) : (function_index += 1) {
2638 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2529 try bw.print("index {d}\n", .{try br.takeLeb128(u32)});
26392530 }
26402531 }
26412532 },
......@@ -2643,101 +2534,95 @@ const WasmDumper = struct {
26432534 .data => {
26442535 var i: u32 = 0;
26452536 while (i < entries) : (i += 1) {
2646 const flags = try std.leb.readUleb128(u32, reader);
2647 const index = if (flags & 0x02 != 0)
2648 try std.leb.readUleb128(u32, reader)
2649 else
2650 0;
2651 try writer.print("memory index 0x{x}\n", .{index});
2652 if (flags == 0) {
2653 try parseDumpInit(step, reader, writer);
2654 }
2655
2656 const size = try std.leb.readUleb128(u32, reader);
2657 try writer.print("size {d}\n", .{size});
2658 try reader.skipBytes(size, .{}); // we do not care about the content of the segments
2537 const flags: packed struct(u32) {
2538 passive: bool,
2539 memidx: bool,
2540 unused: u30,
2541 } = @bitCast(try br.takeLeb128(u32));
2542 const index = if (flags.memidx) try br.takeLeb128(u32) else 0;
2543 try bw.print("memory index 0x{x}\n", .{index});
2544 if (!flags.passive) try parseDumpInit(step, br, bw);
2545 const size = try br.takeLeb128(u32);
2546 try bw.print("size {d}\n", .{size});
2547 _ = try br.discard(.limited(size)); // we do not care about the content of the segments
26592548 }
26602549 },
26612550 else => unreachable,
26622551 }
26632552 }
26642553
2665 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, writer: anytype) !E {
2666 const byte = try reader.readByte();
2667 const tag = std.enums.fromInt(E, byte) orelse {
2668 return step.fail("invalid wasm type value '{d}'", .{byte});
2554 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.Reader, bw: *Writer) !E {
2555 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
2556 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
2557 else => |e| return e,
26692558 };
2670 try writer.print("type {s}\n", .{@tagName(tag)});
2559 try bw.print("type {s}\n", .{@tagName(tag)});
26712560 return tag;
26722561 }
26732562
2674 fn parseDumpLimits(reader: anytype, writer: anytype) !void {
2675 const flags = try std.leb.readUleb128(u8, reader);
2676 const min = try std.leb.readUleb128(u32, reader);
2563 fn parseDumpLimits(br: *std.io.Reader, bw: *Writer) !void {
2564 const flags = try br.takeLeb128(u8);
2565 const min = try br.takeLeb128(u32);
26772566
2678 try writer.print("min {x}\n", .{min});
2679 if (flags != 0) {
2680 try writer.print("max {x}\n", .{try std.leb.readUleb128(u32, reader)});
2681 }
2567 try bw.print("min {x}\n", .{min});
2568 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
26822569 }
26832570
2684 fn parseDumpInit(step: *Step, reader: anytype, writer: anytype) !void {
2685 const byte = try reader.readByte();
2686 const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse {
2687 return step.fail("invalid wasm opcode '{d}'", .{byte});
2571 fn parseDumpInit(step: *Step, br: *std.io.Reader, bw: *Writer) !void {
2572 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
2573 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
2574 else => |e| return e,
26882575 };
26892576 switch (opcode) {
2690 .i32_const => try writer.print("i32.const {x}\n", .{try std.leb.readIleb128(i32, reader)}),
2691 .i64_const => try writer.print("i64.const {x}\n", .{try std.leb.readIleb128(i64, reader)}),
2692 .f32_const => try writer.print("f32.const {x}\n", .{@as(f32, @bitCast(try reader.readInt(u32, .little)))}),
2693 .f64_const => try writer.print("f64.const {x}\n", .{@as(f64, @bitCast(try reader.readInt(u64, .little)))}),
2694 .global_get => try writer.print("global.get {x}\n", .{try std.leb.readUleb128(u32, reader)}),
2577 .i32_const => try bw.print("i32.const {x}\n", .{try br.takeLeb128(i32)}),
2578 .i64_const => try bw.print("i64.const {x}\n", .{try br.takeLeb128(i64)}),
2579 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try br.takeInt(u32, .little)))}),
2580 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try br.takeInt(u64, .little)))}),
2581 .global_get => try bw.print("global.get {x}\n", .{try br.takeLeb128(u32)}),
26952582 else => unreachable,
26962583 }
2697 const end_opcode = try std.leb.readUleb128(u8, reader);
2584 const end_opcode = try br.takeLeb128(u8);
26982585 if (end_opcode != @intFromEnum(std.wasm.Opcode.end)) {
26992586 return step.fail("expected 'end' opcode in init expression", .{});
27002587 }
27012588 }
27022589
27032590 /// https://webassembly.github.io/spec/core/appendix/custom.html
2704 fn parseDumpNames(step: *Step, reader: anytype, writer: anytype, data: []const u8) !void {
2705 while (reader.context.pos < data.len) {
2706 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, writer)) {
2591 fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *Writer) !void {
2592 var subsection_br: std.io.Reader = undefined;
2593 while (br.seek < br.buffer.len) {
2594 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
27072595 // The module name subsection ... consists of a single name
27082596 // that is assigned to the module itself.
27092597 .module => {
2710 const size = try std.leb.readUleb128(u32, reader);
2711 const name_len = try std.leb.readUleb128(u32, reader);
2712 if (size != name_len + 1) return error.BadSubsectionSize;
2713 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2714 try writer.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});
2715 reader.context.pos += name_len;
2598 subsection_br = .fixed(try br.take(try br.takeLeb128(u32)));
2599 const name = try subsection_br.take(try subsection_br.takeLeb128(u32));
2600 try bw.print(
2601 \\name {s}
2602 \\
2603 , .{name});
2604 if (subsection_br.seek != subsection_br.buffer.len) return error.BadSubsectionSize;
27162605 },
27172606
27182607 // The function name subsection ... consists of a name map
27192608 // assigning function names to function indices.
27202609 .function, .global, .data_segment => {
2721 const size = try std.leb.readUleb128(u32, reader);
2722 const entries = try std.leb.readUleb128(u32, reader);
2723 try writer.print(
2724 \\size {d}
2610 subsection_br = .fixed(try br.take(try br.takeLeb128(u32)));
2611 const entries = try br.takeLeb128(u32);
2612 try bw.print(
27252613 \\names {d}
27262614 \\
2727 , .{ size, entries });
2615 , .{entries});
27282616 for (0..entries) |_| {
2729 const index = try std.leb.readUleb128(u32, reader);
2730 const name_len = try std.leb.readUleb128(u32, reader);
2731 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2732 const name = data[reader.context.pos..][0..name_len];
2733 reader.context.pos += name.len;
2734
2735 try writer.print(
2617 const index = try br.takeLeb128(u32);
2618 const name = try br.take(try br.takeLeb128(u32));
2619 try bw.print(
27362620 \\index {d}
27372621 \\name {s}
27382622 \\
27392623 , .{ index, name });
27402624 }
2625 if (subsection_br.seek != subsection_br.buffer.len) return error.BadSubsectionSize;
27412626 },
27422627
27432628 // The local name subsection ... consists of an indirect name
......@@ -2752,52 +2637,49 @@ const WasmDumper = struct {
27522637 }
27532638 }
27542639
2755 fn parseDumpProducers(reader: anytype, writer: anytype, data: []const u8) !void {
2756 const field_count = try std.leb.readUleb128(u32, reader);
2757 try writer.print("fields {d}\n", .{field_count});
2640 fn parseDumpProducers(br: *std.io.Reader, bw: *Writer) !void {
2641 const field_count = try br.takeLeb128(u32);
2642 try bw.print(
2643 \\fields {d}
2644 \\
2645 , .{field_count});
27582646 var current_field: u32 = 0;
27592647 while (current_field < field_count) : (current_field += 1) {
2760 const field_name_length = try std.leb.readUleb128(u32, reader);
2761 const field_name = data[reader.context.pos..][0..field_name_length];
2762 reader.context.pos += field_name_length;
2763
2764 const value_count = try std.leb.readUleb128(u32, reader);
2765 try writer.print(
2648 const field_name = try br.take(try br.takeLeb128(u32));
2649 const value_count = try br.takeLeb128(u32);
2650 try bw.print(
27662651 \\field_name {s}
27672652 \\values {d}
2653 \\
27682654 , .{ field_name, value_count });
2769 try writer.writeByte('\n');
27702655 var current_value: u32 = 0;
27712656 while (current_value < value_count) : (current_value += 1) {
2772 const value_length = try std.leb.readUleb128(u32, reader);
2773 const value = data[reader.context.pos..][0..value_length];
2774 reader.context.pos += value_length;
2775
2776 const version_length = try std.leb.readUleb128(u32, reader);
2777 const version = data[reader.context.pos..][0..version_length];
2778 reader.context.pos += version_length;
2779
2780 try writer.print(
2657 const value = try br.take(try br.takeLeb128(u32));
2658 const version = try br.take(try br.takeLeb128(u32));
2659 try bw.print(
27812660 \\value_name {s}
27822661 \\version {s}
2662 \\
27832663 , .{ value, version });
2784 try writer.writeByte('\n');
27852664 }
27862665 }
27872666 }
27882667
2789 fn parseDumpFeatures(reader: anytype, writer: anytype, data: []const u8) !void {
2790 const feature_count = try std.leb.readUleb128(u32, reader);
2791 try writer.print("features {d}\n", .{feature_count});
2668 fn parseDumpFeatures(br: *std.io.Reader, bw: *Writer) !void {
2669 const feature_count = try br.takeLeb128(u32);
2670 try bw.print(
2671 \\features {d}
2672 \\
2673 , .{feature_count});
27922674
27932675 var index: u32 = 0;
27942676 while (index < feature_count) : (index += 1) {
2795 const prefix_byte = try std.leb.readUleb128(u8, reader);
2796 const name_length = try std.leb.readUleb128(u32, reader);
2797 const feature_name = data[reader.context.pos..][0..name_length];
2798 reader.context.pos += name_length;
2799
2800 try writer.print("{c} {s}\n", .{ prefix_byte, feature_name });
2677 const prefix_byte = try br.takeLeb128(u8);
2678 const feature_name = try br.take(try br.takeLeb128(u32));
2679 try bw.print(
2680 \\{c} {s}
2681 \\
2682 , .{ prefix_byte, feature_name });
28012683 }
28022684 }
28032685};
lib/std/Build/Step/Compile.zig+6-13
......@@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
15421542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
15431543 if (compile.version) |version| {
15441544 try zig_args.append("--version");
1545 try zig_args.append(b.fmt("{}", .{version}));
1545 try zig_args.append(b.fmt("{f}", .{version}));
15461546 }
15471547
15481548 if (compile.rootModuleTarget().os.tag.isDarwin()) {
......@@ -1696,9 +1696,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
16961696
16971697 if (compile.build_id orelse b.build_id) |build_id| {
16981698 try zig_args.append(switch (build_id) {
1699 .hexstring => |hs| b.fmt("--build-id=0x{s}", .{
1700 std.fmt.fmtSliceHexLower(hs.toSlice()),
1701 }),
1699 .hexstring => |hs| b.fmt("--build-id=0x{x}", .{hs.toSlice()}),
17021700 .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
17031701 });
17041702 }
......@@ -1706,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
17061704 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
17071705 dir.getPath2(b, step)
17081706 else if (b.graph.zig_lib_directory.path) |_|
1709 b.fmt("{}", .{b.graph.zig_lib_directory})
1707 b.fmt("{f}", .{b.graph.zig_lib_directory})
17101708 else
17111709 null;
17121710
......@@ -1746,8 +1744,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
17461744 }
17471745
17481746 if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{
1749 "--error-limit",
1750 b.fmt("{}", .{err_limit}),
1747 "--error-limit", b.fmt("{d}", .{err_limit}),
17511748 });
17521749
17531750 try addFlag(&zig_args, "incremental", b.graph.incremental);
......@@ -1793,11 +1790,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
17931790 var args_hash: [Sha256.digest_length]u8 = undefined;
17941791 Sha256.hash(args, &args_hash, .{});
17951792 var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;
1796 _ = try std.fmt.bufPrint(
1797 &args_hex_hash,
1798 "{s}",
1799 .{std.fmt.fmtSliceHexLower(&args_hash)},
1800 );
1793 _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});
18011794
18021795 const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;
18031796 try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });
......@@ -1836,7 +1829,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
18361829 // Update generated files
18371830 if (maybe_output_dir) |output_dir| {
18381831 if (compile.emit_directory) |lp| {
1839 lp.path = b.fmt("{}", .{output_dir});
1832 lp.path = b.fmt("{f}", .{output_dir});
18401833 }
18411834
18421835 // zig fmt: off
lib/std/Build/Step/ConfigHeader.zig+91-139
......@@ -2,6 +2,7 @@ const std = @import("std");
22const ConfigHeader = @This();
33const Step = std.Build.Step;
44const Allocator = std.mem.Allocator;
5const Writer = std.io.Writer;
56
67pub const Style = union(enum) {
78 /// A configure format supported by autotools that uses `#undef foo` to
......@@ -87,7 +88,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
8788 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
8889
8990 config_header.* = .{
90 .step = Step.init(.{
91 .step = .init(.{
9192 .id = base_id,
9293 .name = name,
9394 .owner = owner,
......@@ -95,7 +96,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
9596 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
9697 }),
9798 .style = options.style,
98 .values = std.StringArrayHashMap(Value).init(owner.allocator),
99 .values = .init(owner.allocator),
99100
100101 .max_bytes = options.max_bytes,
101102 .include_path = include_path,
......@@ -195,8 +196,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
195196 man.hash.addBytes(config_header.include_path);
196197 man.hash.addOptionalBytes(config_header.include_guard_override);
197198
198 var output = std.ArrayList(u8).init(gpa);
199 defer output.deinit();
199 var aw: std.io.Writer.Allocating = .init(gpa);
200 defer aw.deinit();
201 const bw = &aw.interface;
200202
201203 const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
202204 const c_generated_line = "/* " ++ header_text ++ " */\n";
......@@ -204,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
204206
205207 switch (config_header.style) {
206208 .autoconf_undef, .autoconf, .autoconf_at => |file_source| {
207 try output.appendSlice(c_generated_line);
209 try bw.writeAll(c_generated_line);
208210 const src_path = file_source.getPath2(b, step);
209211 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
210212 return step.fail("unable to read autoconf input file '{s}': {s}", .{
......@@ -212,32 +214,33 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
212214 });
213215 };
214216 switch (config_header.style) {
215 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path),
216 .autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path),
217 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
218 .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
217219 else => unreachable,
218220 }
219221 },
220222 .cmake => |file_source| {
221 try output.appendSlice(c_generated_line);
223 try bw.writeAll(c_generated_line);
222224 const src_path = file_source.getPath2(b, step);
223225 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
224226 return step.fail("unable to read cmake input file '{s}': {s}", .{
225227 src_path, @errorName(err),
226228 });
227229 };
228 try render_cmake(step, contents, &output, config_header.values, src_path);
230 try render_cmake(step, contents, bw, config_header.values, src_path);
229231 },
230232 .blank => {
231 try output.appendSlice(c_generated_line);
232 try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override);
233 try bw.writeAll(c_generated_line);
234 try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override);
233235 },
234236 .nasm => {
235 try output.appendSlice(asm_generated_line);
236 try render_nasm(&output, config_header.values);
237 try bw.writeAll(asm_generated_line);
238 try render_nasm(bw, config_header.values);
237239 },
238240 }
239241
240 man.hash.addBytes(output.items);
242 const output = aw.getWritten();
243 man.hash.addBytes(output);
241244
242245 if (try step.cacheHit(&man)) {
243246 const digest = man.final();
......@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
256259 const sub_path_dirname = std.fs.path.dirname(sub_path).?;
257260
258261 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
259 return step.fail("unable to make path '{}{s}': {s}", .{
262 return step.fail("unable to make path '{f}{s}': {s}", .{
260263 b.cache_root, sub_path_dirname, @errorName(err),
261264 });
262265 };
263266
264 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| {
265 return step.fail("unable to write file '{}{s}': {s}", .{
267 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| {
268 return step.fail("unable to write file '{f}{s}': {s}", .{
266269 b.cache_root, sub_path, @errorName(err),
267270 });
268271 };
......@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
274277fn render_autoconf_undef(
275278 step: *Step,
276279 contents: []const u8,
277 output: *std.ArrayList(u8),
280 bw: *Writer,
278281 values: std.StringArrayHashMap(Value),
279282 src_path: []const u8,
280283) !void {
......@@ -289,15 +292,15 @@ fn render_autoconf_undef(
289292 var line_it = std.mem.splitScalar(u8, contents, '\n');
290293 while (line_it.next()) |line| : (line_index += 1) {
291294 if (!std.mem.startsWith(u8, line, "#")) {
292 try output.appendSlice(line);
293 try output.appendSlice("\n");
295 try bw.writeAll(line);
296 try bw.writeByte('\n');
294297 continue;
295298 }
296299 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
297300 const undef = it.next().?;
298301 if (!std.mem.eql(u8, undef, "undef")) {
299 try output.appendSlice(line);
300 try output.appendSlice("\n");
302 try bw.writeAll(line);
303 try bw.writeByte('\n');
301304 continue;
302305 }
303306 const name = it.next().?;
......@@ -309,7 +312,7 @@ fn render_autoconf_undef(
309312 continue;
310313 };
311314 is_used.set(index);
312 try renderValueC(output, name, values.values()[index]);
315 try renderValueC(bw, name, values.values()[index]);
313316 }
314317
315318 var unused_value_it = is_used.iterator(.{ .kind = .unset });
......@@ -326,12 +329,13 @@ fn render_autoconf_undef(
326329fn render_autoconf_at(
327330 step: *Step,
328331 contents: []const u8,
329 output: *std.ArrayList(u8),
332 aw: *std.io.Writer.Allocating,
330333 values: std.StringArrayHashMap(Value),
331334 src_path: []const u8,
332335) !void {
333336 const build = step.owner;
334337 const allocator = build.allocator;
338 const bw = &aw.interface;
335339
336340 const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
337341 for (used) |*u| u.* = false;
......@@ -343,11 +347,11 @@ fn render_autoconf_at(
343347 while (line_it.next()) |line| : (line_index += 1) {
344348 const last_line = line_it.index == line_it.buffer.len;
345349
346 const old_len = output.items.len;
347 expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) {
350 const old_len = aw.getWritten().len;
351 expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) {
348352 error.MissingValue => {
349 const name = output.items[old_len..];
350 defer output.shrinkRetainingCapacity(old_len);
353 const name = aw.getWritten()[old_len..];
354 defer aw.shrinkRetainingCapacity(old_len);
351355 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
352356 src_path, line_index + 1, name,
353357 });
......@@ -362,9 +366,7 @@ fn render_autoconf_at(
362366 continue;
363367 },
364368 };
365 if (!last_line) {
366 try output.append('\n');
367 }
369 if (!last_line) try bw.writeByte('\n');
368370 }
369371
370372 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
......@@ -374,15 +376,13 @@ fn render_autoconf_at(
374376 }
375377 }
376378
377 if (any_errors) {
378 return error.MakeFailed;
379 }
379 if (any_errors) return error.MakeFailed;
380380}
381381
382382fn render_cmake(
383383 step: *Step,
384384 contents: []const u8,
385 output: *std.ArrayList(u8),
385 bw: *Writer,
386386 values: std.StringArrayHashMap(Value),
387387 src_path: []const u8,
388388) !void {
......@@ -417,10 +417,8 @@ fn render_cmake(
417417 defer allocator.free(line);
418418
419419 if (!std.mem.startsWith(u8, line, "#")) {
420 try output.appendSlice(line);
421 if (!last_line) {
422 try output.appendSlice("\n");
423 }
420 try bw.writeAll(line);
421 if (!last_line) try bw.writeByte('\n');
424422 continue;
425423 }
426424 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
......@@ -428,10 +426,8 @@ fn render_cmake(
428426 if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
429427 !std.mem.eql(u8, cmakedefine, "cmakedefine01"))
430428 {
431 try output.appendSlice(line);
432 if (!last_line) {
433 try output.appendSlice("\n");
434 }
429 try bw.writeAll(line);
430 if (!last_line) try bw.writeByte('\n');
435431 continue;
436432 }
437433
......@@ -502,7 +498,7 @@ fn render_cmake(
502498 value = Value{ .ident = it.rest() };
503499 }
504500
505 try renderValueC(output, name, value);
501 try renderValueC(bw, name, value);
506502 }
507503
508504 if (any_errors) {
......@@ -511,13 +507,14 @@ fn render_cmake(
511507}
512508
513509fn render_blank(
514 output: *std.ArrayList(u8),
510 gpa: std.mem.Allocator,
511 bw: *Writer,
515512 defines: std.StringArrayHashMap(Value),
516513 include_path: []const u8,
517514 include_guard_override: ?[]const u8,
518515) !void {
519516 const include_guard_name = include_guard_override orelse blk: {
520 const name = try output.allocator.dupe(u8, include_path);
517 const name = try gpa.dupe(u8, include_path);
521518 for (name) |*byte| {
522519 switch (byte.*) {
523520 'a'...'z' => byte.* = byte.* - 'a' + 'A',
......@@ -527,92 +524,53 @@ fn render_blank(
527524 }
528525 break :blk name;
529526 };
527 defer if (include_guard_override == null) gpa.free(include_guard_name);
530528
531 try output.appendSlice("#ifndef ");
532 try output.appendSlice(include_guard_name);
533 try output.appendSlice("\n#define ");
534 try output.appendSlice(include_guard_name);
535 try output.appendSlice("\n");
529 try bw.print(
530 \\#ifndef {[0]s}
531 \\#define {[0]s}
532 \\
533 , .{include_guard_name});
536534
537535 const values = defines.values();
538 for (defines.keys(), 0..) |name, i| {
539 try renderValueC(output, name, values[i]);
540 }
536 for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]);
541537
542 try output.appendSlice("#endif /* ");
543 try output.appendSlice(include_guard_name);
544 try output.appendSlice(" */\n");
538 try bw.print(
539 \\#endif /* {s} */
540 \\
541 , .{include_guard_name});
545542}
546543
547fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void {
548 const values = defines.values();
549 for (defines.keys(), 0..) |name, i| {
550 try renderValueNasm(output, name, values[i]);
551 }
544fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {
545 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
552546}
553547
554fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {
548fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void {
555549 switch (value) {
556 .undef => {
557 try output.appendSlice("/* #undef ");
558 try output.appendSlice(name);
559 try output.appendSlice(" */\n");
560 },
561 .defined => {
562 try output.appendSlice("#define ");
563 try output.appendSlice(name);
564 try output.appendSlice("\n");
565 },
566 .boolean => |b| {
567 try output.appendSlice("#define ");
568 try output.appendSlice(name);
569 try output.appendSlice(if (b) " 1\n" else " 0\n");
570 },
571 .int => |i| {
572 try output.writer().print("#define {s} {d}\n", .{ name, i });
573 },
574 .ident => |ident| {
575 try output.writer().print("#define {s} {s}\n", .{ name, ident });
576 },
577 .string => |string| {
578 // TODO: use C-specific escaping instead of zig string literals
579 try output.writer().print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
580 },
550 .undef => try bw.print("/* #undef {s} */\n", .{name}),
551 .defined => try bw.print("#define {s}\n", .{name}),
552 .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
553 .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }),
554 .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }),
555 // TODO: use C-specific escaping instead of zig string literals
556 .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
581557 }
582558}
583559
584fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {
560fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
585561 switch (value) {
586 .undef => {
587 try output.appendSlice("; %undef ");
588 try output.appendSlice(name);
589 try output.appendSlice("\n");
590 },
591 .defined => {
592 try output.appendSlice("%define ");
593 try output.appendSlice(name);
594 try output.appendSlice("\n");
595 },
596 .boolean => |b| {
597 try output.appendSlice("%define ");
598 try output.appendSlice(name);
599 try output.appendSlice(if (b) " 1\n" else " 0\n");
600 },
601 .int => |i| {
602 try output.writer().print("%define {s} {d}\n", .{ name, i });
603 },
604 .ident => |ident| {
605 try output.writer().print("%define {s} {s}\n", .{ name, ident });
606 },
607 .string => |string| {
608 // TODO: use nasm-specific escaping instead of zig string literals
609 try output.writer().print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
610 },
562 .undef => try bw.print("; %undef {s}\n", .{name}),
563 .defined => try bw.print("%define {s}\n", .{name}),
564 .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
565 .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }),
566 .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }),
567 // TODO: use nasm-specific escaping instead of zig string literals
568 .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
611569 }
612570}
613571
614572fn expand_variables_autoconf_at(
615 output: *std.ArrayList(u8),
573 bw: *Writer,
616574 contents: []const u8,
617575 values: std.StringArrayHashMap(Value),
618576 used: []bool,
......@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(
637595 const key = contents[curr + 1 .. close_pos];
638596 const index = values.getIndex(key) orelse {
639597 // Report the missing key to the caller.
640 try output.appendSlice(key);
598 try bw.writeAll(key);
641599 return error.MissingValue;
642600 };
643601 const value = values.unmanaged.entries.slice().items(.value)[index];
644602 used[index] = true;
645 try output.appendSlice(contents[source_offset..curr]);
603 try bw.writeAll(contents[source_offset..curr]);
646604 switch (value) {
647605 .undef, .defined => {},
648 .boolean => |b| {
649 try output.append(if (b) '1' else '0');
650 },
651 .int => |i| {
652 try output.writer().print("{d}", .{i});
653 },
654 .ident, .string => |s| {
655 try output.appendSlice(s);
656 },
606 .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)),
607 .int => |i| try bw.print("{d}", .{i}),
608 .ident, .string => |s| try bw.writeAll(s),
657609 }
658610
659611 curr = close_pos;
......@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(
661613 }
662614 }
663615
664 try output.appendSlice(contents[source_offset..]);
616 try bw.writeAll(contents[source_offset..]);
665617}
666618
667619fn expand_variables_cmake(
......@@ -669,7 +621,7 @@ fn expand_variables_cmake(
669621 contents: []const u8,
670622 values: std.StringArrayHashMap(Value),
671623) ![]const u8 {
672 var result = std.ArrayList(u8).init(allocator);
624 var result: std.ArrayList(u8) = .init(allocator);
673625 errdefer result.deinit();
674626
675627 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
......@@ -681,7 +633,7 @@ fn expand_variables_cmake(
681633 source: usize,
682634 target: usize,
683635 };
684 var var_stack = std.ArrayList(Position).init(allocator);
636 var var_stack: std.ArrayList(Position) = .init(allocator);
685637 defer var_stack.deinit();
686638 loop: while (curr < contents.len) : (curr += 1) {
687639 switch (contents[curr]) {
......@@ -707,7 +659,7 @@ fn expand_variables_cmake(
707659 try result.append(if (b) '1' else '0');
708660 },
709661 .int => |i| {
710 try result.writer().print("{d}", .{i});
662 try result.print("{d}", .{i});
711663 },
712664 .ident, .string => |s| {
713665 try result.appendSlice(s);
......@@ -764,7 +716,7 @@ fn expand_variables_cmake(
764716 try result.append(if (b) '1' else '0');
765717 },
766718 .int => |i| {
767 try result.writer().print("{d}", .{i});
719 try result.print("{d}", .{i});
768720 },
769721 .ident, .string => |s| {
770722 try result.appendSlice(s);
......@@ -801,17 +753,17 @@ fn testReplaceVariablesAutoconfAt(
801753 expected: []const u8,
802754 values: std.StringArrayHashMap(Value),
803755) !void {
804 var output = std.ArrayList(u8).init(allocator);
756 var output: std.io.Writer.Allocating = .init(allocator);
805757 defer output.deinit();
806758
807759 const used = try allocator.alloc(bool, values.count());
808760 for (used) |*u| u.* = false;
809761 defer allocator.free(used);
810762
811 try expand_variables_autoconf_at(&output, contents, values, used);
763 try expand_variables_autoconf_at(&output.interface, contents, values, used);
812764
813765 for (used) |u| if (!u) return error.UnusedValue;
814 try std.testing.expectEqualStrings(expected, output.items);
766 try std.testing.expectEqualStrings(expected, output.getWritten());
815767}
816768
817769fn testReplaceVariablesCMake(
......@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(
828780
829781test "expand_variables_autoconf_at simple cases" {
830782 const allocator = std.testing.allocator;
831 var values = std.StringArrayHashMap(Value).init(allocator);
783 var values: std.StringArrayHashMap(Value) = .init(allocator);
832784 defer values.deinit();
833785
834786 // empty strings are preserved
......@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {
924876
925877test "expand_variables_autoconf_at edge cases" {
926878 const allocator = std.testing.allocator;
927 var values = std.StringArrayHashMap(Value).init(allocator);
879 var values: std.StringArrayHashMap(Value) = .init(allocator);
928880 defer values.deinit();
929881
930882 // @-vars resolved only when they wrap valid characters, otherwise considered literals
......@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {
940892
941893test "expand_variables_cmake simple cases" {
942894 const allocator = std.testing.allocator;
943 var values = std.StringArrayHashMap(Value).init(allocator);
895 var values: std.StringArrayHashMap(Value) = .init(allocator);
944896 defer values.deinit();
945897
946898 try values.putNoClobber("undef", .undef);
......@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {
1028980
1029981test "expand_variables_cmake edge cases" {
1030982 const allocator = std.testing.allocator;
1031 var values = std.StringArrayHashMap(Value).init(allocator);
983 var values: std.StringArrayHashMap(Value) = .init(allocator);
1032984 defer values.deinit();
1033985
1034986 // special symbols
......@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {
10891041
10901042test "expand_variables_cmake escaped characters" {
10911043 const allocator = std.testing.allocator;
1092 var values = std.StringArrayHashMap(Value).init(allocator);
1044 var values: std.StringArrayHashMap(Value) = .init(allocator);
10931045 defer values.deinit();
10941046
10951047 try values.putNoClobber("string", Value{ .string = "text" });
lib/std/Build/Step/InstallArtifact.zig+1-1
......@@ -164,7 +164,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
164164 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
165165
166166 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
167 return step.fail("unable to open source directory '{}': {s}", .{
167 return step.fail("unable to open source directory '{f}': {s}", .{
168168 src_dir_path, @errorName(err),
169169 });
170170 };
lib/std/Build/Step/InstallDir.zig+1-1
......@@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
6565 const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
6666 const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
6767 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
68 return step.fail("unable to open source directory '{}': {s}", .{
68 return step.fail("unable to open source directory '{f}': {s}", .{
6969 src_dir_path, @errorName(err),
7070 });
7171 };
lib/std/Build/Step/Options.zig+146-112
......@@ -12,23 +12,23 @@ pub const base_id: Step.Id = .options;
1212step: Step,
1313generated_file: GeneratedFile,
1414
15contents: std.ArrayList(u8),
16args: std.ArrayList(Arg),
17encountered_types: std.StringHashMap(void),
15contents: std.ArrayListUnmanaged(u8),
16args: std.ArrayListUnmanaged(Arg),
17encountered_types: std.StringHashMapUnmanaged(void),
1818
1919pub fn create(owner: *std.Build) *Options {
2020 const options = owner.allocator.create(Options) catch @panic("OOM");
2121 options.* = .{
22 .step = Step.init(.{
22 .step = .init(.{
2323 .id = base_id,
2424 .name = "options",
2525 .owner = owner,
2626 .makeFn = make,
2727 }),
2828 .generated_file = undefined,
29 .contents = std.ArrayList(u8).init(owner.allocator),
30 .args = std.ArrayList(Arg).init(owner.allocator),
31 .encountered_types = std.StringHashMap(void).init(owner.allocator),
29 .contents = .empty,
30 .args = .empty,
31 .encountered_types = .empty,
3232 };
3333 options.generated_file = .{ .step = &options.step };
3434
......@@ -40,110 +40,119 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T
4040}
4141
4242fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {
43 const out = options.contents.writer();
44 try printType(options, out, T, value, 0, name);
43 try printType(options, &options.contents, T, value, 0, name);
4544}
4645
47fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent: u8, name: ?[]const u8) !void {
46fn printType(
47 options: *Options,
48 out: *std.ArrayListUnmanaged(u8),
49 comptime T: type,
50 value: T,
51 indent: u8,
52 name: ?[]const u8,
53) !void {
54 const gpa = options.step.owner.allocator;
4855 switch (T) {
4956 []const []const u8 => {
5057 if (name) |payload| {
51 try out.print("pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
58 try out.print(gpa, "pub const {f}: []const []const u8 = ", .{std.zig.fmtId(payload)});
5259 }
5360
54 try out.writeAll("&[_][]const u8{\n");
61 try out.appendSlice(gpa, "&[_][]const u8{\n");
5562
5663 for (value) |slice| {
57 try out.writeByteNTimes(' ', indent);
58 try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)});
64 try out.appendNTimes(gpa, ' ', indent);
65 try out.print(gpa, " \"{f}\",\n", .{std.zig.fmtString(slice)});
5966 }
6067
6168 if (name != null) {
62 try out.writeAll("};\n");
69 try out.appendSlice(gpa, "};\n");
6370 } else {
64 try out.writeAll("},\n");
71 try out.appendSlice(gpa, "},\n");
6572 }
6673
6774 return;
6875 },
6976 []const u8 => {
7077 if (name) |some| {
71 try out.print("pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
78 try out.print(gpa, "pub const {f}: []const u8 = \"{f}\";", .{
79 std.zig.fmtId(some), std.zig.fmtString(value),
80 });
7281 } else {
73 try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});
82 try out.print(gpa, "\"{f}\",", .{std.zig.fmtString(value)});
7483 }
75 return out.writeAll("\n");
84 return out.appendSlice(gpa, "\n");
7685 },
7786 [:0]const u8 => {
7887 if (name) |some| {
79 try out.print("pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
88 try out.print(gpa, "pub const {f}: [:0]const u8 = \"{f}\";", .{ std.zig.fmtId(some), std.zig.fmtString(value) });
8089 } else {
81 try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});
90 try out.print(gpa, "\"{f}\",", .{std.zig.fmtString(value)});
8291 }
83 return out.writeAll("\n");
92 return out.appendSlice(gpa, "\n");
8493 },
8594 ?[]const u8 => {
8695 if (name) |some| {
87 try out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(some)});
96 try out.print(gpa, "pub const {f}: ?[]const u8 = ", .{std.zig.fmtId(some)});
8897 }
8998
9099 if (value) |payload| {
91 try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});
100 try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)});
92101 } else {
93 try out.writeAll("null");
102 try out.appendSlice(gpa, "null");
94103 }
95104
96105 if (name != null) {
97 try out.writeAll(";\n");
106 try out.appendSlice(gpa, ";\n");
98107 } else {
99 try out.writeAll(",\n");
108 try out.appendSlice(gpa, ",\n");
100109 }
101110 return;
102111 },
103112 ?[:0]const u8 => {
104113 if (name) |some| {
105 try out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
114 try out.print(gpa, "pub const {f}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
106115 }
107116
108117 if (value) |payload| {
109 try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});
118 try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)});
110119 } else {
111 try out.writeAll("null");
120 try out.appendSlice(gpa, "null");
112121 }
113122
114123 if (name != null) {
115 try out.writeAll(";\n");
124 try out.appendSlice(gpa, ";\n");
116125 } else {
117 try out.writeAll(",\n");
126 try out.appendSlice(gpa, ",\n");
118127 }
119128 return;
120129 },
121130 std.SemanticVersion => {
122131 if (name) |some| {
123 try out.print("pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
132 try out.print(gpa, "pub const {f}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
124133 }
125134
126 try out.writeAll(".{\n");
127 try out.writeByteNTimes(' ', indent);
128 try out.print(" .major = {d},\n", .{value.major});
129 try out.writeByteNTimes(' ', indent);
130 try out.print(" .minor = {d},\n", .{value.minor});
131 try out.writeByteNTimes(' ', indent);
132 try out.print(" .patch = {d},\n", .{value.patch});
135 try out.appendSlice(gpa, ".{\n");
136 try out.appendNTimes(gpa, ' ', indent);
137 try out.print(gpa, " .major = {d},\n", .{value.major});
138 try out.appendNTimes(gpa, ' ', indent);
139 try out.print(gpa, " .minor = {d},\n", .{value.minor});
140 try out.appendNTimes(gpa, ' ', indent);
141 try out.print(gpa, " .patch = {d},\n", .{value.patch});
133142
134143 if (value.pre) |some| {
135 try out.writeByteNTimes(' ', indent);
136 try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
144 try out.appendNTimes(gpa, ' ', indent);
145 try out.print(gpa, " .pre = \"{f}\",\n", .{std.zig.fmtString(some)});
137146 }
138147 if (value.build) |some| {
139 try out.writeByteNTimes(' ', indent);
140 try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
148 try out.appendNTimes(gpa, ' ', indent);
149 try out.print(gpa, " .build = \"{f}\",\n", .{std.zig.fmtString(some)});
141150 }
142151
143152 if (name != null) {
144 try out.writeAll("};\n");
153 try out.appendSlice(gpa, "};\n");
145154 } else {
146 try out.writeAll("},\n");
155 try out.appendSlice(gpa, "},\n");
147156 }
148157 return;
149158 },
......@@ -153,21 +162,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
153162 switch (@typeInfo(T)) {
154163 .array => {
155164 if (name) |some| {
156 try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
165 try out.print(gpa, "pub const {f}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
157166 }
158167
159 try out.print("{s} {{\n", .{@typeName(T)});
168 try out.print(gpa, "{s} {{\n", .{@typeName(T)});
160169 for (value) |item| {
161 try out.writeByteNTimes(' ', indent + 4);
170 try out.appendNTimes(gpa, ' ', indent + 4);
162171 try printType(options, out, @TypeOf(item), item, indent + 4, null);
163172 }
164 try out.writeByteNTimes(' ', indent);
165 try out.writeAll("}");
173 try out.appendNTimes(gpa, ' ', indent);
174 try out.appendSlice(gpa, "}");
166175
167176 if (name != null) {
168 try out.writeAll(";\n");
177 try out.appendSlice(gpa, ";\n");
169178 } else {
170 try out.writeAll(",\n");
179 try out.appendSlice(gpa, ",\n");
171180 }
172181 return;
173182 },
......@@ -177,27 +186,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
177186 }
178187
179188 if (name) |some| {
180 try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
189 try out.print(gpa, "pub const {f}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
181190 }
182191
183 try out.print("&[_]{s} {{\n", .{@typeName(p.child)});
192 try out.print(gpa, "&[_]{s} {{\n", .{@typeName(p.child)});
184193 for (value) |item| {
185 try out.writeByteNTimes(' ', indent + 4);
194 try out.appendNTimes(gpa, ' ', indent + 4);
186195 try printType(options, out, @TypeOf(item), item, indent + 4, null);
187196 }
188 try out.writeByteNTimes(' ', indent);
189 try out.writeAll("}");
197 try out.appendNTimes(gpa, ' ', indent);
198 try out.appendSlice(gpa, "}");
190199
191200 if (name != null) {
192 try out.writeAll(";\n");
201 try out.appendSlice(gpa, ";\n");
193202 } else {
194 try out.writeAll(",\n");
203 try out.appendSlice(gpa, ",\n");
195204 }
196205 return;
197206 },
198207 .optional => {
199208 if (name) |some| {
200 try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
209 try out.print(gpa, "pub const {f}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
201210 }
202211
203212 if (value) |inner| {
......@@ -206,13 +215,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
206215 _ = options.contents.pop();
207216 _ = options.contents.pop();
208217 } else {
209 try out.writeAll("null");
218 try out.appendSlice(gpa, "null");
210219 }
211220
212221 if (name != null) {
213 try out.writeAll(";\n");
222 try out.appendSlice(gpa, ";\n");
214223 } else {
215 try out.writeAll(",\n");
224 try out.appendSlice(gpa, ",\n");
216225 }
217226 return;
218227 },
......@@ -224,9 +233,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
224233 .null,
225234 => {
226235 if (name) |some| {
227 try out.print("pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
236 try out.print(gpa, "pub const {f}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
228237 } else {
229 try out.print("{any},\n", .{value});
238 try out.print(gpa, "{any},\n", .{value});
230239 }
231240 return;
232241 },
......@@ -234,10 +243,10 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
234243 try printEnum(options, out, T, info, indent);
235244
236245 if (name) |some| {
237 try out.print("pub const {}: {} = .{p_};\n", .{
246 try out.print(gpa, "pub const {f}: {f} = .{f};\n", .{
238247 std.zig.fmtId(some),
239248 std.zig.fmtId(@typeName(T)),
240 std.zig.fmtId(@tagName(value)),
249 std.zig.fmtIdFlags(@tagName(value), .{ .allow_underscore = true, .allow_primitive = true }),
241250 });
242251 }
243252 return;
......@@ -246,7 +255,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
246255 try printStruct(options, out, T, info, indent);
247256
248257 if (name) |some| {
249 try out.print("pub const {}: {} = ", .{
258 try out.print(gpa, "pub const {f}: {f} = ", .{
250259 std.zig.fmtId(some),
251260 std.zig.fmtId(@typeName(T)),
252261 });
......@@ -258,7 +267,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
258267 }
259268}
260269
261fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, indent: u8) !void {
270fn printUserDefinedType(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, indent: u8) !void {
262271 switch (@typeInfo(T)) {
263272 .@"enum" => |info| {
264273 return try printEnum(options, out, T, info, indent);
......@@ -270,94 +279,119 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden
270279 }
271280}
272281
273fn printEnum(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Enum, indent: u8) !void {
274 const gop = try options.encountered_types.getOrPut(@typeName(T));
282fn printEnum(
283 options: *Options,
284 out: *std.ArrayListUnmanaged(u8),
285 comptime T: type,
286 comptime val: std.builtin.Type.Enum,
287 indent: u8,
288) !void {
289 const gpa = options.step.owner.allocator;
290 const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
275291 if (gop.found_existing) return;
276292
277 try out.writeByteNTimes(' ', indent);
278 try out.print("pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
293 try out.appendNTimes(gpa, ' ', indent);
294 try out.print(gpa, "pub const {f} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
279295
280296 inline for (val.fields) |field| {
281 try out.writeByteNTimes(' ', indent);
282 try out.print(" {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
297 try out.appendNTimes(gpa, ' ', indent);
298 try out.print(gpa, " {f} = {d},\n", .{
299 std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true }), field.value,
300 });
283301 }
284302
285303 if (!val.is_exhaustive) {
286 try out.writeByteNTimes(' ', indent);
287 try out.writeAll(" _,\n");
304 try out.appendNTimes(gpa, ' ', indent);
305 try out.appendSlice(gpa, " _,\n");
288306 }
289307
290 try out.writeByteNTimes(' ', indent);
291 try out.writeAll("};\n");
308 try out.appendNTimes(gpa, ' ', indent);
309 try out.appendSlice(gpa, "};\n");
292310}
293311
294fn printStruct(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
295 const gop = try options.encountered_types.getOrPut(@typeName(T));
312fn printStruct(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
313 const gpa = options.step.owner.allocator;
314 const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
296315 if (gop.found_existing) return;
297316
298 try out.writeByteNTimes(' ', indent);
299 try out.print("pub const {} = ", .{std.zig.fmtId(@typeName(T))});
317 try out.appendNTimes(gpa, ' ', indent);
318 try out.print(gpa, "pub const {f} = ", .{std.zig.fmtId(@typeName(T))});
300319
301320 switch (val.layout) {
302 .@"extern" => try out.writeAll("extern struct"),
303 .@"packed" => try out.writeAll("packed struct"),
304 else => try out.writeAll("struct"),
321 .@"extern" => try out.appendSlice(gpa, "extern struct"),
322 .@"packed" => try out.appendSlice(gpa, "packed struct"),
323 else => try out.appendSlice(gpa, "struct"),
305324 }
306325
307 try out.writeAll(" {\n");
326 try out.appendSlice(gpa, " {\n");
308327
309328 inline for (val.fields) |field| {
310 try out.writeByteNTimes(' ', indent);
329 try out.appendNTimes(gpa, ' ', indent);
311330
312331 const type_name = @typeName(field.type);
313332
314333 // If the type name doesn't contains a '.' the type is from zig builtins.
315334 if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {
316 try out.print(" {p_}: {}", .{ std.zig.fmtId(field.name), std.zig.fmtId(type_name) });
335 try out.print(gpa, " {f}: {f}", .{
336 std.zig.fmtIdFlags(field.name, .{ .allow_underscore = true, .allow_primitive = true }),
337 std.zig.fmtId(type_name),
338 });
317339 } else {
318 try out.print(" {p_}: {s}", .{ std.zig.fmtId(field.name), type_name });
340 try out.print(gpa, " {f}: {s}", .{
341 std.zig.fmtIdFlags(field.name, .{ .allow_underscore = true, .allow_primitive = true }),
342 type_name,
343 });
319344 }
320345
321346 if (field.defaultValue()) |default_value| {
322 try out.writeAll(" = ");
347 try out.appendSlice(gpa, " = ");
323348 switch (@typeInfo(@TypeOf(default_value))) {
324 .@"enum" => try out.print(".{s},\n", .{@tagName(default_value)}),
349 .@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(default_value)}),
325350 .@"struct" => |info| {
326351 try printStructValue(options, out, info, default_value, indent + 4);
327352 },
328353 else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
329354 }
330355 } else {
331 try out.writeAll(",\n");
356 try out.appendSlice(gpa, ",\n");
332357 }
333358 }
334359
335360 // TODO: write declarations
336361
337 try out.writeByteNTimes(' ', indent);
338 try out.writeAll("};\n");
362 try out.appendNTimes(gpa, ' ', indent);
363 try out.appendSlice(gpa, "};\n");
339364
340365 inline for (val.fields) |field| {
341366 try printUserDefinedType(options, out, field.type, 0);
342367 }
343368}
344369
345fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.builtin.Type.Struct, val: anytype, indent: u8) !void {
346 try out.writeAll(".{\n");
370fn printStructValue(
371 options: *Options,
372 out: *std.ArrayListUnmanaged(u8),
373 comptime struct_val: std.builtin.Type.Struct,
374 val: anytype,
375 indent: u8,
376) !void {
377 const gpa = options.step.owner.allocator;
378 try out.appendSlice(gpa, ".{\n");
347379
348380 if (struct_val.is_tuple) {
349381 inline for (struct_val.fields) |field| {
350 try out.writeByteNTimes(' ', indent);
382 try out.appendNTimes(gpa, ' ', indent);
351383 try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
352384 }
353385 } else {
354386 inline for (struct_val.fields) |field| {
355 try out.writeByteNTimes(' ', indent);
356 try out.print(" .{p_} = ", .{std.zig.fmtId(field.name)});
387 try out.appendNTimes(gpa, ' ', indent);
388 try out.print(gpa, " .{f} = ", .{
389 std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true, .allow_underscore = true }),
390 });
357391
358392 const field_name = @field(val, field.name);
359393 switch (@typeInfo(@TypeOf(field_name))) {
360 .@"enum" => try out.print(".{s},\n", .{@tagName(field_name)}),
394 .@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(field_name)}),
361395 .@"struct" => |struct_info| {
362396 try printStructValue(options, out, struct_info, field_name, indent + 4);
363397 },
......@@ -367,10 +401,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu
367401 }
368402
369403 if (indent == 0) {
370 try out.writeAll("};\n");
404 try out.appendSlice(gpa, "};\n");
371405 } else {
372 try out.writeByteNTimes(' ', indent);
373 try out.writeAll("},\n");
406 try out.appendNTimes(gpa, ' ', indent);
407 try out.appendSlice(gpa, "},\n");
374408 }
375409}
376410
......@@ -440,7 +474,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
440474 error.FileNotFound => {
441475 const sub_dirname = fs.path.dirname(sub_path).?;
442476 b.cache_root.handle.makePath(sub_dirname) catch |e| {
443 return step.fail("unable to make path '{}{s}': {s}", .{
477 return step.fail("unable to make path '{f}{s}': {s}", .{
444478 b.cache_root, sub_dirname, @errorName(e),
445479 });
446480 };
......@@ -452,13 +486,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
452486 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
453487
454488 b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {
455 return step.fail("unable to make temporary directory '{}{s}': {s}", .{
489 return step.fail("unable to make temporary directory '{f}{s}': {s}", .{
456490 b.cache_root, tmp_sub_path_dirname, @errorName(err),
457491 });
458492 };
459493
460494 b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {
461 return step.fail("unable to write options to '{}{s}': {s}", .{
495 return step.fail("unable to write options to '{f}{s}': {s}", .{
462496 b.cache_root, tmp_sub_path, @errorName(err),
463497 });
464498 };
......@@ -467,7 +501,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
467501 error.PathAlreadyExists => {
468502 // Other process beat us to it. Clean up the temp file.
469503 b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {
470 try step.addError("warning: unable to delete temp file '{}{s}': {s}", .{
504 try step.addError("warning: unable to delete temp file '{f}{s}': {s}", .{
471505 b.cache_root, tmp_sub_path, @errorName(e),
472506 });
473507 };
......@@ -475,7 +509,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
475509 return;
476510 },
477511 else => {
478 return step.fail("unable to rename options from '{}{s}' to '{}{s}': {s}", .{
512 return step.fail("unable to rename options from '{f}{s}' to '{f}{s}': {s}", .{
479513 b.cache_root, tmp_sub_path,
480514 b.cache_root, sub_path,
481515 @errorName(err),
......@@ -483,7 +517,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
483517 },
484518 };
485519 },
486 else => |e| return step.fail("unable to access options file '{}{s}': {s}", .{
520 else => |e| return step.fail("unable to access options file '{f}{s}': {s}", .{
487521 b.cache_root, sub_path, @errorName(e),
488522 }),
489523 }
......@@ -643,5 +677,5 @@ test Options {
643677 \\
644678 , options.contents.items);
645679
646 _ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(0), .zig);
680 _ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(arena.allocator(), 0), .zig);
647681}
lib/std/Build/Step/Run.zig+19-26
......@@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
832832 else => unreachable,
833833 };
834834 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
835 return step.fail("unable to make path '{}{s}': {s}", .{
835 return step.fail("unable to make path '{f}{s}': {s}", .{
836836 b.cache_root, output_sub_dir_path, @errorName(err),
837837 });
838838 };
......@@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
864864 else => unreachable,
865865 };
866866 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
867 return step.fail("unable to make path '{}{s}': {s}", .{
867 return step.fail("unable to make path '{f}{s}': {s}", .{
868868 b.cache_root, output_sub_dir_path, @errorName(err),
869869 });
870870 };
......@@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
903903 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {
904904 if (err == error.PathAlreadyExists) {
905905 b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| {
906 return step.fail("unable to remove dir '{}'{s}: {s}", .{
906 return step.fail("unable to remove dir '{f}'{s}: {s}", .{
907907 b.cache_root,
908908 tmp_dir_path,
909909 @errorName(del_err),
910910 });
911911 };
912912 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| {
913 return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{
913 return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{
914914 b.cache_root, tmp_dir_path,
915915 b.cache_root, o_sub_path,
916916 @errorName(retry_err),
917917 });
918918 };
919919 } else {
920 return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{
920 return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{
921921 b.cache_root, tmp_dir_path,
922922 b.cache_root, o_sub_path,
923923 @errorName(err),
......@@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(
964964 .artifact => |pa| {
965965 const artifact = pa.artifact;
966966 const file_path: []const u8 = p: {
967 if (artifact == run.producer.?) break :p b.fmt("{}", .{run.rebuilt_executable.?});
967 if (artifact == run.producer.?) break :p b.fmt("{f}", .{run.rebuilt_executable.?});
968968 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
969969 };
970970 try argv_list.append(arena, b.fmt("{s}{s}", .{
......@@ -1011,24 +1011,17 @@ fn populateGeneratedPaths(
10111011 }
10121012}
10131013
1014fn formatTerm(
1015 term: ?std.process.Child.Term,
1016 comptime fmt: []const u8,
1017 options: std.fmt.FormatOptions,
1018 writer: anytype,
1019) !void {
1020 _ = fmt;
1021 _ = options;
1014fn formatTerm(term: ?std.process.Child.Term, w: *std.io.Writer) std.io.Writer.Error!void {
10221015 if (term) |t| switch (t) {
1023 .Exited => |code| try writer.print("exited with code {}", .{code}),
1024 .Signal => |sig| try writer.print("terminated with signal {}", .{sig}),
1025 .Stopped => |sig| try writer.print("stopped with signal {}", .{sig}),
1026 .Unknown => |code| try writer.print("terminated for unknown reason with code {}", .{code}),
1016 .Exited => |code| try w.print("exited with code {d}", .{code}),
1017 .Signal => |sig| try w.print("terminated with signal {d}", .{sig}),
1018 .Stopped => |sig| try w.print("stopped with signal {d}", .{sig}),
1019 .Unknown => |code| try w.print("terminated for unknown reason with code {d}", .{code}),
10271020 } else {
1028 try writer.writeAll("exited with any code");
1021 try w.writeAll("exited with any code");
10291022 }
10301023}
1031fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {
1024fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(?std.process.Child.Term, formatTerm) {
10321025 return .{ .data = term };
10331026}
10341027
......@@ -1262,12 +1255,12 @@ fn runCommand(
12621255 const sub_path = b.pathJoin(&output_components);
12631256 const sub_path_dirname = fs.path.dirname(sub_path).?;
12641257 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
1265 return step.fail("unable to make path '{}{s}': {s}", .{
1258 return step.fail("unable to make path '{f}{s}': {s}", .{
12661259 b.cache_root, sub_path_dirname, @errorName(err),
12671260 });
12681261 };
12691262 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = stream.bytes.? }) catch |err| {
1270 return step.fail("unable to write file '{}{s}': {s}", .{
1263 return step.fail("unable to write file '{f}{s}': {s}", .{
12711264 b.cache_root, sub_path, @errorName(err),
12721265 });
12731266 };
......@@ -1346,7 +1339,7 @@ fn runCommand(
13461339 },
13471340 .expect_term => |expected_term| {
13481341 if (!termMatches(expected_term, result.term)) {
1349 return step.fail("the following command {} (expected {}):\n{s}", .{
1342 return step.fail("the following command {f} (expected {f}):\n{s}", .{
13501343 fmtTerm(result.term),
13511344 fmtTerm(expected_term),
13521345 try Step.allocPrintCmd(arena, cwd, final_argv),
......@@ -1366,7 +1359,7 @@ fn runCommand(
13661359 };
13671360 const expected_term: std.process.Child.Term = .{ .Exited = 0 };
13681361 if (!termMatches(expected_term, result.term)) {
1369 return step.fail("{s}the following command {} (expected {}):\n{s}", .{
1362 return step.fail("{s}the following command {f} (expected {f}):\n{s}", .{
13701363 prefix,
13711364 fmtTerm(result.term),
13721365 fmtTerm(expected_term),
......@@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
17971790 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
17981791 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
17991792 } else {
1800 stdout_bytes = try stdout.reader().readAllAlloc(arena, run.max_stdio_size);
1793 stdout_bytes = try stdout.deprecatedReader().readAllAlloc(arena, run.max_stdio_size);
18011794 }
18021795 } else if (child.stderr) |stderr| {
1803 stderr_bytes = try stderr.reader().readAllAlloc(arena, run.max_stdio_size);
1796 stderr_bytes = try stderr.deprecatedReader().readAllAlloc(arena, run.max_stdio_size);
18041797 }
18051798
18061799 if (stderr_bytes) |bytes| if (bytes.len > 0) {
lib/std/Build/Step/UpdateSourceFiles.zig+3-3
......@@ -76,7 +76,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
7676 for (usf.output_source_files.items) |output_source_file| {
7777 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
7878 b.build_root.handle.makePath(dirname) catch |err| {
79 return step.fail("unable to make path '{}{s}': {s}", .{
79 return step.fail("unable to make path '{f}{s}': {s}", .{
8080 b.build_root, dirname, @errorName(err),
8181 });
8282 };
......@@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
8484 switch (output_source_file.contents) {
8585 .bytes => |bytes| {
8686 b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {
87 return step.fail("unable to write file '{}{s}': {s}", .{
87 return step.fail("unable to write file '{f}{s}': {s}", .{
8888 b.build_root, output_source_file.sub_path, @errorName(err),
8989 });
9090 };
......@@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
101101 output_source_file.sub_path,
102102 .{},
103103 ) catch |err| {
104 return step.fail("unable to update file from '{s}' to '{}{s}': {s}", .{
104 return step.fail("unable to update file from '{s}' to '{f}{s}': {s}", .{
105105 source_path, b.build_root, output_source_file.sub_path, @errorName(err),
106106 });
107107 };
lib/std/Build/Step/WriteFile.zig+7-7
......@@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
217217 const src_dir_path = dir.source.getPath3(b, step);
218218
219219 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
220 return step.fail("unable to open source directory '{}': {s}", .{
220 return step.fail("unable to open source directory '{f}': {s}", .{
221221 src_dir_path, @errorName(err),
222222 });
223223 };
......@@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
258258 write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });
259259
260260 var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| {
261 return step.fail("unable to make path '{}{s}': {s}", .{
261 return step.fail("unable to make path '{f}{s}': {s}", .{
262262 b.cache_root, cache_path, @errorName(err),
263263 });
264264 };
......@@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
269269 for (write_file.files.items) |file| {
270270 if (fs.path.dirname(file.sub_path)) |dirname| {
271271 cache_dir.makePath(dirname) catch |err| {
272 return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{
272 return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{
273273 b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),
274274 });
275275 };
......@@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
277277 switch (file.contents) {
278278 .bytes => |bytes| {
279279 cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| {
280 return step.fail("unable to write file '{}{s}{c}{s}': {s}", .{
280 return step.fail("unable to write file '{f}{s}{c}{s}': {s}", .{
281281 b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),
282282 });
283283 };
......@@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
291291 file.sub_path,
292292 .{},
293293 ) catch |err| {
294 return step.fail("unable to update file from '{s}' to '{}{s}{c}{s}': {s}", .{
294 return step.fail("unable to update file from '{s}' to '{f}{s}{c}{s}': {s}", .{
295295 source_path,
296296 b.cache_root,
297297 cache_path,
......@@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
315315
316316 if (dest_dirname.len != 0) {
317317 cache_dir.makePath(dest_dirname) catch |err| {
318 return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{
318 return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{
319319 b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
320320 });
321321 };
......@@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
338338 dest_path,
339339 .{},
340340 ) catch |err| {
341 return step.fail("unable to update file from '{}' to '{}{s}{c}{s}': {s}", .{
341 return step.fail("unable to update file from '{f}' to '{f}{s}{c}{s}': {s}", .{
342342 src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),
343343 });
344344 };
lib/std/Build/Watch.zig+3-3
......@@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {
211211 .ADD = true,
212212 .ONLYDIR = true,
213213 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| {
214 fatal("unable to watch {}: {s}", .{ path, @errorName(err) });
214 fatal("unable to watch {f}: {s}", .{ path, @errorName(err) });
215215 };
216216 }
217217 break :rs &dh_gop.value_ptr.reaction_set;
......@@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {
265265 .ONLYDIR = true,
266266 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {
267267 error.FileNotFound => {}, // Expected, harmless.
268 else => |e| std.log.warn("unable to unwatch '{}': {s}", .{ path, @errorName(e) }),
268 else => |e| std.log.warn("unable to unwatch '{f}': {s}", .{ path, @errorName(e) }),
269269 };
270270
271271 w.dir_table.swapRemoveAt(i);
......@@ -659,7 +659,7 @@ const Os = switch (builtin.os.tag) {
659659 path.root_dir.handle.fd
660660 else
661661 posix.openat(path.root_dir.handle.fd, path.sub_path, dir_open_flags, 0) catch |err| {
662 fatal("failed to open directory {}: {s}", .{ path, @errorName(err) });
662 fatal("failed to open directory {f}: {s}", .{ path, @errorName(err) });
663663 };
664664 // Empirically the dir has to stay open or else no events are triggered.
665665 errdefer if (!skip_open_dir) posix.close(dir_fd);
lib/std/Progress.zig+31
......@@ -9,6 +9,7 @@ const Progress = @This();
99const posix = std.posix;
1010const is_big_endian = builtin.cpu.arch.endian() == .big;
1111const is_windows = builtin.os.tag == .windows;
12const Writer = std.io.Writer;
1213
1314/// `null` if the current node (and its children) should
1415/// not print on update()
......@@ -606,6 +607,36 @@ pub fn unlockStdErr() void {
606607 stderr_mutex.unlock();
607608}
608609
610/// Protected by `stderr_mutex`.
611const stderr_writer: *Writer = &stderr_file_writer.interface;
612/// Protected by `stderr_mutex`.
613var stderr_file_writer: std.fs.File.Writer = .{
614 .interface = std.fs.File.Writer.initInterface(&.{}),
615 .file = if (is_windows) undefined else .stderr(),
616 .mode = .streaming,
617};
618
619/// Allows the caller to freely write to the returned `Writer`,
620/// initialized with `buffer`, until `unlockStderrWriter` is called.
621///
622/// During the lock, any `std.Progress` information is cleared from the terminal.
623///
624/// The lock is recursive; the same thread may hold the lock multiple times.
625pub fn lockStderrWriter(buffer: []u8) *Writer {
626 stderr_mutex.lock();
627 clearWrittenWithEscapeCodes() catch {};
628 if (is_windows) stderr_file_writer.file = .stderr();
629 stderr_writer.flush() catch {};
630 stderr_writer.buffer = buffer;
631 return stderr_writer;
632}
633
634pub fn unlockStderrWriter() void {
635 stderr_writer.flush() catch {};
636 stderr_writer.buffer = &.{};
637 stderr_mutex.unlock();
638}
639
609640fn ipcThreadRun(fd: posix.fd_t) anyerror!void {
610641 // Store this data in the thread so that it does not need to be part of the
611642 // linker data of the main executable.
lib/std/Random/benchmark.zig+1-1
......@@ -122,7 +122,7 @@ fn mode(comptime x: comptime_int) comptime_int {
122122}
123123
124124pub fn main() !void {
125 const stdout = std.fs.File.stdout().writer();
125 const stdout = std.fs.File.stdout().deprecatedWriter();
126126
127127 var buffer: [1024]u8 = undefined;
128128 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
lib/std/SemanticVersion.zig+7-13
......@@ -150,17 +150,11 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {
150150 };
151151}
152152
153pub fn format(
154 self: Version,
155 comptime fmt: []const u8,
156 options: std.fmt.FormatOptions,
157 out_stream: anytype,
158) !void {
159 _ = options;
153pub fn format(self: Version, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
160154 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
161 try std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
162 if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});
163 if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});
155 try w.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
156 if (self.pre) |pre| try w.print("-{s}", .{pre});
157 if (self.build) |build| try w.print("+{s}", .{build});
164158}
165159
166160const expect = std.testing.expect;
......@@ -202,7 +196,7 @@ test format {
202196 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",
203197 "5.4.0-1018-raspi",
204198 "5.7.123",
205 }) |valid| try std.testing.expectFmt(valid, "{}", .{try parse(valid)});
199 }) |valid| try std.testing.expectFmt(valid, "{f}", .{try parse(valid)});
206200
207201 // Invalid version strings should be rejected.
208202 for ([_][]const u8{
......@@ -269,12 +263,12 @@ test format {
269263 // Valid version string that may overflow.
270264 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";
271265 if (parse(big_valid)) |ver| {
272 try std.testing.expectFmt(big_valid, "{}", .{ver});
266 try std.testing.expectFmt(big_valid, "{f}", .{ver});
273267 } else |err| try expect(err == error.Overflow);
274268
275269 // Invalid version string that may overflow.
276270 const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";
277 if (parse(big_invalid)) |ver| std.debug.panic("expected error, found {}", .{ver}) else |_| {}
271 if (parse(big_invalid)) |ver| std.debug.panic("expected error, found {f}", .{ver}) else |_| {}
278272}
279273
280274test "precedence" {
lib/std/Target.zig+11-16
......@@ -301,29 +301,24 @@ pub const Os = struct {
301301
302302 /// This function is defined to serialize a Zig source code representation of this
303303 /// type, that, when parsed, will deserialize into the same data.
304 pub fn format(
305 ver: WindowsVersion,
306 comptime fmt_str: []const u8,
307 _: std.fmt.FormatOptions,
308 writer: anytype,
309 ) @TypeOf(writer).Error!void {
304 pub fn format(ver: WindowsVersion, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
310305 const maybe_name = std.enums.tagName(WindowsVersion, ver);
311 if (comptime std.mem.eql(u8, fmt_str, "s")) {
306 if (comptime std.mem.eql(u8, f, "s")) {
312307 if (maybe_name) |name|
313 try writer.print(".{s}", .{name})
308 try w.print(".{s}", .{name})
314309 else
315 try writer.print(".{d}", .{@intFromEnum(ver)});
316 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {
310 try w.print(".{d}", .{@intFromEnum(ver)});
311 } else if (comptime std.mem.eql(u8, f, "c")) {
317312 if (maybe_name) |name|
318 try writer.print(".{s}", .{name})
313 try w.print(".{s}", .{name})
319314 else
320 try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
321 } else if (fmt_str.len == 0) {
315 try w.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
316 } else if (f.len == 0) {
322317 if (maybe_name) |name|
323 try writer.print("WindowsVersion.{s}", .{name})
318 try w.print("WindowsVersion.{s}", .{name})
324319 else
325 try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
326 } else std.fmt.invalidFmtError(fmt_str, ver);
320 try w.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
321 } else std.fmt.invalidFmtError(f, ver);
327322 }
328323 };
329324
lib/std/Target/Query.zig+20-21
......@@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {
394394
395395/// Formats a version with the patch component omitted if it is zero,
396396/// unlike SemanticVersion.format which formats all its version components regardless.
397fn formatVersion(version: SemanticVersion, writer: anytype) !void {
397fn formatVersion(version: SemanticVersion, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) !void {
398398 if (version.patch == 0) {
399 try writer.print("{d}.{d}", .{ version.major, version.minor });
399 try list.print(gpa, "{d}.{d}", .{ version.major, version.minor });
400400 } else {
401 try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
401 try list.print(gpa, "{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
402402 }
403403}
404404
405pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
406 if (self.isNativeTriple())
407 return allocator.dupe(u8, "native");
405pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
406 if (self.isNativeTriple()) return gpa.dupe(u8, "native");
408407
409408 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
410409 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
411410
412 var result = std.ArrayList(u8).init(allocator);
413 defer result.deinit();
411 var result: std.ArrayListUnmanaged(u8) = .empty;
412 defer result.deinit(gpa);
414413
415 try result.writer().print("{s}-{s}", .{ arch_name, os_name });
414 try result.print(gpa, "{s}-{s}", .{ arch_name, os_name });
416415
417416 // The zig target syntax does not allow specifying a max os version with no min, so
418417 // if either are present, we need the min.
......@@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
420419 switch (min) {
421420 .none => {},
422421 .semver => |v| {
423 try result.writer().writeAll(".");
424 try formatVersion(v, result.writer());
422 try result.appendSlice(gpa, ".");
423 try formatVersion(v, gpa, &result);
425424 },
426425 .windows => |v| {
427 try result.writer().print("{s}", .{v});
426 try result.print(gpa, "{d}", .{v});
428427 },
429428 }
430429 }
......@@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
432431 switch (max) {
433432 .none => {},
434433 .semver => |v| {
435 try result.writer().writeAll("...");
436 try formatVersion(v, result.writer());
434 try result.appendSlice(gpa, "...");
435 try formatVersion(v, gpa, &result);
437436 },
438437 .windows => |v| {
439438 // This is counting on a custom format() function defined on `WindowsVersion`
440439 // to add a prefix '.' and make there be a total of three dots.
441 try result.writer().print("..{s}", .{v});
440 try result.print(gpa, "..{d}", .{v});
442441 },
443442 }
444443 }
445444
446445 if (self.glibc_version) |v| {
447446 const name = if (self.abi) |abi| @tagName(abi) else "gnu";
448 try result.ensureUnusedCapacity(name.len + 2);
447 try result.ensureUnusedCapacity(gpa, name.len + 2);
449448 result.appendAssumeCapacity('-');
450449 result.appendSliceAssumeCapacity(name);
451450 result.appendAssumeCapacity('.');
452 try formatVersion(v, result.writer());
451 try formatVersion(v, gpa, &result);
453452 } else if (self.android_api_level) |lvl| {
454453 const name = if (self.abi) |abi| @tagName(abi) else "android";
455 try result.ensureUnusedCapacity(name.len + 2);
454 try result.ensureUnusedCapacity(gpa, name.len + 2);
456455 result.appendAssumeCapacity('-');
457456 result.appendSliceAssumeCapacity(name);
458457 result.appendAssumeCapacity('.');
459 try result.writer().print("{d}", .{lvl});
458 try result.print(gpa, "{d}", .{lvl});
460459 } else if (self.abi) |abi| {
461460 const name = @tagName(abi);
462 try result.ensureUnusedCapacity(name.len + 1);
461 try result.ensureUnusedCapacity(gpa, name.len + 1);
463462 result.appendAssumeCapacity('-');
464463 result.appendSliceAssumeCapacity(name);
465464 }
466465
467 return result.toOwnedSlice();
466 return result.toOwnedSlice(gpa);
468467}
469468
470469/// Renders the query into a textual representation that can be parsed via the
lib/std/Thread.zig+3-3
......@@ -167,7 +167,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
167167 const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
168168 defer file.close();
169169
170 try file.writer().writeAll(name);
170 try file.deprecatedWriter().writeAll(name);
171171 return;
172172 },
173173 .windows => {
......@@ -281,7 +281,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
281281 const file = try std.fs.cwd().openFile(path, .{});
282282 defer file.close();
283283
284 const data_len = try file.reader().readAll(buffer_ptr[0 .. max_name_len + 1]);
284 const data_len = try file.deprecatedReader().readAll(buffer_ptr[0 .. max_name_len + 1]);
285285
286286 return if (data_len >= 1) buffer[0 .. data_len - 1] else null;
287287 },
......@@ -1163,7 +1163,7 @@ const LinuxThreadImpl = struct {
11631163
11641164 fn getCurrentId() Id {
11651165 return tls_thread_id orelse {
1166 const tid = @as(u32, @bitCast(linux.gettid()));
1166 const tid: u32 = @bitCast(linux.gettid());
11671167 tls_thread_id = tid;
11681168 return tid;
11691169 };
lib/std/Uri.zig+40-58
......@@ -34,27 +34,22 @@ pub const Component = union(enum) {
3434 return switch (component) {
3535 .raw => |raw| raw,
3636 .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|
37 try std.fmt.allocPrint(arena, "{raw}", .{component})
37 try std.fmt.allocPrint(arena, "{fraw}", .{component})
3838 else
3939 percent_encoded,
4040 };
4141 }
4242
43 pub fn format(
44 component: Component,
45 comptime fmt_str: []const u8,
46 _: std.fmt.FormatOptions,
47 writer: anytype,
48 ) @TypeOf(writer).Error!void {
43 pub fn format(component: Component, w: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
4944 if (fmt_str.len == 0) {
50 try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{
45 try w.print("std.Uri.Component{{ .{s} = \"{f}\" }}", .{
5146 @tagName(component),
52 std.zig.fmtEscapes(switch (component) {
47 std.zig.fmtString(switch (component) {
5348 .raw, .percent_encoded => |string| string,
5449 }),
5550 });
5651 } else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) {
57 .raw => |raw| try writer.writeAll(raw),
52 .raw => |raw| try w.writeAll(raw),
5853 .percent_encoded => |percent_encoded| {
5954 var start: usize = 0;
6055 var index: usize = 0;
......@@ -63,51 +58,47 @@ pub const Component = union(enum) {
6358 if (percent_encoded.len - index < 2) continue;
6459 const percent_encoded_char =
6560 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
66 try writer.print("{s}{c}", .{
61 try w.print("{s}{c}", .{
6762 percent_encoded[start..percent],
6863 percent_encoded_char,
6964 });
7065 start = percent + 3;
7166 index = percent + 3;
7267 }
73 try writer.writeAll(percent_encoded[start..]);
68 try w.writeAll(percent_encoded[start..]);
7469 },
7570 } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {
76 .raw => |raw| try percentEncode(writer, raw, isUnreserved),
77 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
71 .raw => |raw| try percentEncode(w, raw, isUnreserved),
72 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
7873 } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {
79 .raw => |raw| try percentEncode(writer, raw, isUserChar),
80 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
74 .raw => |raw| try percentEncode(w, raw, isUserChar),
75 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
8176 } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {
82 .raw => |raw| try percentEncode(writer, raw, isPasswordChar),
83 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
77 .raw => |raw| try percentEncode(w, raw, isPasswordChar),
78 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
8479 } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {
85 .raw => |raw| try percentEncode(writer, raw, isHostChar),
86 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
80 .raw => |raw| try percentEncode(w, raw, isHostChar),
81 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
8782 } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {
88 .raw => |raw| try percentEncode(writer, raw, isPathChar),
89 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
83 .raw => |raw| try percentEncode(w, raw, isPathChar),
84 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
9085 } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {
91 .raw => |raw| try percentEncode(writer, raw, isQueryChar),
92 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
86 .raw => |raw| try percentEncode(w, raw, isQueryChar),
87 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
9388 } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {
94 .raw => |raw| try percentEncode(writer, raw, isFragmentChar),
95 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
89 .raw => |raw| try percentEncode(w, raw, isFragmentChar),
90 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
9691 } else @compileError("invalid format string '" ++ fmt_str ++ "'");
9792 }
9893
99 pub fn percentEncode(
100 writer: anytype,
101 raw: []const u8,
102 comptime isValidChar: fn (u8) bool,
103 ) @TypeOf(writer).Error!void {
94 pub fn percentEncode(w: *std.io.Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) std.io.Writer.Error!void {
10495 var start: usize = 0;
10596 for (raw, 0..) |char, index| {
10697 if (isValidChar(char)) continue;
107 try writer.print("{s}%{X:0>2}", .{ raw[start..index], char });
98 try w.print("{s}%{X:0>2}", .{ raw[start..index], char });
10899 start = index + 1;
109100 }
110 try writer.writeAll(raw[start..]);
101 try w.writeAll(raw[start..]);
111102 }
112103};
113104
......@@ -247,11 +238,7 @@ pub const WriteToStreamOptions = struct {
247238 port: bool = true,
248239};
249240
250pub fn writeToStream(
251 uri: Uri,
252 options: WriteToStreamOptions,
253 writer: anytype,
254) @TypeOf(writer).Error!void {
241pub fn writeToStream(uri: Uri, writer: *std.io.Writer, options: WriteToStreamOptions) std.io.Writer.Error!void {
255242 if (options.scheme) {
256243 try writer.print("{s}:", .{uri.scheme});
257244 if (options.authority and uri.host != null) {
......@@ -261,39 +248,34 @@ pub fn writeToStream(
261248 if (options.authority) {
262249 if (options.authentication and uri.host != null) {
263250 if (uri.user) |user| {
264 try writer.print("{user}", .{user});
251 try writer.print("{fuser}", .{user});
265252 if (uri.password) |password| {
266 try writer.print(":{password}", .{password});
253 try writer.print(":{fpassword}", .{password});
267254 }
268255 try writer.writeByte('@');
269256 }
270257 }
271258 if (uri.host) |host| {
272 try writer.print("{host}", .{host});
259 try writer.print("{fhost}", .{host});
273260 if (options.port) {
274261 if (uri.port) |port| try writer.print(":{d}", .{port});
275262 }
276263 }
277264 }
278265 if (options.path) {
279 try writer.print("{path}", .{
266 try writer.print("{fpath}", .{
280267 if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,
281268 });
282269 if (options.query) {
283 if (uri.query) |query| try writer.print("?{query}", .{query});
270 if (uri.query) |query| try writer.print("?{fquery}", .{query});
284271 }
285272 if (options.fragment) {
286 if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment});
273 if (uri.fragment) |fragment| try writer.print("#{ffragment}", .{fragment});
287274 }
288275 }
289276}
290277
291pub fn format(
292 uri: Uri,
293 comptime fmt_str: []const u8,
294 _: std.fmt.FormatOptions,
295 writer: anytype,
296) @TypeOf(writer).Error!void {
278pub fn format(uri: Uri, writer: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
297279 const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;
298280 const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;
299281 const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;
......@@ -301,14 +283,14 @@ pub fn format(
301283 const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;
302284 const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0;
303285
304 return writeToStream(uri, .{
286 return writeToStream(uri, writer, .{
305287 .scheme = scheme,
306288 .authentication = authentication,
307289 .authority = authority,
308290 .path = path,
309291 .query = query,
310292 .fragment = fragment,
311 }, writer);
293 });
312294}
313295
314296/// Parses the URI or returns an error.
......@@ -447,7 +429,7 @@ test remove_dot_segments {
447429fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
448430 var aux = std.io.fixedBufferStream(aux_buf.*);
449431 if (!base.isEmpty()) {
450 try aux.writer().print("{path}", .{base});
432 try aux.writer().print("{fpath}", .{base});
451433 aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse
452434 return remove_dot_segments(new);
453435 }
......@@ -812,7 +794,7 @@ test "Special test" {
812794test "URI percent encoding" {
813795 try std.testing.expectFmt(
814796 "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad",
815 "{%}",
797 "{f%}",
816798 .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},
817799 );
818800}
......@@ -822,7 +804,7 @@ test "URI percent decoding" {
822804 const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
823805 var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*;
824806
825 try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});
807 try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }});
826808
827809 var output: [expected.len]u8 = undefined;
828810 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
......@@ -834,7 +816,7 @@ test "URI percent decoding" {
834816 const expected = "/abc%";
835817 var input = expected.*;
836818
837 try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});
819 try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }});
838820
839821 var output: [expected.len]u8 = undefined;
840822 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
......@@ -848,7 +830,7 @@ test "URI query encoding" {
848830 const parsed = try Uri.parse(address);
849831
850832 // format the URI to percent encode it
851 try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{/?}", .{parsed});
833 try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{f/?}", .{parsed});
852834}
853835
854836test "format" {
......@@ -862,7 +844,7 @@ test "format" {
862844 .query = null,
863845 .fragment = null,
864846 };
865 try std.testing.expectFmt("file:/foo/bar/baz", "{;/?#}", .{uri});
847 try std.testing.expectFmt("file:/foo/bar/baz", "{f;/?#}", .{uri});
866848}
867849
868850test "URI malformed input" {
lib/std/ascii.zig+41
......@@ -435,3 +435,44 @@ pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {
435435pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {
436436 return orderIgnoreCase(lhs, rhs) == .lt;
437437}
438
439pub const HexEscape = struct {
440 bytes: []const u8,
441 charset: *const [16]u8,
442
443 pub const upper_charset = "0123456789ABCDEF";
444 pub const lower_charset = "0123456789abcdef";
445
446 pub fn format(se: HexEscape, w: *std.io.Writer) std.io.Writer.Error!void {
447 const charset = se.charset;
448
449 var buf: [4]u8 = undefined;
450 buf[0] = '\\';
451 buf[1] = 'x';
452
453 for (se.bytes) |c| {
454 if (std.ascii.isPrint(c)) {
455 try w.writeByte(c);
456 } else {
457 buf[2] = charset[c >> 4];
458 buf[3] = charset[c & 15];
459 try w.writeAll(&buf);
460 }
461 }
462 }
463};
464
465/// Replaces non-ASCII bytes with hex escapes.
466pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Formatter(HexEscape, HexEscape.format) {
467 return .{ .data = .{ .bytes = bytes, .charset = switch (case) {
468 .lower => HexEscape.lower_charset,
469 .upper => HexEscape.upper_charset,
470 } } };
471}
472
473test hexEscape {
474 try std.testing.expectFmt("abc 123", "{f}", .{hexEscape("abc 123", .lower)});
475 try std.testing.expectFmt("ab\\xffc", "{f}", .{hexEscape("ab\xffc", .lower)});
476 try std.testing.expectFmt("abc 123", "{f}", .{hexEscape("abc 123", .upper)});
477 try std.testing.expectFmt("ab\\xFFc", "{f}", .{hexEscape("ab\xffc", .upper)});
478}
lib/std/builtin.zig+2-8
......@@ -34,20 +34,14 @@ pub const StackTrace = struct {
3434 index: usize,
3535 instruction_addresses: []usize,
3636
37 pub fn format(
38 self: StackTrace,
39 comptime fmt: []const u8,
40 options: std.fmt.FormatOptions,
41 writer: anytype,
42 ) !void {
43 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
37 pub fn format(self: StackTrace, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
38 if (fmt.len != 0) unreachable;
4439
4540 // TODO: re-evaluate whether to use format() methods at all.
4641 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly
4742 // where it tries to call detectTTYConfig here.
4843 if (builtin.os.tag == .freestanding) return;
4944
50 _ = options;
5145 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
5246 return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
5347 };
lib/std/crypto/25519/curve25519.zig+2-2
......@@ -124,9 +124,9 @@ test "curve25519" {
124124 const p = try Curve25519.basePoint.clampedMul(s);
125125 try p.rejectIdentity();
126126 var buf: [128]u8 = undefined;
127 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&p.toBytes())}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");
127 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");
128128 const q = try p.clampedMul(s);
129 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&q.toBytes())}), "3614E119FFE55EC55B87D6B19971A9F4CBC78EFE80BEC55B96392BABCC712537");
129 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&q.toBytes()}), "3614E119FFE55EC55B87D6B19971A9F4CBC78EFE80BEC55B96392BABCC712537");
130130
131131 try Curve25519.rejectNonCanonical(s);
132132 s[31] |= 0x80;
lib/std/crypto/25519/ed25519.zig+3-3
......@@ -509,8 +509,8 @@ test "key pair creation" {
509509 _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
510510 const key_pair = try Ed25519.KeyPair.generateDeterministic(seed);
511511 var buf: [256]u8 = undefined;
512 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&key_pair.secret_key.toBytes())}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
513 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&key_pair.public_key.toBytes())}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
512 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.secret_key.toBytes()}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
513 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.public_key.toBytes()}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
514514}
515515
516516test "signature" {
......@@ -520,7 +520,7 @@ test "signature" {
520520
521521 const sig = try key_pair.sign("test", null);
522522 var buf: [128]u8 = undefined;
523 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&sig.toBytes())}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808");
523 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&sig.toBytes()}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808");
524524 try sig.verify("test", key_pair.public_key);
525525 try std.testing.expectError(error.SignatureVerificationFailed, sig.verify("TEST", key_pair.public_key));
526526}
lib/std/crypto/25519/edwards25519.zig+1-1
......@@ -546,7 +546,7 @@ test "packing/unpacking" {
546546 var b = Edwards25519.basePoint;
547547 const pk = try b.mul(s);
548548 var buf: [128]u8 = undefined;
549 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&pk.toBytes())}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");
549 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");
550550
551551 const small_order_ss: [7][32]u8 = .{
552552 .{
lib/std/crypto/25519/ristretto255.zig+4-4
......@@ -175,21 +175,21 @@ pub const Ristretto255 = struct {
175175test "ristretto255" {
176176 const p = Ristretto255.basePoint;
177177 var buf: [256]u8 = undefined;
178 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&p.toBytes())}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
178 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
179179
180180 var r: [Ristretto255.encoded_length]u8 = undefined;
181181 _ = try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");
182182 var q = try Ristretto255.fromBytes(r);
183183 q = q.dbl().add(p);
184 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&q.toBytes())}), "E882B131016B52C1D3337080187CF768423EFCCBB517BB495AB812C4160FF44E");
184 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&q.toBytes()}), "E882B131016B52C1D3337080187CF768423EFCCBB517BB495AB812C4160FF44E");
185185
186186 const s = [_]u8{15} ++ [_]u8{0} ** 31;
187187 const w = try p.mul(s);
188 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&w.toBytes())}), "E0C418F7C8D9C4CDD7395B93EA124F3AD99021BB681DFC3302A9D99A2E53E64E");
188 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&w.toBytes()}), "E0C418F7C8D9C4CDD7395B93EA124F3AD99021BB681DFC3302A9D99A2E53E64E");
189189
190190 try std.testing.expect(p.dbl().dbl().dbl().dbl().equivalent(w.add(p)));
191191
192192 const h = [_]u8{69} ** 32 ++ [_]u8{42} ** 32;
193193 const ph = Ristretto255.fromUniform(h);
194 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&ph.toBytes())}), "DCCA54E037A4311EFBEEF413ACD21D35276518970B7A61DC88F8587B493D5E19");
194 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&ph.toBytes()}), "DCCA54E037A4311EFBEEF413ACD21D35276518970B7A61DC88F8587B493D5E19");
195195}
lib/std/crypto/25519/scalar.zig+3-3
......@@ -850,10 +850,10 @@ test "scalar25519" {
850850 var y = x.toBytes();
851851 try rejectNonCanonical(y);
852852 var buf: [128]u8 = undefined;
853 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&y)}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F");
853 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&y}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F");
854854
855855 const reduced = reduce(field_order_s);
856 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&reduced)}), "0000000000000000000000000000000000000000000000000000000000000000");
856 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&reduced}), "0000000000000000000000000000000000000000000000000000000000000000");
857857}
858858
859859test "non-canonical scalar25519" {
......@@ -867,7 +867,7 @@ test "mulAdd overflow check" {
867867 const c: [32]u8 = [_]u8{0xff} ** 32;
868868 const x = mulAdd(a, b, c);
869869 var buf: [128]u8 = undefined;
870 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&x)}), "D14DF91389432C25AD60FF9791B9FD1D67BEF517D273ECCE3D9A307C1B419903");
870 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&x}), "D14DF91389432C25AD60FF9791B9FD1D67BEF517D273ECCE3D9A307C1B419903");
871871}
872872
873873test "scalar field inversion" {
lib/std/crypto/benchmark.zig+1-1
......@@ -458,7 +458,7 @@ fn mode(comptime x: comptime_int) comptime_int {
458458}
459459
460460pub fn main() !void {
461 const stdout = std.fs.File.stdout().writer();
461 const stdout = std.fs.File.stdout().deprecatedWriter();
462462
463463 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
464464 defer arena.deinit();
lib/std/crypto/chacha20.zig+2-2
......@@ -1145,7 +1145,7 @@ test "xchacha20" {
11451145 var c: [m.len]u8 = undefined;
11461146 XChaCha20IETF.xor(c[0..], m[0..], 0, key, nonce);
11471147 var buf: [2 * c.len]u8 = undefined;
1148 try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&c)}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");
1148 try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&c}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");
11491149 }
11501150 {
11511151 const ad = "Additional data";
......@@ -1154,7 +1154,7 @@ test "xchacha20" {
11541154 var out: [m.len]u8 = undefined;
11551155 try XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key);
11561156 var buf: [2 * c.len]u8 = undefined;
1157 try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&c)}), "994D2DD32333F48E53650C02C7A2ABB8E018B0836D7175AEC779F52E961780768F815C58F1AA52D211498DB89B9216763F569C9433A6BBFCEFB4D4A49387A4C5207FBB3B5A92B5941294DF30588C6740D39DC16FA1F0E634F7246CF7CDCB978E44347D89381B7A74EB7084F754B90BDE9AAF5A94B8F2A85EFD0B50692AE2D425E234");
1157 try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&c}), "994D2DD32333F48E53650C02C7A2ABB8E018B0836D7175AEC779F52E961780768F815C58F1AA52D211498DB89B9216763F569C9433A6BBFCEFB4D4A49387A4C5207FBB3B5A92B5941294DF30588C6740D39DC16FA1F0E634F7246CF7CDCB978E44347D89381B7A74EB7084F754B90BDE9AAF5A94B8F2A85EFD0B50692AE2D425E234");
11581158 try testing.expectEqualSlices(u8, out[0..], m);
11591159 c[0] +%= 1;
11601160 try testing.expectError(error.AuthenticationFailed, XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key));
lib/std/crypto/ml_kem.zig+8-8
......@@ -1737,11 +1737,11 @@ test "NIST KAT test" {
17371737 var f = sha2.Sha256.init(.{});
17381738 const fw = f.writer();
17391739 var g = NistDRBG.init(seed);
1740 try std.fmt.format(fw, "# {s}\n\n", .{mode.name});
1740 try std.fmt.deprecatedFormat(fw, "# {s}\n\n", .{mode.name});
17411741 for (0..100) |i| {
17421742 g.fill(&seed);
1743 try std.fmt.format(fw, "count = {}\n", .{i});
1744 try std.fmt.format(fw, "seed = {s}\n", .{std.fmt.fmtSliceHexUpper(&seed)});
1743 try std.fmt.deprecatedFormat(fw, "count = {}\n", .{i});
1744 try std.fmt.deprecatedFormat(fw, "seed = {X}\n", .{&seed});
17451745 var g2 = NistDRBG.init(seed);
17461746
17471747 // This is not equivalent to g2.fill(kseed[:]). As the reference
......@@ -1756,16 +1756,16 @@ test "NIST KAT test" {
17561756 const e = kp.public_key.encaps(eseed);
17571757 const ss2 = try kp.secret_key.decaps(&e.ciphertext);
17581758 try testing.expectEqual(ss2, e.shared_secret);
1759 try std.fmt.format(fw, "pk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.public_key.toBytes())});
1760 try std.fmt.format(fw, "sk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.secret_key.toBytes())});
1761 try std.fmt.format(fw, "ct = {s}\n", .{std.fmt.fmtSliceHexUpper(&e.ciphertext)});
1762 try std.fmt.format(fw, "ss = {s}\n\n", .{std.fmt.fmtSliceHexUpper(&e.shared_secret)});
1759 try std.fmt.deprecatedFormat(fw, "pk = {X}\n", .{&kp.public_key.toBytes()});
1760 try std.fmt.deprecatedFormat(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()});
1761 try std.fmt.deprecatedFormat(fw, "ct = {X}\n", .{&e.ciphertext});
1762 try std.fmt.deprecatedFormat(fw, "ss = {X}\n\n", .{&e.shared_secret});
17631763 }
17641764
17651765 var out: [32]u8 = undefined;
17661766 f.final(&out);
17671767 var outHex: [64]u8 = undefined;
1768 _ = try std.fmt.bufPrint(&outHex, "{s}", .{std.fmt.fmtSliceHexLower(&out)});
1768 _ = try std.fmt.bufPrint(&outHex, "{x}", .{&out});
17691769 try testing.expectEqual(outHex, modeHash[1].*);
17701770 }
17711771}
lib/std/crypto/tls/Client.zig+4-4
......@@ -1512,11 +1512,11 @@ fn logSecrets(key_log_file: std.fs.File, context: anytype, secrets: anytype) voi
15121512 const locked = if (key_log_file.lock(.exclusive)) |_| true else |_| false;
15131513 defer if (locked) key_log_file.unlock();
15141514 key_log_file.seekFromEnd(0) catch {};
1515 inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.writer().print("{s}" ++
1516 (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {} {}\n", .{field.name} ++
1515 inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.deprecatedWriter().print("{s}" ++
1516 (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++
15171517 (if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{
1518 std.fmt.fmtSliceHexLower(context.client_random),
1519 std.fmt.fmtSliceHexLower(@field(secrets, field.name)),
1518 context.client_random,
1519 @field(secrets, field.name),
15201520 }) catch {};
15211521}
15221522
lib/std/debug.zig+182-168
......@@ -12,6 +12,7 @@ const windows = std.os.windows;
1212const native_arch = builtin.cpu.arch;
1313const native_os = builtin.os.tag;
1414const native_endian = native_arch.endian();
15const Writer = std.io.Writer;
1516
1617pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
1718pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
......@@ -204,13 +205,26 @@ pub fn unlockStdErr() void {
204205 std.Progress.unlockStdErr();
205206}
206207
208/// Allows the caller to freely write to stderr until `unlockStdErr` is called.
209///
210/// During the lock, any `std.Progress` information is cleared from the terminal.
211///
212/// Returns a `Writer` with empty buffer, meaning that it is
213/// in fact unbuffered and does not need to be flushed.
214pub fn lockStderrWriter(buffer: []u8) *Writer {
215 return std.Progress.lockStderrWriter(buffer);
216}
217
218pub fn unlockStderrWriter() void {
219 std.Progress.unlockStderrWriter();
220}
221
207222/// Print to stderr, unbuffered, and silently returning on failure. Intended
208/// for use in "printf debugging." Use `std.log` functions for proper logging.
223/// for use in "printf debugging". Use `std.log` functions for proper logging.
209224pub fn print(comptime fmt: []const u8, args: anytype) void {
210 lockStdErr();
211 defer unlockStdErr();
212 const stderr = fs.File.stderr().writer();
213 nosuspend stderr.print(fmt, args) catch return;
225 const bw = lockStderrWriter(&.{});
226 defer unlockStderrWriter();
227 nosuspend bw.print(fmt, args) catch return;
214228}
215229
216230pub fn getStderrMutex() *std.Thread.Mutex {
......@@ -232,50 +246,44 @@ pub fn getSelfDebugInfo() !*SelfInfo {
232246/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
233247/// Obtains the stderr mutex while dumping.
234248pub fn dumpHex(bytes: []const u8) void {
235 lockStdErr();
236 defer unlockStdErr();
237 dumpHexFallible(bytes) catch {};
238}
239
240/// Prints a hexadecimal view of the bytes, unbuffered, returning any error that occurs.
241pub fn dumpHexFallible(bytes: []const u8) !void {
242 const stderr: fs.File = .stderr();
243 const ttyconf = std.io.tty.detectConfig(stderr);
244 const writer = stderr.writer();
245 try dumpHexInternal(bytes, ttyconf, writer);
249 const bw = lockStderrWriter(&.{});
250 defer unlockStderrWriter();
251 const ttyconf = std.io.tty.detectConfig(.stderr());
252 dumpHexFallible(bw, ttyconf, bytes) catch {};
246253}
247254
248fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytype) !void {
255/// Prints a hexadecimal view of the bytes, returning any error that occurs.
256pub fn dumpHexFallible(bw: *Writer, ttyconf: std.io.tty.Config, bytes: []const u8) !void {
249257 var chunks = mem.window(u8, bytes, 16, 16);
250258 while (chunks.next()) |window| {
251259 // 1. Print the address.
252260 const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10;
253 try ttyconf.setColor(writer, .dim);
261 try ttyconf.setColor(bw, .dim);
254262 // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.
255263 // Also, make sure all lines are aligned by padding the address.
256 try writer.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
257 try ttyconf.setColor(writer, .reset);
264 try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
265 try ttyconf.setColor(bw, .reset);
258266
259267 // 2. Print the bytes.
260268 for (window, 0..) |byte, index| {
261 try writer.print("{X:0>2} ", .{byte});
262 if (index == 7) try writer.writeByte(' ');
269 try bw.print("{X:0>2} ", .{byte});
270 if (index == 7) try bw.writeByte(' ');
263271 }
264 try writer.writeByte(' ');
272 try bw.writeByte(' ');
265273 if (window.len < 16) {
266274 var missing_columns = (16 - window.len) * 3;
267275 if (window.len < 8) missing_columns += 1;
268 try writer.writeByteNTimes(' ', missing_columns);
276 try bw.splatByteAll(' ', missing_columns);
269277 }
270278
271279 // 3. Print the characters.
272280 for (window) |byte| {
273281 if (std.ascii.isPrint(byte)) {
274 try writer.writeByte(byte);
282 try bw.writeByte(byte);
275283 } else {
276284 // Related: https://github.com/ziglang/zig/issues/7600
277285 if (ttyconf == .windows_api) {
278 try writer.writeByte('.');
286 try bw.writeByte('.');
279287 continue;
280288 }
281289
......@@ -283,22 +291,23 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp
283291 // We don't want to do this for all control codes because most control codes apart from
284292 // the ones that Zig has escape sequences for are likely not very useful to print as symbols.
285293 switch (byte) {
286 '\n' => try writer.writeAll("␊"),
287 '\r' => try writer.writeAll("␍"),
288 '\t' => try writer.writeAll("␉"),
289 else => try writer.writeByte('.'),
294 '\n' => try bw.writeAll("␊"),
295 '\r' => try bw.writeAll("␍"),
296 '\t' => try bw.writeAll("␉"),
297 else => try bw.writeByte('.'),
290298 }
291299 }
292300 }
293 try writer.writeByte('\n');
301 try bw.writeByte('\n');
294302 }
295303}
296304
297test dumpHexInternal {
305test dumpHexFallible {
298306 const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 };
299 var output = std.ArrayList(u8).init(std.testing.allocator);
300 defer output.deinit();
301 try dumpHexInternal(bytes, .no_color, output.writer());
307 var aw: std.io.Writer.Allocating = .init(std.testing.allocator);
308 defer aw.deinit();
309
310 try dumpHexFallible(&aw.interface, .no_color, bytes);
302311 const expected = try std.fmt.allocPrint(std.testing.allocator,
303312 \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........
304313 \\{x:0>[2]} 01 12 13 ...
......@@ -309,34 +318,36 @@ test dumpHexInternal {
309318 @sizeOf(usize) * 2,
310319 });
311320 defer std.testing.allocator.free(expected);
312 try std.testing.expectEqualStrings(expected, output.items);
321 try std.testing.expectEqualStrings(expected, aw.getWritten());
313322}
314323
315324/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
316/// TODO multithreaded awareness
317325pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
318 nosuspend {
319 if (builtin.target.cpu.arch.isWasm()) {
320 if (native_os == .wasi) {
321 const stderr = fs.File.stderr().writer();
322 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
323 }
324 return;
325 }
326 const stderr = fs.File.stderr().writer();
327 if (builtin.strip_debug_info) {
328 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
329 return;
326 const stderr = lockStderrWriter(&.{});
327 defer unlockStderrWriter();
328 nosuspend dumpCurrentStackTraceToWriter(start_addr, stderr) catch return;
329}
330
331/// Prints the current stack trace to the provided writer.
332pub fn dumpCurrentStackTraceToWriter(start_addr: ?usize, writer: *Writer) !void {
333 if (builtin.target.cpu.arch.isWasm()) {
334 if (native_os == .wasi) {
335 try writer.writeAll("Unable to dump stack trace: not implemented for Wasm\n");
330336 }
331 const debug_info = getSelfDebugInfo() catch |err| {
332 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
333 return;
334 };
335 writeCurrentStackTrace(stderr, debug_info, io.tty.detectConfig(fs.File.stderr()), start_addr) catch |err| {
336 stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
337 return;
338 };
337 return;
339338 }
339 if (builtin.strip_debug_info) {
340 try writer.writeAll("Unable to dump stack trace: debug info stripped\n");
341 return;
342 }
343 const debug_info = getSelfDebugInfo() catch |err| {
344 try writer.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
345 return;
346 };
347 writeCurrentStackTrace(writer, debug_info, io.tty.detectConfig(.stderr()), start_addr) catch |err| {
348 try writer.print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
349 return;
350 };
340351}
341352
342353pub const have_ucontext = posix.ucontext_t != void;
......@@ -402,16 +413,14 @@ pub inline fn getContext(context: *ThreadContext) bool {
402413/// Tries to print the stack trace starting from the supplied base pointer to stderr,
403414/// unbuffered, and ignores any error returned.
404415/// TODO multithreaded awareness
405pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
416pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void {
406417 nosuspend {
407418 if (builtin.target.cpu.arch.isWasm()) {
408419 if (native_os == .wasi) {
409 const stderr = fs.File.stderr().writer();
410420 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
411421 }
412422 return;
413423 }
414 const stderr = fs.File.stderr().writer();
415424 if (builtin.strip_debug_info) {
416425 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
417426 return;
......@@ -420,7 +429,7 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
420429 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
421430 return;
422431 };
423 const tty_config = io.tty.detectConfig(fs.File.stderr());
432 const tty_config = io.tty.detectConfig(.stderr());
424433 if (native_os == .windows) {
425434 // On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context
426435 // provided by the exception handler. On x86, RtlVirtualUnwind doesn't exist. Instead, a new backtrace
......@@ -510,21 +519,23 @@ pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
510519 nosuspend {
511520 if (builtin.target.cpu.arch.isWasm()) {
512521 if (native_os == .wasi) {
513 const stderr = fs.File.stderr().writer();
514 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
522 const stderr = lockStderrWriter(&.{});
523 defer unlockStderrWriter();
524 stderr.writeAll("Unable to dump stack trace: not implemented for Wasm\n") catch return;
515525 }
516526 return;
517527 }
518 const stderr = fs.File.stderr().writer();
528 const stderr = lockStderrWriter(&.{});
529 defer unlockStderrWriter();
519530 if (builtin.strip_debug_info) {
520 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
531 stderr.writeAll("Unable to dump stack trace: debug info stripped\n") catch return;
521532 return;
522533 }
523534 const debug_info = getSelfDebugInfo() catch |err| {
524535 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
525536 return;
526537 };
527 writeStackTrace(stack_trace, stderr, debug_info, io.tty.detectConfig(fs.File.stderr())) catch |err| {
538 writeStackTrace(stack_trace, stderr, debug_info, io.tty.detectConfig(.stderr())) catch |err| {
528539 stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
529540 return;
530541 };
......@@ -573,14 +584,13 @@ pub fn panicExtra(
573584 const size = 0x1000;
574585 const trunc_msg = "(msg truncated)";
575586 var buf: [size + trunc_msg.len]u8 = undefined;
587 var bw: Writer = .fixed(buf[0..size]);
576588 // a minor annoyance with this is that it will result in the NoSpaceLeft
577589 // error being part of the @panic stack trace (but that error should
578590 // only happen rarely)
579 const msg = std.fmt.bufPrint(buf[0..size], format, args) catch |err| switch (err) {
580 error.NoSpaceLeft => blk: {
581 @memcpy(buf[size..], trunc_msg);
582 break :blk &buf;
583 },
591 const msg = if (bw.print(format, args)) |_| bw.buffered() else |_| blk: {
592 @memcpy(buf[size..], trunc_msg);
593 break :blk &buf;
584594 };
585595 std.builtin.panic.call(msg, ret_addr);
586596}
......@@ -675,10 +685,9 @@ pub fn defaultPanic(
675685 _ = panicking.fetchAdd(1, .seq_cst);
676686
677687 {
678 lockStdErr();
679 defer unlockStdErr();
688 const stderr = lockStderrWriter(&.{});
689 defer unlockStderrWriter();
680690
681 const stderr = fs.File.stderr().writer();
682691 if (builtin.single_threaded) {
683692 stderr.print("panic: ", .{}) catch posix.abort();
684693 } else {
......@@ -688,7 +697,7 @@ pub fn defaultPanic(
688697 stderr.print("{s}\n", .{msg}) catch posix.abort();
689698
690699 if (@errorReturnTrace()) |t| dumpStackTrace(t.*);
691 dumpCurrentStackTrace(first_trace_addr orelse @returnAddress());
700 dumpCurrentStackTraceToWriter(first_trace_addr orelse @returnAddress(), stderr) catch {};
692701 }
693702
694703 waitForOtherThreadToFinishPanicking();
......@@ -723,7 +732,7 @@ fn waitForOtherThreadToFinishPanicking() void {
723732
724733pub fn writeStackTrace(
725734 stack_trace: std.builtin.StackTrace,
726 out_stream: anytype,
735 writer: *Writer,
727736 debug_info: *SelfInfo,
728737 tty_config: io.tty.Config,
729738) !void {
......@@ -736,15 +745,15 @@ pub fn writeStackTrace(
736745 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
737746 }) {
738747 const return_address = stack_trace.instruction_addresses[frame_index];
739 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
748 try printSourceAtAddress(debug_info, writer, return_address - 1, tty_config);
740749 }
741750
742751 if (stack_trace.index > stack_trace.instruction_addresses.len) {
743752 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
744753
745 tty_config.setColor(out_stream, .bold) catch {};
746 try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
747 tty_config.setColor(out_stream, .reset) catch {};
754 tty_config.setColor(writer, .bold) catch {};
755 try writer.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
756 tty_config.setColor(writer, .reset) catch {};
748757 }
749758}
750759
......@@ -954,7 +963,7 @@ pub const StackIterator = struct {
954963};
955964
956965pub fn writeCurrentStackTrace(
957 out_stream: anytype,
966 writer: *Writer,
958967 debug_info: *SelfInfo,
959968 tty_config: io.tty.Config,
960969 start_addr: ?usize,
......@@ -962,7 +971,7 @@ pub fn writeCurrentStackTrace(
962971 if (native_os == .windows) {
963972 var context: ThreadContext = undefined;
964973 assert(getContext(&context));
965 return writeStackTraceWindows(out_stream, debug_info, tty_config, &context, start_addr);
974 return writeStackTraceWindows(writer, debug_info, tty_config, &context, start_addr);
966975 }
967976 var context: ThreadContext = undefined;
968977 const has_context = getContext(&context);
......@@ -973,7 +982,7 @@ pub fn writeCurrentStackTrace(
973982 defer it.deinit();
974983
975984 while (it.next()) |return_address| {
976 printLastUnwindError(&it, debug_info, out_stream, tty_config);
985 printLastUnwindError(&it, debug_info, writer, tty_config);
977986
978987 // On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,
979988 // therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid
......@@ -981,8 +990,8 @@ pub fn writeCurrentStackTrace(
981990 // condition on the subsequent iteration and return `null` thus terminating the loop.
982991 // same behaviour for x86-windows-msvc
983992 const address = return_address -| 1;
984 try printSourceAtAddress(debug_info, out_stream, address, tty_config);
985 } else printLastUnwindError(&it, debug_info, out_stream, tty_config);
993 try printSourceAtAddress(debug_info, writer, address, tty_config);
994 } else printLastUnwindError(&it, debug_info, writer, tty_config);
986995}
987996
988997pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const windows.CONTEXT) usize {
......@@ -1042,7 +1051,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w
10421051}
10431052
10441053pub fn writeStackTraceWindows(
1045 out_stream: anytype,
1054 writer: *Writer,
10461055 debug_info: *SelfInfo,
10471056 tty_config: io.tty.Config,
10481057 context: *const windows.CONTEXT,
......@@ -1058,14 +1067,14 @@ pub fn writeStackTraceWindows(
10581067 return;
10591068 } else 0;
10601069 for (addrs[start_i..]) |addr| {
1061 try printSourceAtAddress(debug_info, out_stream, addr - 1, tty_config);
1070 try printSourceAtAddress(debug_info, writer, addr - 1, tty_config);
10621071 }
10631072}
10641073
1065fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void {
1074fn printUnknownSource(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void {
10661075 const module_name = debug_info.getModuleNameForAddress(address);
10671076 return printLineInfo(
1068 out_stream,
1077 writer,
10691078 null,
10701079 address,
10711080 "???",
......@@ -1075,38 +1084,38 @@ fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize
10751084 );
10761085}
10771086
1078fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, out_stream: anytype, tty_config: io.tty.Config) void {
1087fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, writer: *Writer, tty_config: io.tty.Config) void {
10791088 if (!have_ucontext) return;
10801089 if (it.getLastError()) |unwind_error| {
1081 printUnwindError(debug_info, out_stream, unwind_error.address, unwind_error.err, tty_config) catch {};
1090 printUnwindError(debug_info, writer, unwind_error.address, unwind_error.err, tty_config) catch {};
10821091 }
10831092}
10841093
1085fn printUnwindError(debug_info: *SelfInfo, out_stream: anytype, address: usize, err: UnwindError, tty_config: io.tty.Config) !void {
1094fn printUnwindError(debug_info: *SelfInfo, writer: *Writer, address: usize, err: UnwindError, tty_config: io.tty.Config) !void {
10861095 const module_name = debug_info.getModuleNameForAddress(address) orelse "???";
1087 try tty_config.setColor(out_stream, .dim);
1096 try tty_config.setColor(writer, .dim);
10881097 if (err == error.MissingDebugInfo) {
1089 try out_stream.print("Unwind information for `{s}:0x{x}` was not available, trace may be incomplete\n\n", .{ module_name, address });
1098 try writer.print("Unwind information for `{s}:0x{x}` was not available, trace may be incomplete\n\n", .{ module_name, address });
10901099 } else {
1091 try out_stream.print("Unwind error at address `{s}:0x{x}` ({}), trace may be incomplete\n\n", .{ module_name, address, err });
1100 try writer.print("Unwind error at address `{s}:0x{x}` ({}), trace may be incomplete\n\n", .{ module_name, address, err });
10921101 }
1093 try tty_config.setColor(out_stream, .reset);
1102 try tty_config.setColor(writer, .reset);
10941103}
10951104
1096pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void {
1105pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void {
10971106 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
1098 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config),
1107 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),
10991108 else => return err,
11001109 };
11011110
11021111 const symbol_info = module.getSymbolAtAddress(debug_info.allocator, address) catch |err| switch (err) {
1103 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config),
1112 error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),
11041113 else => return err,
11051114 };
11061115 defer if (symbol_info.source_location) |sl| debug_info.allocator.free(sl.file_name);
11071116
11081117 return printLineInfo(
1109 out_stream,
1118 writer,
11101119 symbol_info.source_location,
11111120 address,
11121121 symbol_info.name,
......@@ -1117,7 +1126,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address:
11171126}
11181127
11191128fn printLineInfo(
1120 out_stream: anytype,
1129 writer: *Writer,
11211130 source_location: ?SourceLocation,
11221131 address: usize,
11231132 symbol_name: []const u8,
......@@ -1126,34 +1135,34 @@ fn printLineInfo(
11261135 comptime printLineFromFile: anytype,
11271136) !void {
11281137 nosuspend {
1129 try tty_config.setColor(out_stream, .bold);
1138 try tty_config.setColor(writer, .bold);
11301139
11311140 if (source_location) |*sl| {
1132 try out_stream.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column });
1141 try writer.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column });
11331142 } else {
1134 try out_stream.writeAll("???:?:?");
1143 try writer.writeAll("???:?:?");
11351144 }
11361145
1137 try tty_config.setColor(out_stream, .reset);
1138 try out_stream.writeAll(": ");
1139 try tty_config.setColor(out_stream, .dim);
1140 try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
1141 try tty_config.setColor(out_stream, .reset);
1142 try out_stream.writeAll("\n");
1146 try tty_config.setColor(writer, .reset);
1147 try writer.writeAll(": ");
1148 try tty_config.setColor(writer, .dim);
1149 try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
1150 try tty_config.setColor(writer, .reset);
1151 try writer.writeAll("\n");
11431152
11441153 // Show the matching source code line if possible
11451154 if (source_location) |sl| {
1146 if (printLineFromFile(out_stream, sl)) {
1155 if (printLineFromFile(writer, sl)) {
11471156 if (sl.column > 0) {
11481157 // The caret already takes one char
11491158 const space_needed = @as(usize, @intCast(sl.column - 1));
11501159
1151 try out_stream.writeByteNTimes(' ', space_needed);
1152 try tty_config.setColor(out_stream, .green);
1153 try out_stream.writeAll("^");
1154 try tty_config.setColor(out_stream, .reset);
1160 try writer.splatByteAll(' ', space_needed);
1161 try tty_config.setColor(writer, .green);
1162 try writer.writeAll("^");
1163 try tty_config.setColor(writer, .reset);
11551164 }
1156 try out_stream.writeAll("\n");
1165 try writer.writeAll("\n");
11571166 } else |err| switch (err) {
11581167 error.EndOfFile, error.FileNotFound => {},
11591168 error.BadPathName => {},
......@@ -1164,7 +1173,7 @@ fn printLineInfo(
11641173 }
11651174}
11661175
1167fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) !void {
1176fn printLineFromFileAnyOs(writer: *Writer, source_location: SourceLocation) !void {
11681177 // Need this to always block even in async I/O mode, because this could potentially
11691178 // be called from e.g. the event loop code crashing.
11701179 var f = try fs.cwd().openFile(source_location.file_name, .{});
......@@ -1197,31 +1206,31 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation)
11971206 if (mem.indexOfScalar(u8, slice, '\n')) |pos| {
11981207 const line = slice[0 .. pos + 1];
11991208 mem.replaceScalar(u8, line, '\t', ' ');
1200 return out_stream.writeAll(line);
1209 return writer.writeAll(line);
12011210 } else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends.
12021211 mem.replaceScalar(u8, slice, '\t', ' ');
1203 try out_stream.writeAll(slice);
1212 try writer.writeAll(slice);
12041213 while (amt_read == buf.len) {
12051214 amt_read = try f.read(buf[0..]);
12061215 if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| {
12071216 const line = buf[0 .. pos + 1];
12081217 mem.replaceScalar(u8, line, '\t', ' ');
1209 return out_stream.writeAll(line);
1218 return writer.writeAll(line);
12101219 } else {
12111220 const line = buf[0..amt_read];
12121221 mem.replaceScalar(u8, line, '\t', ' ');
1213 try out_stream.writeAll(line);
1222 try writer.writeAll(line);
12141223 }
12151224 }
12161225 // Make sure printing last line of file inserts extra newline
1217 try out_stream.writeByte('\n');
1226 try writer.writeByte('\n');
12181227 }
12191228}
12201229
12211230test printLineFromFileAnyOs {
1222 var output = std.ArrayList(u8).init(std.testing.allocator);
1223 defer output.deinit();
1224 const output_stream = output.writer();
1231 var aw: Writer.Allocating = .init(std.testing.allocator);
1232 defer aw.deinit();
1233 const output_stream = &aw.interface;
12251234
12261235 const allocator = std.testing.allocator;
12271236 const join = std.fs.path.join;
......@@ -1243,8 +1252,8 @@ test printLineFromFileAnyOs {
12431252 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
12441253
12451254 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1246 try expectEqualStrings("no new lines in this file, but one is printed anyway\n", output.items);
1247 output.clearRetainingCapacity();
1255 try expectEqualStrings("no new lines in this file, but one is printed anyway\n", aw.getWritten());
1256 aw.clearRetainingCapacity();
12481257 }
12491258 {
12501259 const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" });
......@@ -1259,12 +1268,12 @@ test printLineFromFileAnyOs {
12591268 });
12601269
12611270 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1262 try expectEqualStrings("1\n", output.items);
1263 output.clearRetainingCapacity();
1271 try expectEqualStrings("1\n", aw.getWritten());
1272 aw.clearRetainingCapacity();
12641273
12651274 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 3, .column = 0 });
1266 try expectEqualStrings("3\n", output.items);
1267 output.clearRetainingCapacity();
1275 try expectEqualStrings("3\n", aw.getWritten());
1276 aw.clearRetainingCapacity();
12681277 }
12691278 {
12701279 const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{});
......@@ -1273,14 +1282,15 @@ test printLineFromFileAnyOs {
12731282 defer allocator.free(path);
12741283
12751284 const overlap = 10;
1276 var writer = file.writer();
1277 try writer.writeByteNTimes('a', std.heap.page_size_min - overlap);
1285 var file_writer = file.writer(&.{});
1286 const writer = &file_writer.interface;
1287 try writer.splatByteAll('a', std.heap.page_size_min - overlap);
12781288 try writer.writeByte('\n');
1279 try writer.writeByteNTimes('a', overlap);
1289 try writer.splatByteAll('a', overlap);
12801290
12811291 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
1282 try expectEqualStrings(("a" ** overlap) ++ "\n", output.items);
1283 output.clearRetainingCapacity();
1292 try expectEqualStrings(("a" ** overlap) ++ "\n", aw.getWritten());
1293 aw.clearRetainingCapacity();
12841294 }
12851295 {
12861296 const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});
......@@ -1288,12 +1298,13 @@ test printLineFromFileAnyOs {
12881298 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });
12891299 defer allocator.free(path);
12901300
1291 var writer = file.writer();
1292 try writer.writeByteNTimes('a', std.heap.page_size_max);
1301 var file_writer = file.writer(&.{});
1302 const writer = &file_writer.interface;
1303 try writer.splatByteAll('a', std.heap.page_size_max);
12931304
12941305 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1295 try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", output.items);
1296 output.clearRetainingCapacity();
1306 try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", aw.getWritten());
1307 aw.clearRetainingCapacity();
12971308 }
12981309 {
12991310 const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});
......@@ -1301,24 +1312,25 @@ test printLineFromFileAnyOs {
13011312 const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });
13021313 defer allocator.free(path);
13031314
1304 var writer = file.writer();
1305 try writer.writeByteNTimes('a', 3 * std.heap.page_size_max);
1315 var file_writer = file.writer(&.{});
1316 const writer = &file_writer.interface;
1317 try writer.splatByteAll('a', 3 * std.heap.page_size_max);
13061318
13071319 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
13081320
13091321 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1310 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", output.items);
1311 output.clearRetainingCapacity();
1322 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", aw.getWritten());
1323 aw.clearRetainingCapacity();
13121324
13131325 try writer.writeAll("a\na");
13141326
13151327 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1316 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", output.items);
1317 output.clearRetainingCapacity();
1328 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", aw.getWritten());
1329 aw.clearRetainingCapacity();
13181330
13191331 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
1320 try expectEqualStrings("a\n", output.items);
1321 output.clearRetainingCapacity();
1332 try expectEqualStrings("a\n", aw.getWritten());
1333 aw.clearRetainingCapacity();
13221334 }
13231335 {
13241336 const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});
......@@ -1326,18 +1338,19 @@ test printLineFromFileAnyOs {
13261338 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });
13271339 defer allocator.free(path);
13281340
1329 var writer = file.writer();
1341 var file_writer = file.writer(&.{});
1342 const writer = &file_writer.interface;
13301343 const real_file_start = 3 * std.heap.page_size_min;
1331 try writer.writeByteNTimes('\n', real_file_start);
1344 try writer.splatByteAll('\n', real_file_start);
13321345 try writer.writeAll("abc\ndef");
13331346
13341347 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });
1335 try expectEqualStrings("abc\n", output.items);
1336 output.clearRetainingCapacity();
1348 try expectEqualStrings("abc\n", aw.getWritten());
1349 aw.clearRetainingCapacity();
13371350
13381351 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });
1339 try expectEqualStrings("def\n", output.items);
1340 output.clearRetainingCapacity();
1352 try expectEqualStrings("def\n", aw.getWritten());
1353 aw.clearRetainingCapacity();
13411354 }
13421355}
13431356
......@@ -1461,7 +1474,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
14611474}
14621475
14631476fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
1464 const stderr = fs.File.stderr().writer();
1477 const stderr = lockStderrWriter(&.{});
1478 defer unlockStderrWriter();
14651479 _ = switch (sig) {
14661480 posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
14671481 // x86_64 doesn't have a full 64-bit virtual address space.
......@@ -1471,7 +1485,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
14711485 // but can also happen when no addressable memory is involved;
14721486 // for example when reading/writing model-specific registers
14731487 // by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).
1474 stderr.print("General protection exception (no address available)\n", .{})
1488 stderr.writeAll("General protection exception (no address available)\n")
14751489 else
14761490 stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
14771491 posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),
......@@ -1509,7 +1523,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
15091523 }, @ptrCast(ctx)).__mcontext_data;
15101524 }
15111525 relocateContext(&new_ctx);
1512 dumpStackTraceFromBase(&new_ctx);
1526 dumpStackTraceFromBase(&new_ctx, stderr);
15131527 },
15141528 else => {},
15151529 }
......@@ -1539,10 +1553,10 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
15391553 _ = panicking.fetchAdd(1, .seq_cst);
15401554
15411555 {
1542 lockStdErr();
1543 defer unlockStdErr();
1556 const stderr = lockStderrWriter(&.{});
1557 defer unlockStderrWriter();
15441558
1545 dumpSegfaultInfoWindows(info, msg, label);
1559 dumpSegfaultInfoWindows(info, msg, label, stderr);
15461560 }
15471561
15481562 waitForOtherThreadToFinishPanicking();
......@@ -1556,8 +1570,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
15561570 posix.abort();
15571571}
15581572
1559fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {
1560 const stderr = fs.File.stderr().writer();
1573fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *Writer) void {
15611574 _ = switch (msg) {
15621575 0 => stderr.print("{s}\n", .{label.?}),
15631576 1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
......@@ -1565,7 +1578,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[
15651578 else => unreachable,
15661579 } catch posix.abort();
15671580
1568 dumpStackTraceFromBase(info.ContextRecord);
1581 dumpStackTraceFromBase(info.ContextRecord, stderr);
15691582}
15701583
15711584pub fn dumpStackPointerAddr(prefix: []const u8) void {
......@@ -1588,10 +1601,10 @@ test "manage resources correctly" {
15881601 // self-hosted debug info is still too buggy
15891602 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
15901603
1591 const writer = std.io.null_writer;
1604 var writer: std.io.Writer = .discarding(&.{});
15921605 var di = try SelfInfo.open(testing.allocator);
15931606 defer di.deinit();
1594 try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.fs.File.stderr()));
1607 try printSourceAtAddress(&di, &writer, showMyTrace(), io.tty.detectConfig(.stderr()));
15951608}
15961609
15971610noinline fn showMyTrace() usize {
......@@ -1657,8 +1670,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
16571670 pub fn dump(t: @This()) void {
16581671 if (!enabled) return;
16591672
1660 const tty_config = io.tty.detectConfig(std.fs.File.stderr());
1661 const stderr = fs.File.stderr().writer();
1673 const tty_config = io.tty.detectConfig(.stderr());
1674 const stderr = lockStderrWriter(&.{});
1675 defer unlockStderrWriter();
16621676 const end = @min(t.index, size);
16631677 const debug_info = getSelfDebugInfo() catch |err| {
16641678 stderr.print(
......@@ -1688,7 +1702,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
16881702 t: @This(),
16891703 comptime fmt: []const u8,
16901704 options: std.fmt.FormatOptions,
1691 writer: anytype,
1705 writer: *Writer,
16921706 ) !void {
16931707 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
16941708 _ = options;
lib/std/debug/Dwarf.zig+3-11
......@@ -2302,11 +2302,7 @@ pub const ElfModule = struct {
23022302 };
23032303 defer debuginfod_dir.close();
23042304
2305 const filename = std.fmt.allocPrint(
2306 gpa,
2307 "{s}/debuginfo",
2308 .{std.fmt.fmtSliceHexLower(id)},
2309 ) catch break :blk;
2305 const filename = std.fmt.allocPrint(gpa, "{x}/debuginfo", .{id}) catch break :blk;
23102306 defer gpa.free(filename);
23112307
23122308 const path: Path = .{
......@@ -2330,12 +2326,8 @@ pub const ElfModule = struct {
23302326 var id_prefix_buf: [2]u8 = undefined;
23312327 var filename_buf: [38 + extension.len]u8 = undefined;
23322328
2333 _ = std.fmt.bufPrint(&id_prefix_buf, "{s}", .{std.fmt.fmtSliceHexLower(id[0..1])}) catch unreachable;
2334 const filename = std.fmt.bufPrint(
2335 &filename_buf,
2336 "{s}" ++ extension,
2337 .{std.fmt.fmtSliceHexLower(id[1..])},
2338 ) catch break :blk;
2329 _ = std.fmt.bufPrint(&id_prefix_buf, "{x}", .{id[0..1]}) catch unreachable;
2330 const filename = std.fmt.bufPrint(&filename_buf, "{x}" ++ extension, .{id[1..]}) catch break :blk;
23392331
23402332 for (global_debug_directories) |global_directory| {
23412333 const path: Path = .{
lib/std/debug/Pdb.zig+2-2
......@@ -395,7 +395,7 @@ const Msf = struct {
395395 streams: []MsfStream,
396396
397397 fn init(allocator: Allocator, file: File) !Msf {
398 const in = file.reader();
398 const in = file.deprecatedReader();
399399
400400 const superblock = try in.readStruct(pdb.SuperBlock);
401401
......@@ -514,7 +514,7 @@ const MsfStream = struct {
514514 var offset = self.pos % self.block_size;
515515
516516 try self.in_file.seekTo(block * self.block_size + offset);
517 const in = self.in_file.reader();
517 const in = self.in_file.deprecatedReader();
518518
519519 var size: usize = 0;
520520 var rem_buffer = buffer;
lib/std/fmt.zig+204-1445
......@@ -1,17 +1,20 @@
11//! String formatting and parsing.
22
3const std = @import("std.zig");
43const builtin = @import("builtin");
54
5const std = @import("std.zig");
66const io = std.io;
77const math = std.math;
88const assert = std.debug.assert;
99const mem = std.mem;
10const unicode = std.unicode;
1110const meta = std.meta;
1211const lossyCast = math.lossyCast;
1312const expectFmt = std.testing.expectFmt;
1413const testing = std.testing;
14const Allocator = std.mem.Allocator;
15const Writer = std.io.Writer;
16
17pub const float = @import("fmt/float.zig");
1518
1619pub const default_max_depth = 3;
1720
......@@ -24,11 +27,14 @@ pub const Alignment = enum {
2427const default_alignment = .right;
2528const default_fill_char = ' ';
2629
27pub const FormatOptions = struct {
30/// Deprecated in favor of `Options`.
31pub const FormatOptions = Options;
32
33pub const Options = struct {
2834 precision: ?usize = null,
2935 width: ?usize = null,
3036 alignment: Alignment = default_alignment,
31 fill: u21 = default_fill_char,
37 fill: u8 = default_fill_char,
3238};
3339
3440/// Renders fmt string with args, calling `writer` with slices of bytes.
......@@ -45,9 +51,10 @@ pub const FormatOptions = struct {
4551/// - when using a field name, you are required to enclose the field name (an identifier) in square
4652/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}
4753/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
48/// - *fill* is a single unicode codepoint which is used to pad the formatted text
54/// - *fill* is a single byte which is used to pad the formatted text
4955/// - *alignment* is one of the three bytes '<', '^', or '>' to make the text left-, center-, or right-aligned, respectively
50/// - *width* is the total width of the field in unicode codepoints
56/// - *width* is the total width of the field in bytes. This is generally only
57/// useful for ASCII text, such as numbers.
5158/// - *precision* specifies how many decimals a formatted number should have
5259///
5360/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when
......@@ -56,16 +63,20 @@ pub const FormatOptions = struct {
5663/// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*.
5764///
5865/// The *specifier* has several options for types:
59/// - `x` and `X`: output numeric value in hexadecimal notation
66/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes
6067/// - `s`:
6168/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
6269/// - for slices of u8, print the entire slice as a string without zero-termination
70/// - `b64`: output string as standard base64
6371/// - `e`: output floating point value in scientific notation
6472/// - `d`: output numeric value in decimal notation
6573/// - `b`: output integer value in binary notation
6674/// - `o`: output integer value in octal notation
6775/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
6876/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.
77/// - `D`: output nanoseconds as duration
78/// - `B`: output bytes in SI units (decimal)
79/// - `Bi`: output bytes in IEC units (binary)
6980/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value.
7081/// - `!`: output error union value as either the unwrapped value, or the formatted error value; may be followed by a format specifier for the underlying value.
7182/// - `*`: output the address of the value instead of the value itself.
......@@ -73,7 +84,7 @@ pub const FormatOptions = struct {
7384///
7485/// If a formatted user type contains a function of the type
7586/// ```
76/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void
87/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.Options, writer: anytype) !void
7788/// ```
7889/// with `?` being the type formatted, this function will be called instead of the default implementation.
7990/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
......@@ -81,11 +92,7 @@ pub const FormatOptions = struct {
8192/// A user type may be a `struct`, `vector`, `union` or `enum` type.
8293///
8394/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
84pub fn format(
85 writer: anytype,
86 comptime fmt: []const u8,
87 args: anytype,
88) !void {
95pub fn format(w: *Writer, comptime fmt: []const u8, args: anytype) Writer.Error!void {
8996 const ArgsType = @TypeOf(args);
9097 const args_type_info = @typeInfo(ArgsType);
9198 if (args_type_info != .@"struct") {
......@@ -97,7 +104,7 @@ pub fn format(
97104 @compileError("32 arguments max are supported per format call");
98105 }
99106
100 @setEvalBranchQuota(2000000);
107 @setEvalBranchQuota(fmt.len * 1000);
101108 comptime var arg_state: ArgState = .{ .args_len = fields_info.len };
102109 comptime var i = 0;
103110 comptime var literal: []const u8 = "";
......@@ -130,7 +137,7 @@ pub fn format(
130137
131138 // Write out the literal
132139 if (literal.len != 0) {
133 try writer.writeAll(literal);
140 try w.writeAll(literal);
134141 literal = "";
135142 }
136143
......@@ -157,7 +164,7 @@ pub fn format(
157164 comptime assert(fmt[i] == '}');
158165 i += 1;
159166
160 const placeholder = comptime Placeholder.parse(fmt[fmt_begin..fmt_end].*);
167 const placeholder = comptime Placeholder.parse(&(fmt[fmt_begin..fmt_end].*));
161168 const arg_pos = comptime switch (placeholder.arg) {
162169 .none => null,
163170 .number => |pos| pos,
......@@ -190,16 +197,15 @@ pub fn format(
190197 const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse
191198 @compileError("too few arguments");
192199
193 try formatType(
194 @field(args, fields_info[arg_to_print].name),
200 try w.printValue(
195201 placeholder.specifier_arg,
196 FormatOptions{
202 .{
197203 .fill = placeholder.fill,
198204 .alignment = placeholder.alignment,
199205 .width = width,
200206 .precision = precision,
201207 },
202 writer,
208 @field(args, fields_info[arg_to_print].name),
203209 std.options.fmt_max_depth,
204210 );
205211 }
......@@ -214,44 +220,41 @@ pub fn format(
214220 }
215221}
216222
223/// Deprecated in favor of `format`.
224pub fn deprecatedFormat(writer: anytype, comptime fmt: []const u8, args: anytype) !void {
225 var adapter = writer.adaptToNewApi();
226 return format(&adapter.new_interface, fmt, args) catch |err| switch (err) {
227 error.WriteFailed => return adapter.err.?,
228 };
229}
230
217231fn cacheString(str: anytype) []const u8 {
218232 return &str;
219233}
220234
221235pub const Placeholder = struct {
222236 specifier_arg: []const u8,
223 fill: u21,
237 fill: u8,
224238 alignment: Alignment,
225239 arg: Specifier,
226240 width: Specifier,
227241 precision: Specifier,
228242
229 pub fn parse(comptime str: anytype) Placeholder {
230 const view = std.unicode.Utf8View.initComptime(&str);
231 comptime var parser = Parser{
232 .iter = view.iterator(),
233 };
234
235 // Parse the positional argument number
236 const arg = comptime parser.specifier() catch |err|
237 @compileError(@errorName(err));
238
239 // Parse the format specifier
240 const specifier_arg = comptime parser.until(':');
241
242 // Skip the colon, if present
243 if (comptime parser.char()) |ch| {
244 if (ch != ':') {
245 @compileError("expected : or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
246 }
243 pub fn parse(bytes: []const u8) Placeholder {
244 var parser: Parser = .{ .bytes = bytes, .i = 0 };
245 const arg = parser.specifier() catch |err| @compileError(@errorName(err));
246 const specifier_arg = parser.until(':');
247 if (parser.char()) |b| {
248 if (b != ':') @compileError("expected : or }, found '" ++ &[1]u8{b} ++ "'");
247249 }
248250
249 // Parse the fill character, if present.
250 // When the width field is also specified, the fill character must
251 // Parse the fill byte, if present.
252 //
253 // When the width field is also specified, the fill byte must
251254 // be followed by an alignment specifier, unless it's '0' (zero)
252 // (in which case it's handled as part of the width specifier)
253 var fill: ?u21 = comptime if (parser.peek(1)) |ch|
254 switch (ch) {
255 // (in which case it's handled as part of the width specifier).
256 var fill: ?u8 = if (parser.peek(1)) |b|
257 switch (b) {
255258 '<', '^', '>' => parser.char(),
256259 else => null,
257260 }
......@@ -259,8 +262,8 @@ pub const Placeholder = struct {
259262 null;
260263
261264 // Parse the alignment parameter
262 const alignment: ?Alignment = comptime if (parser.peek(0)) |ch| init: {
263 switch (ch) {
265 const alignment: ?Alignment = if (parser.peek(0)) |b| init: {
266 switch (b) {
264267 '<', '^', '>' => {
265268 // consume the character
266269 break :init switch (parser.char().?) {
......@@ -276,29 +279,23 @@ pub const Placeholder = struct {
276279 // When none of the fill character and the alignment specifier have
277280 // been provided, check whether the width starts with a zero.
278281 if (fill == null and alignment == null) {
279 fill = comptime if (parser.peek(0) == '0') '0' else null;
282 fill = if (parser.peek(0) == '0') '0' else null;
280283 }
281284
282285 // Parse the width parameter
283 const width = comptime parser.specifier() catch |err|
284 @compileError(@errorName(err));
286 const width = parser.specifier() catch |err| @compileError(@errorName(err));
285287
286288 // Skip the dot, if present
287 if (comptime parser.char()) |ch| {
288 if (ch != '.') {
289 @compileError("expected . or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
290 }
289 if (parser.char()) |b| {
290 if (b != '.') @compileError("expected . or }, found '" ++ &[1]u8{b} ++ "'");
291291 }
292292
293293 // Parse the precision parameter
294 const precision = comptime parser.specifier() catch |err|
295 @compileError(@errorName(err));
294 const precision = parser.specifier() catch |err| @compileError(@errorName(err));
296295
297 if (comptime parser.char()) |ch| {
298 @compileError("extraneous trailing character '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
299 }
296 if (parser.char()) |b| @compileError("extraneous trailing character '" ++ &[1]u8{b} ++ "'");
300297
301 return Placeholder{
298 return .{
302299 .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),
303300 .fill = fill orelse default_fill_char,
304301 .alignment = alignment orelse default_alignment,
......@@ -320,88 +317,60 @@ pub const Specifier = union(enum) {
320317/// Allows to implement formatters compatible with std.fmt without replicating
321318/// the standard library behavior.
322319pub const Parser = struct {
323 iter: std.unicode.Utf8Iterator,
320 bytes: []const u8,
321 i: usize,
324322
325 // Returns a decimal number or null if the current character is not a
326 // digit
327323 pub fn number(self: *@This()) ?usize {
328324 var r: ?usize = null;
329
330 while (self.peek(0)) |code_point| {
331 switch (code_point) {
325 while (self.peek(0)) |byte| {
326 switch (byte) {
332327 '0'...'9' => {
333328 if (r == null) r = 0;
334329 r.? *= 10;
335 r.? += code_point - '0';
330 r.? += byte - '0';
336331 },
337332 else => break,
338333 }
339 _ = self.iter.nextCodepoint();
334 self.i += 1;
340335 }
341
342336 return r;
343337 }
344338
345 // Returns a substring of the input starting from the current position
346 // and ending where `ch` is found or until the end if not found
347 pub fn until(self: *@This(), ch: u21) []const u8 {
348 const start = self.iter.i;
349 while (self.peek(0)) |code_point| {
350 if (code_point == ch)
351 break;
352 _ = self.iter.nextCodepoint();
353 }
354 return self.iter.bytes[start..self.iter.i];
339 pub fn until(self: *@This(), delimiter: u8) []const u8 {
340 const start = self.i;
341 self.i = std.mem.indexOfScalarPos(u8, self.bytes, self.i, delimiter) orelse self.bytes.len;
342 return self.bytes[start..self.i];
355343 }
356344
357 // Returns the character pointed to by the iterator if available, or
358 // null otherwise
359 pub fn char(self: *@This()) ?u21 {
360 if (self.iter.nextCodepoint()) |code_point| {
361 return code_point;
362 }
363 return null;
345 pub fn char(self: *@This()) ?u8 {
346 const i = self.i;
347 if (self.bytes.len - i == 0) return null;
348 self.i = i + 1;
349 return self.bytes[i];
364350 }
365351
366 // Returns true if the iterator points to an existing character and
367 // false otherwise
368 pub fn maybe(self: *@This(), val: u21) bool {
369 if (self.peek(0) == val) {
370 _ = self.iter.nextCodepoint();
352 pub fn maybe(self: *@This(), byte: u8) bool {
353 if (self.peek(0) == byte) {
354 self.i += 1;
371355 return true;
372356 }
373357 return false;
374358 }
375359
376 // Returns a decimal number or null if the current character is not a
377 // digit
378360 pub fn specifier(self: *@This()) !Specifier {
379361 if (self.maybe('[')) {
380362 const arg_name = self.until(']');
381
382 if (!self.maybe(']'))
383 return @field(anyerror, "Expected closing ]");
384
385 return Specifier{ .named = arg_name };
363 if (!self.maybe(']')) return error.@"Expected closing ]";
364 return .{ .named = arg_name };
386365 }
387 if (self.number()) |i|
388 return Specifier{ .number = i };
389
390 return Specifier{ .none = {} };
366 if (self.number()) |i| return .{ .number = i };
367 return .{ .none = {} };
391368 }
392369
393 // Returns the n-th next character or null if that's past the end
394 pub fn peek(self: *@This(), n: usize) ?u21 {
395 const original_i = self.iter.i;
396 defer self.iter.i = original_i;
397
398 var i: usize = 0;
399 var code_point: ?u21 = null;
400 while (i <= n) : (i += 1) {
401 code_point = self.iter.nextCodepoint();
402 if (code_point == null) return null;
403 }
404 return code_point;
370 pub fn peek(self: *@This(), i: usize) ?u8 {
371 const peek_index = self.i + i;
372 if (peek_index >= self.bytes.len) return null;
373 return self.bytes[peek_index];
405374 }
406375};
407376
......@@ -434,822 +403,14 @@ pub const ArgState = struct {
434403 }
435404};
436405
437pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @TypeOf(writer).Error!void {
438 _ = options;
439 const T = @TypeOf(value);
440
441 switch (@typeInfo(T)) {
442 .pointer => |info| {
443 try writer.writeAll(@typeName(info.child) ++ "@");
444 if (info.size == .slice)
445 try formatInt(@intFromPtr(value.ptr), 16, .lower, FormatOptions{}, writer)
446 else
447 try formatInt(@intFromPtr(value), 16, .lower, FormatOptions{}, writer);
448 return;
449 },
450 .optional => |info| {
451 if (@typeInfo(info.child) == .pointer) {
452 try writer.writeAll(@typeName(info.child) ++ "@");
453 try formatInt(@intFromPtr(value), 16, .lower, FormatOptions{}, writer);
454 return;
455 }
456 },
457 else => {},
458 }
459
460 @compileError("cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
461}
462
463// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
464const ANY = "any";
465
466pub fn defaultSpec(comptime T: type) [:0]const u8 {
467 switch (@typeInfo(T)) {
468 .array, .vector => return ANY,
469 .pointer => |ptr_info| switch (ptr_info.size) {
470 .one => switch (@typeInfo(ptr_info.child)) {
471 .array => return ANY,
472 else => {},
473 },
474 .many, .c => return "*",
475 .slice => return ANY,
476 },
477 .optional => |info| return "?" ++ defaultSpec(info.child),
478 .error_union => |info| return "!" ++ defaultSpec(info.payload),
479 else => {},
480 }
481 return "";
482}
483
484fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 {
485 return if (std.mem.eql(u8, fmt[1..], ANY))
486 ANY
487 else
488 fmt[1..];
489}
490
491pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) void {
492 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
493}
494
495pub fn formatType(
496 value: anytype,
497 comptime fmt: []const u8,
498 options: FormatOptions,
499 writer: anytype,
500 max_depth: usize,
501) @TypeOf(writer).Error!void {
502 const T = @TypeOf(value);
503 const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY))
504 defaultSpec(T)
505 else if (fmt.len != 0 and (fmt[0] == '?' or fmt[0] == '!')) switch (@typeInfo(T)) {
506 .optional, .error_union => fmt,
507 else => stripOptionalOrErrorUnionSpec(fmt),
508 } else fmt;
509
510 if (comptime std.mem.eql(u8, actual_fmt, "*")) {
511 return formatAddress(value, options, writer);
512 }
513
514 if (std.meta.hasMethod(T, "format")) {
515 return try value.format(actual_fmt, options, writer);
516 }
517
518 switch (@typeInfo(T)) {
519 .comptime_int, .int, .comptime_float, .float => {
520 return formatValue(value, actual_fmt, options, writer);
521 },
522 .void => {
523 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
524 return formatBuf("void", options, writer);
525 },
526 .bool => {
527 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
528 return formatBuf(if (value) "true" else "false", options, writer);
529 },
530 .optional => {
531 if (actual_fmt.len == 0 or actual_fmt[0] != '?')
532 @compileError("cannot format optional without a specifier (i.e. {?} or {any})");
533 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);
534 if (value) |payload| {
535 return formatType(payload, remaining_fmt, options, writer, max_depth);
536 } else {
537 return formatBuf("null", options, writer);
538 }
539 },
540 .error_union => {
541 if (actual_fmt.len == 0 or actual_fmt[0] != '!')
542 @compileError("cannot format error union without a specifier (i.e. {!} or {any})");
543 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);
544 if (value) |payload| {
545 return formatType(payload, remaining_fmt, options, writer, max_depth);
546 } else |err| {
547 return formatType(err, "", options, writer, max_depth);
548 }
549 },
550 .error_set => {
551 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
552 try writer.writeAll("error.");
553 return writer.writeAll(@errorName(value));
554 },
555 .@"enum" => |enumInfo| {
556 try writer.writeAll(@typeName(T));
557 if (enumInfo.is_exhaustive) {
558 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
559 try writer.writeAll(".");
560 try writer.writeAll(@tagName(value));
561 return;
562 }
563
564 // Use @tagName only if value is one of known fields
565 @setEvalBranchQuota(3 * enumInfo.fields.len);
566 inline for (enumInfo.fields) |enumField| {
567 if (@intFromEnum(value) == enumField.value) {
568 try writer.writeAll(".");
569 try writer.writeAll(@tagName(value));
570 return;
571 }
572 }
573
574 try writer.writeAll("(");
575 try formatType(@intFromEnum(value), actual_fmt, options, writer, max_depth);
576 try writer.writeAll(")");
577 },
578 .@"union" => |info| {
579 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
580 try writer.writeAll(@typeName(T));
581 if (max_depth == 0) {
582 return writer.writeAll("{ ... }");
583 }
584 if (info.tag_type) |UnionTagType| {
585 try writer.writeAll("{ .");
586 try writer.writeAll(@tagName(@as(UnionTagType, value)));
587 try writer.writeAll(" = ");
588 inline for (info.fields) |u_field| {
589 if (value == @field(UnionTagType, u_field.name)) {
590 try formatType(@field(value, u_field.name), ANY, options, writer, max_depth - 1);
591 }
592 }
593 try writer.writeAll(" }");
594 } else {
595 try format(writer, "@{x}", .{@intFromPtr(&value)});
596 }
597 },
598 .@"struct" => |info| {
599 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
600 if (info.is_tuple) {
601 // Skip the type and field names when formatting tuples.
602 if (max_depth == 0) {
603 return writer.writeAll("{ ... }");
604 }
605 try writer.writeAll("{");
606 inline for (info.fields, 0..) |f, i| {
607 if (i == 0) {
608 try writer.writeAll(" ");
609 } else {
610 try writer.writeAll(", ");
611 }
612 try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1);
613 }
614 return writer.writeAll(" }");
615 }
616 try writer.writeAll(@typeName(T));
617 if (max_depth == 0) {
618 return writer.writeAll("{ ... }");
619 }
620 try writer.writeAll("{");
621 inline for (info.fields, 0..) |f, i| {
622 if (i == 0) {
623 try writer.writeAll(" .");
624 } else {
625 try writer.writeAll(", .");
626 }
627 try writer.writeAll(f.name);
628 try writer.writeAll(" = ");
629 try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1);
630 }
631 try writer.writeAll(" }");
632 },
633 .pointer => |ptr_info| switch (ptr_info.size) {
634 .one => switch (@typeInfo(ptr_info.child)) {
635 .array, .@"enum", .@"union", .@"struct" => {
636 return formatType(value.*, actual_fmt, options, writer, max_depth);
637 },
638 else => return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @intFromPtr(value) }),
639 },
640 .many, .c => {
641 if (actual_fmt.len == 0)
642 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
643 if (ptr_info.sentinel() != null) {
644 return formatType(mem.span(value), actual_fmt, options, writer, max_depth);
645 }
646 if (actual_fmt[0] == 's' and ptr_info.child == u8) {
647 return formatBuf(mem.span(value), options, writer);
648 }
649 invalidFmtError(fmt, value);
650 },
651 .slice => {
652 if (actual_fmt.len == 0)
653 @compileError("cannot format slice without a specifier (i.e. {s} or {any})");
654 if (max_depth == 0) {
655 return writer.writeAll("{ ... }");
656 }
657 if (actual_fmt[0] == 's' and ptr_info.child == u8) {
658 return formatBuf(value, options, writer);
659 }
660 try writer.writeAll("{ ");
661 for (value, 0..) |elem, i| {
662 try formatType(elem, actual_fmt, options, writer, max_depth - 1);
663 if (i != value.len - 1) {
664 try writer.writeAll(", ");
665 }
666 }
667 try writer.writeAll(" }");
668 },
669 },
670 .array => |info| {
671 if (actual_fmt.len == 0)
672 @compileError("cannot format array without a specifier (i.e. {s} or {any})");
673 if (max_depth == 0) {
674 return writer.writeAll("{ ... }");
675 }
676 if (actual_fmt[0] == 's' and info.child == u8) {
677 return formatBuf(&value, options, writer);
678 }
679 try writer.writeAll("{ ");
680 for (value, 0..) |elem, i| {
681 try formatType(elem, actual_fmt, options, writer, max_depth - 1);
682 if (i < value.len - 1) {
683 try writer.writeAll(", ");
684 }
685 }
686 try writer.writeAll(" }");
687 },
688 .vector => |info| {
689 if (max_depth == 0) {
690 return writer.writeAll("{ ... }");
691 }
692 try writer.writeAll("{ ");
693 var i: usize = 0;
694 while (i < info.len) : (i += 1) {
695 try formatType(value[i], actual_fmt, options, writer, max_depth - 1);
696 if (i < info.len - 1) {
697 try writer.writeAll(", ");
698 }
699 }
700 try writer.writeAll(" }");
701 },
702 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),
703 .type => {
704 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
705 return formatBuf(@typeName(value), options, writer);
706 },
707 .enum_literal => {
708 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
709 const buffer = [_]u8{'.'} ++ @tagName(value);
710 return formatBuf(buffer, options, writer);
711 },
712 .null => {
713 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
714 return formatBuf("null", options, writer);
715 },
716 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
717 }
718}
719
720fn formatValue(
721 value: anytype,
722 comptime fmt: []const u8,
723 options: FormatOptions,
724 writer: anytype,
725) !void {
726 const T = @TypeOf(value);
727 switch (@typeInfo(T)) {
728 .float, .comptime_float => return formatFloatValue(value, fmt, options, writer),
729 .int, .comptime_int => return formatIntValue(value, fmt, options, writer),
730 .bool => return formatBuf(if (value) "true" else "false", options, writer),
731 else => comptime unreachable,
732 }
733}
734
735pub fn formatIntValue(
736 value: anytype,
737 comptime fmt: []const u8,
738 options: FormatOptions,
739 writer: anytype,
740) !void {
741 comptime var base = 10;
742 comptime var case: Case = .lower;
743
744 const int_value = if (@TypeOf(value) == comptime_int) blk: {
745 const Int = math.IntFittingRange(value, value);
746 break :blk @as(Int, value);
747 } else value;
748
749 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
750 base = 10;
751 case = .lower;
752 } else if (comptime std.mem.eql(u8, fmt, "c")) {
753 if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) {
754 return formatAsciiChar(@as(u8, int_value), options, writer);
755 } else {
756 @compileError("cannot print integer that is larger than 8 bits as an ASCII character");
757 }
758 } else if (comptime std.mem.eql(u8, fmt, "u")) {
759 if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) {
760 return formatUnicodeCodepoint(@as(u21, int_value), options, writer);
761 } else {
762 @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");
763 }
764 } else if (comptime std.mem.eql(u8, fmt, "b")) {
765 base = 2;
766 case = .lower;
767 } else if (comptime std.mem.eql(u8, fmt, "x")) {
768 base = 16;
769 case = .lower;
770 } else if (comptime std.mem.eql(u8, fmt, "X")) {
771 base = 16;
772 case = .upper;
773 } else if (comptime std.mem.eql(u8, fmt, "o")) {
774 base = 8;
775 case = .lower;
776 } else {
777 invalidFmtError(fmt, value);
778 }
779
780 return formatInt(int_value, base, case, options, writer);
781}
782
783pub const format_float = @import("fmt/format_float.zig");
784pub const formatFloat = format_float.formatFloat;
785pub const FormatFloatError = format_float.FormatError;
786
787fn formatFloatValue(
788 value: anytype,
789 comptime fmt: []const u8,
790 options: FormatOptions,
791 writer: anytype,
792) !void {
793 var buf: [format_float.bufferSize(.decimal, f64)]u8 = undefined;
794
795 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
796 const s = formatFloat(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) {
797 error.BufferTooSmall => "(float)",
798 };
799 return formatBuf(s, options, writer);
800 } else if (comptime std.mem.eql(u8, fmt, "d")) {
801 const s = formatFloat(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
802 error.BufferTooSmall => "(float)",
803 };
804 return formatBuf(s, options, writer);
805 } else if (comptime std.mem.eql(u8, fmt, "x")) {
806 var buf_stream = std.io.fixedBufferStream(&buf);
807 formatFloatHexadecimal(value, options, buf_stream.writer()) catch |err| switch (err) {
808 error.NoSpaceLeft => unreachable,
809 };
810 return formatBuf(buf_stream.getWritten(), options, writer);
811 } else {
812 invalidFmtError(fmt, value);
813 }
814}
815
816test {
817 _ = &format_float;
818}
819
820406pub const Case = enum { lower, upper };
821407
822fn SliceHex(comptime case: Case) type {
823 const charset = "0123456789" ++ if (case == .upper) "ABCDEF" else "abcdef";
824
825 return struct {
826 pub fn format(
827 bytes: []const u8,
828 comptime fmt: []const u8,
829 options: std.fmt.FormatOptions,
830 writer: anytype,
831 ) !void {
832 _ = fmt;
833 _ = options;
834 var buf: [2]u8 = undefined;
835
836 for (bytes) |c| {
837 buf[0] = charset[c >> 4];
838 buf[1] = charset[c & 15];
839 try writer.writeAll(&buf);
840 }
841 }
842 };
843}
844
845const formatSliceHexLower = SliceHex(.lower).format;
846const formatSliceHexUpper = SliceHex(.upper).format;
847
848/// Return a Formatter for a []const u8 where every byte is formatted as a pair
849/// of lowercase hexadecimal digits.
850pub fn fmtSliceHexLower(bytes: []const u8) std.fmt.Formatter(formatSliceHexLower) {
851 return .{ .data = bytes };
852}
853
854/// Return a Formatter for a []const u8 where every byte is formatted as pair
855/// of uppercase hexadecimal digits.
856pub fn fmtSliceHexUpper(bytes: []const u8) std.fmt.Formatter(formatSliceHexUpper) {
857 return .{ .data = bytes };
858}
859
860fn SliceEscape(comptime case: Case) type {
861 const charset = "0123456789" ++ if (case == .upper) "ABCDEF" else "abcdef";
862
863 return struct {
864 pub fn format(
865 bytes: []const u8,
866 comptime fmt: []const u8,
867 options: std.fmt.FormatOptions,
868 writer: anytype,
869 ) !void {
870 _ = fmt;
871 _ = options;
872 var buf: [4]u8 = undefined;
873
874 buf[0] = '\\';
875 buf[1] = 'x';
876
877 for (bytes) |c| {
878 if (std.ascii.isPrint(c)) {
879 try writer.writeByte(c);
880 } else {
881 buf[2] = charset[c >> 4];
882 buf[3] = charset[c & 15];
883 try writer.writeAll(&buf);
884 }
885 }
886 }
887 };
888}
889
890const formatSliceEscapeLower = SliceEscape(.lower).format;
891const formatSliceEscapeUpper = SliceEscape(.upper).format;
892
893/// Return a Formatter for a []const u8 where every non-printable ASCII
894/// character is escaped as \xNN, where NN is the character in lowercase
895/// hexadecimal notation.
896pub fn fmtSliceEscapeLower(bytes: []const u8) std.fmt.Formatter(formatSliceEscapeLower) {
897 return .{ .data = bytes };
898}
899
900/// Return a Formatter for a []const u8 where every non-printable ASCII
901/// character is escaped as \xNN, where NN is the character in uppercase
902/// hexadecimal notation.
903pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscapeUpper) {
904 return .{ .data = bytes };
905}
906
907fn Size(comptime base: comptime_int) type {
908 return struct {
909 fn format(
910 value: u64,
911 comptime fmt: []const u8,
912 options: FormatOptions,
913 writer: anytype,
914 ) !void {
915 _ = fmt;
916 if (value == 0) {
917 return formatBuf("0B", options, writer);
918 }
919 // The worst case in terms of space needed is 32 bytes + 3 for the suffix.
920 var buf: [format_float.min_buffer_size + 3]u8 = undefined;
921
922 const mags_si = " kMGTPEZY";
923 const mags_iec = " KMGTPEZY";
924
925 const log2 = math.log2(value);
926 const magnitude = switch (base) {
927 1000 => @min(log2 / comptime math.log2(1000), mags_si.len - 1),
928 1024 => @min(log2 / 10, mags_iec.len - 1),
929 else => unreachable,
930 };
931 const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, base), lossyCast(f64, magnitude));
932 const suffix = switch (base) {
933 1000 => mags_si[magnitude],
934 1024 => mags_iec[magnitude],
935 else => unreachable,
936 };
937
938 const s = switch (magnitude) {
939 0 => buf[0..formatIntBuf(&buf, value, 10, .lower, .{})],
940 else => formatFloat(&buf, new_value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
941 error.BufferTooSmall => unreachable,
942 },
943 };
944
945 var i: usize = s.len;
946 if (suffix == ' ') {
947 buf[i] = 'B';
948 i += 1;
949 } else switch (base) {
950 1000 => {
951 buf[i..][0..2].* = [_]u8{ suffix, 'B' };
952 i += 2;
953 },
954 1024 => {
955 buf[i..][0..3].* = [_]u8{ suffix, 'i', 'B' };
956 i += 3;
957 },
958 else => unreachable,
959 }
960
961 return formatBuf(buf[0..i], options, writer);
962 }
963 };
964}
965const formatSizeDec = Size(1000).format;
966const formatSizeBin = Size(1024).format;
967
968/// Return a Formatter for a u64 value representing a file size.
969/// This formatter represents the number as multiple of 1000 and uses the SI
970/// measurement units (kB, MB, GB, ...).
971/// Format option `precision` is ignored when `value` is less than 1kB
972pub fn fmtIntSizeDec(value: u64) std.fmt.Formatter(formatSizeDec) {
973 return .{ .data = value };
974}
975
976/// Return a Formatter for a u64 value representing a file size.
977/// This formatter represents the number as multiple of 1024 and uses the IEC
978/// measurement units (KiB, MiB, GiB, ...).
979/// Format option `precision` is ignored when `value` is less than 1KiB
980pub fn fmtIntSizeBin(value: u64) std.fmt.Formatter(formatSizeBin) {
981 return .{ .data = value };
982}
983
984fn checkTextFmt(comptime fmt: []const u8) void {
985 if (fmt.len != 1)
986 @compileError("unsupported format string '" ++ fmt ++ "' when formatting text");
987 switch (fmt[0]) {
988 // Example of deprecation:
989 // '[deprecated_specifier]' => @compileError("specifier '[deprecated_specifier]' has been deprecated, wrap your argument in `std.some_function` instead"),
990 'x' => @compileError("specifier 'x' has been deprecated, wrap your argument in std.fmt.fmtSliceHexLower instead"),
991 'X' => @compileError("specifier 'X' has been deprecated, wrap your argument in std.fmt.fmtSliceHexUpper instead"),
992 else => {},
993 }
994}
995
996pub fn formatText(
997 bytes: []const u8,
998 comptime fmt: []const u8,
999 options: FormatOptions,
1000 writer: anytype,
1001) !void {
1002 comptime checkTextFmt(fmt);
1003 return formatBuf(bytes, options, writer);
1004}
1005
1006pub fn formatAsciiChar(
1007 c: u8,
1008 options: FormatOptions,
1009 writer: anytype,
1010) !void {
1011 return formatBuf(@as(*const [1]u8, &c), options, writer);
1012}
1013
1014pub fn formatUnicodeCodepoint(
1015 c: u21,
1016 options: FormatOptions,
1017 writer: anytype,
1018) !void {
1019 var buf: [4]u8 = undefined;
1020 const len = unicode.utf8Encode(c, &buf) catch |err| switch (err) {
1021 error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => {
1022 return formatBuf(&unicode.utf8EncodeComptime(unicode.replacement_character), options, writer);
1023 },
1024 };
1025 return formatBuf(buf[0..len], options, writer);
1026}
1027
1028pub fn formatBuf(
1029 buf: []const u8,
1030 options: FormatOptions,
1031 writer: anytype,
1032) !void {
1033 if (options.width) |min_width| {
1034 // In case of error assume the buffer content is ASCII-encoded
1035 const width = unicode.utf8CountCodepoints(buf) catch buf.len;
1036 const padding = if (width < min_width) min_width - width else 0;
1037
1038 if (padding == 0)
1039 return writer.writeAll(buf);
1040
1041 var fill_buffer: [4]u8 = undefined;
1042 const fill_utf8 = if (unicode.utf8Encode(options.fill, &fill_buffer)) |len|
1043 fill_buffer[0..len]
1044 else |err| switch (err) {
1045 error.Utf8CannotEncodeSurrogateHalf,
1046 error.CodepointTooLarge,
1047 => &unicode.utf8EncodeComptime(unicode.replacement_character),
1048 };
1049 switch (options.alignment) {
1050 .left => {
1051 try writer.writeAll(buf);
1052 try writer.writeBytesNTimes(fill_utf8, padding);
1053 },
1054 .center => {
1055 const left_padding = padding / 2;
1056 const right_padding = (padding + 1) / 2;
1057 try writer.writeBytesNTimes(fill_utf8, left_padding);
1058 try writer.writeAll(buf);
1059 try writer.writeBytesNTimes(fill_utf8, right_padding);
1060 },
1061 .right => {
1062 try writer.writeBytesNTimes(fill_utf8, padding);
1063 try writer.writeAll(buf);
1064 },
1065 }
1066 } else {
1067 // Fast path, avoid counting the number of codepoints
1068 try writer.writeAll(buf);
1069 }
1070}
1071
1072pub fn formatFloatHexadecimal(
1073 value: anytype,
1074 options: FormatOptions,
1075 writer: anytype,
1076) !void {
1077 if (math.signbit(value)) {
1078 try writer.writeByte('-');
1079 }
1080 if (math.isNan(value)) {
1081 return writer.writeAll("nan");
1082 }
1083 if (math.isInf(value)) {
1084 return writer.writeAll("inf");
1085 }
1086
1087 const T = @TypeOf(value);
1088 const TU = std.meta.Int(.unsigned, @bitSizeOf(T));
1089
1090 const mantissa_bits = math.floatMantissaBits(T);
1091 const fractional_bits = math.floatFractionalBits(T);
1092 const exponent_bits = math.floatExponentBits(T);
1093 const mantissa_mask = (1 << mantissa_bits) - 1;
1094 const exponent_mask = (1 << exponent_bits) - 1;
1095 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
1096
1097 const as_bits = @as(TU, @bitCast(value));
1098 var mantissa = as_bits & mantissa_mask;
1099 var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask));
1100
1101 const is_denormal = exponent == 0 and mantissa != 0;
1102 const is_zero = exponent == 0 and mantissa == 0;
1103
1104 if (is_zero) {
1105 // Handle this case here to simplify the logic below.
1106 try writer.writeAll("0x0");
1107 if (options.precision) |precision| {
1108 if (precision > 0) {
1109 try writer.writeAll(".");
1110 try writer.writeByteNTimes('0', precision);
1111 }
1112 } else {
1113 try writer.writeAll(".0");
1114 }
1115 try writer.writeAll("p0");
1116 return;
1117 }
1118
1119 if (is_denormal) {
1120 // Adjust the exponent for printing.
1121 exponent += 1;
1122 } else {
1123 if (fractional_bits == mantissa_bits)
1124 mantissa |= 1 << fractional_bits; // Add the implicit integer bit.
1125 }
1126
1127 const mantissa_digits = (fractional_bits + 3) / 4;
1128 // Fill in zeroes to round the fraction width to a multiple of 4.
1129 mantissa <<= mantissa_digits * 4 - fractional_bits;
1130
1131 if (options.precision) |precision| {
1132 // Round if needed.
1133 if (precision < mantissa_digits) {
1134 // We always have at least 4 extra bits.
1135 var extra_bits = (mantissa_digits - precision) * 4;
1136 // The result LSB is the Guard bit, we need two more (Round and
1137 // Sticky) to round the value.
1138 while (extra_bits > 2) {
1139 mantissa = (mantissa >> 1) | (mantissa & 1);
1140 extra_bits -= 1;
1141 }
1142 // Round to nearest, tie to even.
1143 mantissa |= @intFromBool(mantissa & 0b100 != 0);
1144 mantissa += 1;
1145 // Drop the excess bits.
1146 mantissa >>= 2;
1147 // Restore the alignment.
1148 mantissa <<= @as(math.Log2Int(TU), @intCast((mantissa_digits - precision) * 4));
1149
1150 const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0;
1151 // Prefer a normalized result in case of overflow.
1152 if (overflow) {
1153 mantissa >>= 1;
1154 exponent += 1;
1155 }
1156 }
1157 }
1158
1159 // +1 for the decimal part.
1160 var buf: [1 + mantissa_digits]u8 = undefined;
1161 _ = formatIntBuf(&buf, mantissa, 16, .lower, .{ .fill = '0', .width = 1 + mantissa_digits });
1162
1163 try writer.writeAll("0x");
1164 try writer.writeByte(buf[0]);
1165 const trimmed = mem.trimEnd(u8, buf[1..], "0");
1166 if (options.precision) |precision| {
1167 if (precision > 0) try writer.writeAll(".");
1168 } else if (trimmed.len > 0) {
1169 try writer.writeAll(".");
1170 }
1171 try writer.writeAll(trimmed);
1172 // Add trailing zeros if explicitly requested.
1173 if (options.precision) |precision| if (precision > 0) {
1174 if (precision > trimmed.len)
1175 try writer.writeByteNTimes('0', precision - trimmed.len);
1176 };
1177 try writer.writeAll("p");
1178 try formatInt(exponent - exponent_bias, 10, .lower, .{}, writer);
1179}
1180
1181pub fn formatInt(
1182 value: anytype,
1183 base: u8,
1184 case: Case,
1185 options: FormatOptions,
1186 writer: anytype,
1187) !void {
1188 assert(base >= 2);
1189
1190 const int_value = if (@TypeOf(value) == comptime_int) blk: {
1191 const Int = math.IntFittingRange(value, value);
1192 break :blk @as(Int, value);
1193 } else value;
1194
1195 const value_info = @typeInfo(@TypeOf(int_value)).int;
1196
1197 // The type must have the same size as `base` or be wider in order for the
1198 // division to work
1199 const min_int_bits = comptime @max(value_info.bits, 8);
1200 const MinInt = std.meta.Int(.unsigned, min_int_bits);
1201
1202 const abs_value = @abs(int_value);
1203 // The worst case in terms of space needed is base 2, plus 1 for the sign
1204 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
1205
1206 var a: MinInt = abs_value;
1207 var index: usize = buf.len;
1208
1209 if (base == 10) {
1210 while (a >= 100) : (a = @divTrunc(a, 100)) {
1211 index -= 2;
1212 buf[index..][0..2].* = digits2(@intCast(a % 100));
1213 }
1214
1215 if (a < 10) {
1216 index -= 1;
1217 buf[index] = '0' + @as(u8, @intCast(a));
1218 } else {
1219 index -= 2;
1220 buf[index..][0..2].* = digits2(@intCast(a));
1221 }
1222 } else {
1223 while (true) {
1224 const digit = a % base;
1225 index -= 1;
1226 buf[index] = digitToChar(@intCast(digit), case);
1227 a /= base;
1228 if (a == 0) break;
1229 }
1230 }
1231
1232 if (value_info.signedness == .signed) {
1233 if (value < 0) {
1234 // Negative integer
1235 index -= 1;
1236 buf[index] = '-';
1237 } else if (options.width == null or options.width.? == 0) {
1238 // Positive integer, omit the plus sign
1239 } else {
1240 // Positive integer
1241 index -= 1;
1242 buf[index] = '+';
1243 }
1244 }
1245
1246 return formatBuf(buf[index..], options, writer);
1247}
1248
1249pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) usize {
1250 var fbs = std.io.fixedBufferStream(out_buf);
1251 formatInt(value, base, case, options, fbs.writer()) catch unreachable;
1252 return fbs.pos;
408/// Asserts the rendered integer value fits in `buffer`.
409/// Returns the end index within `buffer`.
410pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {
411 var bw: Writer = .fixed(buffer);
412 bw.printIntOptions(value, base, case, options) catch unreachable;
413 return bw.end;
1253414}
1254415
1255416/// Converts values in the range [0, 100) to a base 10 string.
......@@ -1261,244 +422,22 @@ pub fn digits2(value: u8) [2]u8 {
1261422 }
1262423}
1263424
1264const FormatDurationData = struct {
1265 ns: u64,
1266 negative: bool = false,
1267};
1268
1269fn formatDuration(data: FormatDurationData, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
1270 _ = fmt;
1271
1272 // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24
1273 var buf: [24]u8 = undefined;
1274 var fbs = std.io.fixedBufferStream(&buf);
1275 var buf_writer = fbs.writer();
1276 if (data.negative) {
1277 buf_writer.writeByte('-') catch unreachable;
1278 }
1279
1280 var ns_remaining = data.ns;
1281 inline for (.{
1282 .{ .ns = 365 * std.time.ns_per_day, .sep = 'y' },
1283 .{ .ns = std.time.ns_per_week, .sep = 'w' },
1284 .{ .ns = std.time.ns_per_day, .sep = 'd' },
1285 .{ .ns = std.time.ns_per_hour, .sep = 'h' },
1286 .{ .ns = std.time.ns_per_min, .sep = 'm' },
1287 }) |unit| {
1288 if (ns_remaining >= unit.ns) {
1289 const units = ns_remaining / unit.ns;
1290 formatInt(units, 10, .lower, .{}, buf_writer) catch unreachable;
1291 buf_writer.writeByte(unit.sep) catch unreachable;
1292 ns_remaining -= units * unit.ns;
1293 if (ns_remaining == 0)
1294 return formatBuf(fbs.getWritten(), options, writer);
1295 }
1296 }
1297
1298 inline for (.{
1299 .{ .ns = std.time.ns_per_s, .sep = "s" },
1300 .{ .ns = std.time.ns_per_ms, .sep = "ms" },
1301 .{ .ns = std.time.ns_per_us, .sep = "us" },
1302 }) |unit| {
1303 const kunits = ns_remaining * 1000 / unit.ns;
1304 if (kunits >= 1000) {
1305 formatInt(kunits / 1000, 10, .lower, .{}, buf_writer) catch unreachable;
1306 const frac = kunits % 1000;
1307 if (frac > 0) {
1308 // Write up to 3 decimal places
1309 var decimal_buf = [_]u8{ '.', 0, 0, 0 };
1310 _ = formatIntBuf(decimal_buf[1..], frac, 10, .lower, .{ .fill = '0', .width = 3 });
1311 var end: usize = 4;
1312 while (end > 1) : (end -= 1) {
1313 if (decimal_buf[end - 1] != '0') break;
1314 }
1315 buf_writer.writeAll(decimal_buf[0..end]) catch unreachable;
1316 }
1317 buf_writer.writeAll(unit.sep) catch unreachable;
1318 return formatBuf(fbs.getWritten(), options, writer);
1319 }
1320 }
1321
1322 formatInt(ns_remaining, 10, .lower, .{}, buf_writer) catch unreachable;
1323 buf_writer.writeAll("ns") catch unreachable;
1324 return formatBuf(fbs.getWritten(), options, writer);
1325}
1326
1327/// Return a Formatter for number of nanoseconds according to its magnitude:
1328/// [#y][#w][#d][#h][#m]#[.###][n|u|m]s
1329pub fn fmtDuration(ns: u64) Formatter(formatDuration) {
1330 const data = FormatDurationData{ .ns = ns };
1331 return .{ .data = data };
1332}
1333
1334test fmtDuration {
1335 var buf: [24]u8 = undefined;
1336 inline for (.{
1337 .{ .s = "0ns", .d = 0 },
1338 .{ .s = "1ns", .d = 1 },
1339 .{ .s = "999ns", .d = std.time.ns_per_us - 1 },
1340 .{ .s = "1us", .d = std.time.ns_per_us },
1341 .{ .s = "1.45us", .d = 1450 },
1342 .{ .s = "1.5us", .d = 3 * std.time.ns_per_us / 2 },
1343 .{ .s = "14.5us", .d = 14500 },
1344 .{ .s = "145us", .d = 145000 },
1345 .{ .s = "999.999us", .d = std.time.ns_per_ms - 1 },
1346 .{ .s = "1ms", .d = std.time.ns_per_ms + 1 },
1347 .{ .s = "1.5ms", .d = 3 * std.time.ns_per_ms / 2 },
1348 .{ .s = "1.11ms", .d = 1110000 },
1349 .{ .s = "1.111ms", .d = 1111000 },
1350 .{ .s = "1.111ms", .d = 1111100 },
1351 .{ .s = "999.999ms", .d = std.time.ns_per_s - 1 },
1352 .{ .s = "1s", .d = std.time.ns_per_s },
1353 .{ .s = "59.999s", .d = std.time.ns_per_min - 1 },
1354 .{ .s = "1m", .d = std.time.ns_per_min },
1355 .{ .s = "1h", .d = std.time.ns_per_hour },
1356 .{ .s = "1d", .d = std.time.ns_per_day },
1357 .{ .s = "1w", .d = std.time.ns_per_week },
1358 .{ .s = "1y", .d = 365 * std.time.ns_per_day },
1359 .{ .s = "1y52w23h59m59.999s", .d = 730 * std.time.ns_per_day - 1 }, // 365d = 52w1d
1360 .{ .s = "1y1h1.001s", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms },
1361 .{ .s = "1y1h1s", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us },
1362 .{ .s = "1y1h999.999us", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1 },
1363 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms },
1364 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1 },
1365 .{ .s = "1y1m999ns", .d = 365 * std.time.ns_per_day + std.time.ns_per_min + 999 },
1366 .{ .s = "584y49w23h34m33.709s", .d = math.maxInt(u64) },
1367 }) |tc| {
1368 const slice = try bufPrint(&buf, "{}", .{fmtDuration(tc.d)});
1369 try std.testing.expectEqualStrings(tc.s, slice);
1370 }
1371
1372 inline for (.{
1373 .{ .s = "=======0ns", .f = "{s:=>10}", .d = 0 },
1374 .{ .s = "1ns=======", .f = "{s:=<10}", .d = 1 },
1375 .{ .s = " 999ns ", .f = "{s:^10}", .d = std.time.ns_per_us - 1 },
1376 }) |tc| {
1377 const slice = try bufPrint(&buf, tc.f, .{fmtDuration(tc.d)});
1378 try std.testing.expectEqualStrings(tc.s, slice);
1379 }
1380}
1381
1382fn formatDurationSigned(ns: i64, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
1383 const data = FormatDurationData{ .ns = @abs(ns), .negative = ns < 0 };
1384 try formatDuration(data, fmt, options, writer);
1385}
1386
1387/// Return a Formatter for number of nanoseconds according to its signed magnitude:
1388/// [#y][#w][#d][#h][#m]#[.###][n|u|m]s
1389pub fn fmtDurationSigned(ns: i64) Formatter(formatDurationSigned) {
1390 return .{ .data = ns };
1391}
1392
1393test fmtDurationSigned {
1394 var buf: [24]u8 = undefined;
1395 inline for (.{
1396 .{ .s = "0ns", .d = 0 },
1397 .{ .s = "1ns", .d = 1 },
1398 .{ .s = "-1ns", .d = -(1) },
1399 .{ .s = "999ns", .d = std.time.ns_per_us - 1 },
1400 .{ .s = "-999ns", .d = -(std.time.ns_per_us - 1) },
1401 .{ .s = "1us", .d = std.time.ns_per_us },
1402 .{ .s = "-1us", .d = -(std.time.ns_per_us) },
1403 .{ .s = "1.45us", .d = 1450 },
1404 .{ .s = "-1.45us", .d = -(1450) },
1405 .{ .s = "1.5us", .d = 3 * std.time.ns_per_us / 2 },
1406 .{ .s = "-1.5us", .d = -(3 * std.time.ns_per_us / 2) },
1407 .{ .s = "14.5us", .d = 14500 },
1408 .{ .s = "-14.5us", .d = -(14500) },
1409 .{ .s = "145us", .d = 145000 },
1410 .{ .s = "-145us", .d = -(145000) },
1411 .{ .s = "999.999us", .d = std.time.ns_per_ms - 1 },
1412 .{ .s = "-999.999us", .d = -(std.time.ns_per_ms - 1) },
1413 .{ .s = "1ms", .d = std.time.ns_per_ms + 1 },
1414 .{ .s = "-1ms", .d = -(std.time.ns_per_ms + 1) },
1415 .{ .s = "1.5ms", .d = 3 * std.time.ns_per_ms / 2 },
1416 .{ .s = "-1.5ms", .d = -(3 * std.time.ns_per_ms / 2) },
1417 .{ .s = "1.11ms", .d = 1110000 },
1418 .{ .s = "-1.11ms", .d = -(1110000) },
1419 .{ .s = "1.111ms", .d = 1111000 },
1420 .{ .s = "-1.111ms", .d = -(1111000) },
1421 .{ .s = "1.111ms", .d = 1111100 },
1422 .{ .s = "-1.111ms", .d = -(1111100) },
1423 .{ .s = "999.999ms", .d = std.time.ns_per_s - 1 },
1424 .{ .s = "-999.999ms", .d = -(std.time.ns_per_s - 1) },
1425 .{ .s = "1s", .d = std.time.ns_per_s },
1426 .{ .s = "-1s", .d = -(std.time.ns_per_s) },
1427 .{ .s = "59.999s", .d = std.time.ns_per_min - 1 },
1428 .{ .s = "-59.999s", .d = -(std.time.ns_per_min - 1) },
1429 .{ .s = "1m", .d = std.time.ns_per_min },
1430 .{ .s = "-1m", .d = -(std.time.ns_per_min) },
1431 .{ .s = "1h", .d = std.time.ns_per_hour },
1432 .{ .s = "-1h", .d = -(std.time.ns_per_hour) },
1433 .{ .s = "1d", .d = std.time.ns_per_day },
1434 .{ .s = "-1d", .d = -(std.time.ns_per_day) },
1435 .{ .s = "1w", .d = std.time.ns_per_week },
1436 .{ .s = "-1w", .d = -(std.time.ns_per_week) },
1437 .{ .s = "1y", .d = 365 * std.time.ns_per_day },
1438 .{ .s = "-1y", .d = -(365 * std.time.ns_per_day) },
1439 .{ .s = "1y52w23h59m59.999s", .d = 730 * std.time.ns_per_day - 1 }, // 365d = 52w1d
1440 .{ .s = "-1y52w23h59m59.999s", .d = -(730 * std.time.ns_per_day - 1) }, // 365d = 52w1d
1441 .{ .s = "1y1h1.001s", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms },
1442 .{ .s = "-1y1h1.001s", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms) },
1443 .{ .s = "1y1h1s", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us },
1444 .{ .s = "-1y1h1s", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us) },
1445 .{ .s = "1y1h999.999us", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1 },
1446 .{ .s = "-1y1h999.999us", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1) },
1447 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms },
1448 .{ .s = "-1y1h1ms", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms) },
1449 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1 },
1450 .{ .s = "-1y1h1ms", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1) },
1451 .{ .s = "1y1m999ns", .d = 365 * std.time.ns_per_day + std.time.ns_per_min + 999 },
1452 .{ .s = "-1y1m999ns", .d = -(365 * std.time.ns_per_day + std.time.ns_per_min + 999) },
1453 .{ .s = "292y24w3d23h47m16.854s", .d = math.maxInt(i64) },
1454 .{ .s = "-292y24w3d23h47m16.854s", .d = math.minInt(i64) + 1 },
1455 .{ .s = "-292y24w3d23h47m16.854s", .d = math.minInt(i64) },
1456 }) |tc| {
1457 const slice = try bufPrint(&buf, "{}", .{fmtDurationSigned(tc.d)});
1458 try std.testing.expectEqualStrings(tc.s, slice);
1459 }
1460
1461 inline for (.{
1462 .{ .s = "=======0ns", .f = "{s:=>10}", .d = 0 },
1463 .{ .s = "1ns=======", .f = "{s:=<10}", .d = 1 },
1464 .{ .s = "-1ns======", .f = "{s:=<10}", .d = -(1) },
1465 .{ .s = " -999ns ", .f = "{s:^10}", .d = -(std.time.ns_per_us - 1) },
1466 }) |tc| {
1467 const slice = try bufPrint(&buf, tc.f, .{fmtDurationSigned(tc.d)});
1468 try std.testing.expectEqualStrings(tc.s, slice);
1469 }
1470}
1471
1472425pub const ParseIntError = error{
1473 /// The result cannot fit in the type specified
426 /// The result cannot fit in the type specified.
1474427 Overflow,
1475
1476 /// The input was empty or contained an invalid character
428 /// The input was empty or contained an invalid character.
1477429 InvalidCharacter,
1478430};
1479431
1480/// Creates a Formatter type from a format function. Wrapping data in Formatter(func) causes
1481/// the data to be formatted using the given function `func`. `func` must be of the following
1482/// form:
1483///
1484/// fn formatExample(
1485/// data: T,
1486/// comptime fmt: []const u8,
1487/// options: std.fmt.FormatOptions,
1488/// writer: anytype,
1489/// ) !void;
1490///
1491pub fn Formatter(comptime formatFn: anytype) type {
1492 const Data = @typeInfo(@TypeOf(formatFn)).@"fn".params[0].type.?;
432pub fn Formatter(
433 comptime Data: type,
434 comptime formatFn: fn (data: Data, writer: *Writer) Writer.Error!void,
435) type {
1493436 return struct {
1494437 data: Data,
1495 pub fn format(
1496 self: @This(),
1497 comptime fmt: []const u8,
1498 options: std.fmt.FormatOptions,
1499 writer: anytype,
1500 ) @TypeOf(writer).Error!void {
1501 try formatFn(self.data, fmt, options, writer);
438 pub fn format(self: @This(), writer: *Writer, comptime fmt: []const u8) Writer.Error!void {
439 comptime assert(fmt.len == 0);
440 try formatFn(self.data, writer);
1502441 }
1503442 };
1504443}
......@@ -1793,15 +732,13 @@ pub const BufPrintError = error{
1793732 NoSpaceLeft,
1794733};
1795734
1796/// Print a Formatter string into `buf`. Actually just a thin wrapper around `format` and `fixedBufferStream`.
1797/// Returns a slice of the bytes printed to.
735/// Print a Formatter string into `buf`. Returns a slice of the bytes printed.
1798736pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {
1799 var fbs = std.io.fixedBufferStream(buf);
1800 format(fbs.writer().any(), fmt, args) catch |err| switch (err) {
1801 error.NoSpaceLeft => return error.NoSpaceLeft,
1802 else => unreachable,
737 var w: Writer = .fixed(buf);
738 w.print(fmt, args) catch |err| switch (err) {
739 error.WriteFailed => return error.NoSpaceLeft,
1803740 };
1804 return fbs.getWritten();
741 return w.buffered();
1805742}
1806743
1807744pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![:0]u8 {
......@@ -1809,51 +746,37 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr
1809746 return result[0 .. result.len - 1 :0];
1810747}
1811748
1812/// Count the characters needed for format. Useful for preallocating memory
1813pub fn count(comptime fmt: []const u8, args: anytype) u64 {
1814 var counting_writer = std.io.countingWriter(std.io.null_writer);
1815 format(counting_writer.writer().any(), fmt, args) catch unreachable;
1816 return counting_writer.bytes_written;
1817}
1818
1819pub const AllocPrintError = error{OutOfMemory};
1820
1821pub fn allocPrint(allocator: mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![]u8 {
1822 const size = math.cast(usize, count(fmt, args)) orelse return error.OutOfMemory;
1823 const buf = try allocator.alloc(u8, size);
1824 return bufPrint(buf, fmt, args) catch |err| switch (err) {
1825 error.NoSpaceLeft => unreachable, // we just counted the size above
749/// Count the characters needed for format.
750pub fn count(comptime fmt: []const u8, args: anytype) usize {
751 var trash_buffer: [64]u8 = undefined;
752 var w: Writer = .discarding(&trash_buffer);
753 w.print(fmt, args) catch |err| switch (err) {
754 error.WriteFailed => unreachable,
1826755 };
756 return w.count;
1827757}
1828758
1829pub fn allocPrintZ(allocator: mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![:0]u8 {
1830 const result = try allocPrint(allocator, fmt ++ "\x00", args);
1831 return result[0 .. result.len - 1 :0];
1832}
1833
1834test bufPrintIntToSlice {
1835 var buffer: [100]u8 = undefined;
1836 const buf = buffer[0..];
1837
1838 try std.testing.expectEqualSlices(u8, "-1", bufPrintIntToSlice(buf, @as(i1, -1), 10, .lower, FormatOptions{}));
1839
1840 try std.testing.expectEqualSlices(u8, "-101111000110000101001110", bufPrintIntToSlice(buf, @as(i32, -12345678), 2, .lower, FormatOptions{}));
1841 try std.testing.expectEqualSlices(u8, "-12345678", bufPrintIntToSlice(buf, @as(i32, -12345678), 10, .lower, FormatOptions{}));
1842 try std.testing.expectEqualSlices(u8, "-bc614e", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, .lower, FormatOptions{}));
1843 try std.testing.expectEqualSlices(u8, "-BC614E", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, .upper, FormatOptions{}));
1844
1845 try std.testing.expectEqualSlices(u8, "12345678", bufPrintIntToSlice(buf, @as(u32, 12345678), 10, .upper, FormatOptions{}));
1846
1847 try std.testing.expectEqualSlices(u8, " 666", bufPrintIntToSlice(buf, @as(u32, 666), 10, .lower, FormatOptions{ .width = 6 }));
1848 try std.testing.expectEqualSlices(u8, " 1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, .lower, FormatOptions{ .width = 6 }));
1849 try std.testing.expectEqualSlices(u8, "1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, .lower, FormatOptions{ .width = 1 }));
1850
1851 try std.testing.expectEqualSlices(u8, "+42", bufPrintIntToSlice(buf, @as(i32, 42), 10, .lower, FormatOptions{ .width = 3 }));
1852 try std.testing.expectEqualSlices(u8, "-42", bufPrintIntToSlice(buf, @as(i32, -42), 10, .lower, FormatOptions{ .width = 3 }));
759pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {
760 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
761 defer aw.deinit();
762 aw.interface.print(fmt, args) catch |err| switch (err) {
763 error.WriteFailed => return error.OutOfMemory,
764 };
765 return aw.toOwnedSlice();
1853766}
1854767
1855pub fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) []u8 {
1856 return buf[0..formatIntBuf(buf, value, base, case, options)];
768pub fn allocPrintSentinel(
769 gpa: Allocator,
770 comptime fmt: []const u8,
771 args: anytype,
772 comptime sentinel: u8,
773) Allocator.Error![:sentinel]u8 {
774 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
775 defer aw.deinit();
776 aw.interface.print(fmt, args) catch |err| switch (err) {
777 error.WriteFailed => return error.OutOfMemory,
778 };
779 return aw.toOwnedSliceSentinel(sentinel);
1857780}
1858781
1859782pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
......@@ -1984,26 +907,22 @@ test "int.padded" {
1984907 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});
1985908 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});
1986909 try expectFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});
1987
1988 try expectFmt("UTF-8: 'ü '", "UTF-8: '{u:<4}'", .{'ü'});
1989 try expectFmt("UTF-8: ' ü'", "UTF-8: '{u:>4}'", .{'ü'});
1990 try expectFmt("UTF-8: ' ü '", "UTF-8: '{u:^4}'", .{'ü'});
1991910}
1992911
1993912test "buffer" {
1994913 {
1995914 var buf1: [32]u8 = undefined;
1996 var fbs = std.io.fixedBufferStream(&buf1);
1997 try formatType(1234, "", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);
1998 try std.testing.expectEqualStrings("1234", fbs.getWritten());
915 var w: Writer = .fixed(&buf1);
916 try w.printValue("", .{}, 1234, std.options.fmt_max_depth);
917 try std.testing.expectEqualStrings("1234", w.buffered());
1999918
2000 fbs.reset();
2001 try formatType('a', "c", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);
2002 try std.testing.expectEqualStrings("a", fbs.getWritten());
919 w = .fixed(&buf1);
920 try w.printValue("c", .{}, 'a', std.options.fmt_max_depth);
921 try std.testing.expectEqualStrings("a", w.buffered());
2003922
2004 fbs.reset();
2005 try formatType(0b1100, "b", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);
2006 try std.testing.expectEqualStrings("1100", fbs.getWritten());
923 w = .fixed(&buf1);
924 try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);
925 try std.testing.expectEqualStrings("1100", w.buffered());
2007926 }
2008927}
2009928
......@@ -2021,7 +940,7 @@ test "array" {
2021940 const value: [3]u8 = "abc".*;
2022941 try expectArrayFmt("array: abc\n", "array: {s}\n", value);
2023942 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\n", value);
2024 try expectArrayFmt("array: { 61, 62, 63 }\n", "array: {x}\n", value);
943 try expectArrayFmt("array: 616263\n", "array: {x}\n", value);
2025944 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
2026945
2027946 var buf: [100]u8 = undefined;
......@@ -2037,7 +956,7 @@ test "array" {
2037956
2038957 try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value);
2039958 try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value);
2040 try expectArrayFmt("array: { { 61, 62, 63 }, { 64, 65, 66 } }\n", "array: {x}\n", value);
959 try expectArrayFmt("array: { 616263, 646566 }\n", "array: {x}\n", value);
2041960 }
2042961}
2043962
......@@ -2046,7 +965,7 @@ test "slice" {
2046965 const value: []const u8 = "abc";
2047966 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});
2048967 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value});
2049 try expectFmt("slice: { 61, 62, 63 }\n", "slice: {x}\n", .{value});
968 try expectFmt("slice: 616263\n", "slice: {x}\n", .{value});
2050969 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});
2051970 }
2052971 {
......@@ -2083,22 +1002,15 @@ test "slice" {
20831002 const S2 = struct {
20841003 x: u8,
20851004
2086 pub fn format(s: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
1005 pub fn format(s: @This(), writer: *Writer, comptime _: []const u8) Writer.Error!void {
20871006 try writer.print("S2({})", .{s.x});
20881007 }
20891008 };
20901009 const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } };
2091 try expectFmt("slice: { S2(8), S2(42) }", "slice: {any}", .{struct_slice});
1010 try expectFmt("slice: { fmt.test.slice.S2{ .x = 8 }, fmt.test.slice.S2{ .x = 42 } }", "slice: {any}", .{struct_slice});
20921011 }
20931012}
20941013
2095test "escape non-printable" {
2096 try expectFmt("abc 123", "{s}", .{fmtSliceEscapeLower("abc 123")});
2097 try expectFmt("ab\\xffc", "{s}", .{fmtSliceEscapeLower("ab\xffc")});
2098 try expectFmt("abc 123", "{s}", .{fmtSliceEscapeUpper("abc 123")});
2099 try expectFmt("ab\\xFFc", "{s}", .{fmtSliceEscapeUpper("ab\xffc")});
2100}
2101
21021014test "pointer" {
21031015 {
21041016 const value = @as(*align(1) i32, @ptrFromInt(0xdeadbeef));
......@@ -2129,21 +1041,6 @@ test "cstr" {
21291041 );
21301042}
21311043
2132test "filesize" {
2133 try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeDec(42)});
2134 try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeBin(42)});
2135 try expectFmt("file size: 63MB\n", "file size: {}\n", .{fmtIntSizeDec(63 * 1000 * 1000)});
2136 try expectFmt("file size: 63MiB\n", "file size: {}\n", .{fmtIntSizeBin(63 * 1024 * 1024)});
2137 try expectFmt("file size: 42B\n", "file size: {:.2}\n", .{fmtIntSizeDec(42)});
2138 try expectFmt("file size: 42B\n", "file size: {:>9.2}\n", .{fmtIntSizeDec(42)});
2139 try expectFmt("file size: 66.06MB\n", "file size: {:.2}\n", .{fmtIntSizeDec(63 * 1024 * 1024)});
2140 try expectFmt("file size: 60.08MiB\n", "file size: {:.2}\n", .{fmtIntSizeBin(63 * 1000 * 1000)});
2141 try expectFmt("file size: =66.06MB=\n", "file size: {:=^9.2}\n", .{fmtIntSizeDec(63 * 1024 * 1024)});
2142 try expectFmt("file size: 66.06MB\n", "file size: {: >9.2}\n", .{fmtIntSizeDec(63 * 1024 * 1024)});
2143 try expectFmt("file size: 66.06MB \n", "file size: {: <9.2}\n", .{fmtIntSizeDec(63 * 1024 * 1024)});
2144 try expectFmt("file size: 0.01844674407370955ZB\n", "file size: {}\n", .{fmtIntSizeDec(math.maxInt(u64))});
2145}
2146
21471044test "struct" {
21481045 {
21491046 const Struct = struct {
......@@ -2176,7 +1073,7 @@ test "struct" {
21761073 // Tuples
21771074 try expectFmt("{ }", "{}", .{.{}});
21781075 try expectFmt("{ -1 }", "{}", .{.{-1}});
2179 try expectFmt("{ -1, 42, 2.5e4 }", "{}", .{.{ -1, 42, 0.25e5 }});
1076 try expectFmt("{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }});
21801077}
21811078
21821079test "enum" {
......@@ -2216,10 +1113,14 @@ test "non-exhaustive enum" {
22161113 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One});
22171114 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two});
22181115 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))});
2219 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {x}\n", .{Enum.One});
2220 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {x}\n", .{Enum.Two});
2221 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {X}\n", .{Enum.Two});
2222 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(1234)\n", "enum: {x}\n", .{@as(Enum, @enumFromInt(0x1234))});
1116 try expectFmt("enum: f\n", "enum: {x}\n", .{Enum.One});
1117 try expectFmt("enum: beef\n", "enum: {x}\n", .{Enum.Two});
1118 try expectFmt("enum: BEEF\n", "enum: {X}\n", .{Enum.Two});
1119 try expectFmt("enum: 1234\n", "enum: {x}\n", .{@as(Enum, @enumFromInt(0x1234))});
1120
1121 try expectFmt("enum: 15\n", "enum: {d}\n", .{Enum.One});
1122 try expectFmt("enum: 48879\n", "enum: {d}\n", .{Enum.Two});
1123 try expectFmt("enum: 4660\n", "enum: {d}\n", .{@as(Enum, @enumFromInt(0x1234))});
22231124}
22241125
22251126test "float.scientific" {
......@@ -2351,13 +1252,7 @@ test "custom" {
23511252 x: f32,
23521253 y: f32,
23531254
2354 pub fn format(
2355 self: SelfType,
2356 comptime fmt: []const u8,
2357 options: FormatOptions,
2358 writer: anytype,
2359 ) !void {
2360 _ = options;
1255 pub fn format(self: SelfType, writer: *Writer, comptime fmt: []const u8) Writer.Error!void {
23611256 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
23621257 return std.fmt.format(writer, "({d:.3},{d:.3})", .{ self.x, self.y });
23631258 } else if (comptime std.mem.eql(u8, fmt, "d")) {
......@@ -2368,16 +1263,16 @@ test "custom" {
23681263 }
23691264 };
23701265
2371 var value = Vec2{
1266 var value: Vec2 = .{
23721267 .x = 10.2,
23731268 .y = 2.22,
23741269 };
2375 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
2376 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
1270 try expectFmt("point: (10.200,2.220)\n", "point: {f}\n", .{&value});
1271 try expectFmt("dim: 10.200x2.220\n", "dim: {fd}\n", .{&value});
23771272
23781273 // same thing but not passing a pointer
2379 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
2380 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
1274 try expectFmt("point: (10.200,2.220)\n", "point: {f}\n", .{value});
1275 try expectFmt("dim: 10.200x2.220\n", "dim: {fd}\n", .{value});
23811276}
23821277
23831278test "union" {
......@@ -2439,17 +1334,6 @@ test "struct.zero-size" {
24391334 try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b});
24401335}
24411336
2442test "bytes.hex" {
2443 const some_bytes = "\xCA\xFE\xBA\xBE";
2444 try expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{fmtSliceHexLower(some_bytes)});
2445 try expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{fmtSliceHexUpper(some_bytes)});
2446 //Test Slices
2447 try expectFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{fmtSliceHexUpper(some_bytes[0..2])});
2448 try expectFmt("lowercase: babe\n", "lowercase: {x}\n", .{fmtSliceHexLower(some_bytes[2..])});
2449 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
2450 try expectFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{fmtSliceHexLower(bytes_with_zeros)});
2451}
2452
24531337/// Encodes a sequence of bytes as hexadecimal digits.
24541338/// Returns an array containing the encoded bytes.
24551339pub fn bytesToHex(input: anytype, case: Case) [input.len * 2]u8 {
......@@ -2494,110 +1378,14 @@ test bytesToHex {
24941378
24951379test hexToBytes {
24961380 var buf: [32]u8 = undefined;
2497 try expectFmt("90" ** 32, "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "90" ** 32))});
2498 try expectFmt("ABCD", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "ABCD"))});
2499 try expectFmt("", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, ""))});
1381 try expectFmt("90" ** 32, "{X}", .{try hexToBytes(&buf, "90" ** 32)});
1382 try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")});
1383 try expectFmt("", "{X}", .{try hexToBytes(&buf, "")});
25001384 try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));
25011385 try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));
25021386 try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));
25031387}
25041388
2505test "formatIntValue with comptime_int" {
2506 const value: comptime_int = 123456789123456789;
2507
2508 var buf: [20]u8 = undefined;
2509 var fbs = std.io.fixedBufferStream(&buf);
2510 try formatIntValue(value, "", FormatOptions{}, fbs.writer());
2511 try std.testing.expectEqualStrings("123456789123456789", fbs.getWritten());
2512}
2513
2514test "formatFloatValue with comptime_float" {
2515 const value: comptime_float = 1.0;
2516
2517 var buf: [20]u8 = undefined;
2518 var fbs = std.io.fixedBufferStream(&buf);
2519 try formatFloatValue(value, "", FormatOptions{}, fbs.writer());
2520 try std.testing.expectEqualStrings(fbs.getWritten(), "1e0");
2521
2522 try expectFmt("1e0", "{}", .{value});
2523 try expectFmt("1e0", "{}", .{1.0});
2524}
2525
2526test "formatType max_depth" {
2527 const Vec2 = struct {
2528 const SelfType = @This();
2529 x: f32,
2530 y: f32,
2531
2532 pub fn format(
2533 self: SelfType,
2534 comptime fmt: []const u8,
2535 options: FormatOptions,
2536 writer: anytype,
2537 ) !void {
2538 _ = options;
2539 if (fmt.len == 0) {
2540 return std.fmt.format(writer, "({d:.3},{d:.3})", .{ self.x, self.y });
2541 } else {
2542 @compileError("unknown format string: '" ++ fmt ++ "'");
2543 }
2544 }
2545 };
2546 const E = enum {
2547 One,
2548 Two,
2549 Three,
2550 };
2551 const TU = union(enum) {
2552 const SelfType = @This();
2553 float: f32,
2554 int: u32,
2555 ptr: ?*SelfType,
2556 };
2557 const S = struct {
2558 const SelfType = @This();
2559 a: ?*SelfType,
2560 tu: TU,
2561 e: E,
2562 vec: Vec2,
2563 };
2564
2565 var inst = S{
2566 .a = null,
2567 .tu = TU{ .ptr = null },
2568 .e = E.Two,
2569 .vec = Vec2{ .x = 10.2, .y = 2.22 },
2570 };
2571 inst.a = &inst;
2572 inst.tu.ptr = &inst.tu;
2573
2574 var buf: [1000]u8 = undefined;
2575 var fbs = std.io.fixedBufferStream(&buf);
2576 try formatType(inst, "", FormatOptions{}, fbs.writer(), 0);
2577 try std.testing.expectEqualStrings("fmt.test.formatType max_depth.S{ ... }", fbs.getWritten());
2578
2579 fbs.reset();
2580 try formatType(inst, "", FormatOptions{}, fbs.writer(), 1);
2581 try std.testing.expectEqualStrings("fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }", fbs.getWritten());
2582
2583 fbs.reset();
2584 try formatType(inst, "", FormatOptions{}, fbs.writer(), 2);
2585 try std.testing.expectEqualStrings("fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }", fbs.getWritten());
2586
2587 fbs.reset();
2588 try formatType(inst, "", FormatOptions{}, fbs.writer(), 3);
2589 try std.testing.expectEqualStrings("fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }", fbs.getWritten());
2590
2591 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
2592 fbs.reset();
2593 try formatType(vec, "", FormatOptions{}, fbs.writer(), 0);
2594 try std.testing.expectEqualStrings("{ ... }", fbs.getWritten());
2595
2596 fbs.reset();
2597 try formatType(vec, "", FormatOptions{}, fbs.writer(), 1);
2598 try std.testing.expectEqualStrings("{ 1, 2, 3, 4 }", fbs.getWritten());
2599}
2600
26011389test "positional" {
26021390 try expectFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
26031391 try expectFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
......@@ -2664,23 +1452,11 @@ test "padding" {
26641452 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});
26651453 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});
26661454 try expectFmt("-", "{s:-^1}", .{""});
2667 try expectFmt("==crêpe===", "{s:=^10}", .{"crêpe"});
2668 try expectFmt("=====crêpe", "{s:=>10}", .{"crêpe"});
2669 try expectFmt("crêpe=====", "{s:=<10}", .{"crêpe"});
26701455 try expectFmt("====a", "{c:=>5}", .{'a'});
26711456 try expectFmt("==a==", "{c:=^5}", .{'a'});
26721457 try expectFmt("a====", "{c:=<5}", .{'a'});
26731458}
26741459
2675test "padding fill char utf" {
2676 try expectFmt("──crêpe───", "{s:─^10}", .{"crêpe"});
2677 try expectFmt("─────crêpe", "{s:─>10}", .{"crêpe"});
2678 try expectFmt("crêpe─────", "{s:─<10}", .{"crêpe"});
2679 try expectFmt("────a", "{c:─>5}", .{'a'});
2680 try expectFmt("──a──", "{c:─^5}", .{'a'});
2681 try expectFmt("a────", "{c:─<5}", .{'a'});
2682}
2683
26841460test "decimal float padding" {
26851461 const number: f32 = 3.1415;
26861462 try expectFmt("left-pad: **3.142\n", "left-pad: {d:*>7.3}\n", .{number});
......@@ -2742,16 +1518,16 @@ test "recursive format function" {
27421518 Leaf: i32,
27431519 Branch: struct { left: *const R, right: *const R },
27441520
2745 pub fn format(self: R, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
1521 pub fn format(self: R, writer: *Writer, comptime _: []const u8) Writer.Error!void {
27461522 return switch (self) {
27471523 .Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}),
2748 .Branch => |b| std.fmt.format(writer, "Branch({}, {})", .{ b.left, b.right }),
1524 .Branch => |b| std.fmt.format(writer, "Branch({f}, {f})", .{ b.left, b.right }),
27491525 };
27501526 }
27511527 };
27521528
2753 var r = R{ .Leaf = 1 };
2754 try expectFmt("Leaf(1)\n", "{}\n", .{&r});
1529 var r: R = .{ .Leaf = 1 };
1530 try expectFmt("Leaf(1)\n", "{f}\n", .{&r});
27551531}
27561532
27571533pub const hex_charset = "0123456789abcdef";
......@@ -2785,54 +1561,39 @@ test hex {
27851561
27861562test "parser until" {
27871563 { // return substring till ':'
2788 var parser: Parser = .{
2789 .iter = .{ .bytes = "abc:1234", .i = 0 },
2790 };
1564 var parser: Parser = .{ .bytes = "abc:1234", .i = 0 };
27911565 try testing.expectEqualStrings("abc", parser.until(':'));
27921566 }
27931567
27941568 { // return the entire string - `ch` not found
2795 var parser: Parser = .{
2796 .iter = .{ .bytes = "abc1234", .i = 0 },
2797 };
1569 var parser: Parser = .{ .bytes = "abc1234", .i = 0 };
27981570 try testing.expectEqualStrings("abc1234", parser.until(':'));
27991571 }
28001572
28011573 { // substring is empty - `ch` is the only character
2802 var parser: Parser = .{
2803 .iter = .{ .bytes = ":", .i = 0 },
2804 };
1574 var parser: Parser = .{ .bytes = ":", .i = 0 };
28051575 try testing.expectEqualStrings("", parser.until(':'));
28061576 }
28071577
28081578 { // empty string and `ch` not found
2809 var parser: Parser = .{
2810 .iter = .{ .bytes = "", .i = 0 },
2811 };
1579 var parser: Parser = .{ .bytes = "", .i = 0 };
28121580 try testing.expectEqualStrings("", parser.until(':'));
28131581 }
28141582
28151583 { // substring starts at index 2 and goes upto `ch`
2816 var parser: Parser = .{
2817 .iter = .{ .bytes = "abc:1234", .i = 2 },
2818 };
1584 var parser: Parser = .{ .bytes = "abc:1234", .i = 2 };
28191585 try testing.expectEqualStrings("c", parser.until(':'));
28201586 }
28211587
28221588 { // substring starts at index 4 and goes upto the end - `ch` not found
2823 var parser: Parser = .{
2824 .iter = .{ .bytes = "abc1234", .i = 4 },
2825 };
1589 var parser: Parser = .{ .bytes = "abc1234", .i = 4 };
28261590 try testing.expectEqualStrings("234", parser.until(':'));
28271591 }
28281592}
28291593
28301594test "parser peek" {
28311595 { // start iteration from the first index
2832 var parser: Parser = .{
2833 .iter = .{ .bytes = "hello world", .i = 0 },
2834 };
2835
1596 var parser: Parser = .{ .bytes = "hello world", .i = 0 };
28361597 try testing.expectEqual('h', parser.peek(0));
28371598 try testing.expectEqual('e', parser.peek(1));
28381599 try testing.expectEqual(' ', parser.peek(5));
......@@ -2841,9 +1602,7 @@ test "parser peek" {
28411602 }
28421603
28431604 { // start iteration from the second last index
2844 var parser: Parser = .{
2845 .iter = .{ .bytes = "hello world!", .i = 10 },
2846 };
1605 var parser: Parser = .{ .bytes = "hello world!", .i = 10 };
28471606
28481607 try testing.expectEqual('d', parser.peek(0));
28491608 try testing.expectEqual('!', parser.peek(1));
......@@ -2851,18 +1610,14 @@ test "parser peek" {
28511610 }
28521611
28531612 { // start iteration beyond the length of the string
2854 var parser: Parser = .{
2855 .iter = .{ .bytes = "hello", .i = 5 },
2856 };
1613 var parser: Parser = .{ .bytes = "hello", .i = 5 };
28571614
28581615 try testing.expectEqual(null, parser.peek(0));
28591616 try testing.expectEqual(null, parser.peek(1));
28601617 }
28611618
28621619 { // empty string
2863 var parser: Parser = .{
2864 .iter = .{ .bytes = "", .i = 0 },
2865 };
1620 var parser: Parser = .{ .bytes = "", .i = 0 };
28661621
28671622 try testing.expectEqual(null, parser.peek(0));
28681623 try testing.expectEqual(null, parser.peek(2));
......@@ -2871,78 +1626,78 @@ test "parser peek" {
28711626
28721627test "parser char" {
28731628 // character exists - iterator at 0
2874 var parser: Parser = .{ .iter = .{ .bytes = "~~hello", .i = 0 } };
1629 var parser: Parser = .{ .bytes = "~~hello", .i = 0 };
28751630 try testing.expectEqual('~', parser.char());
28761631
28771632 // character exists - iterator in the middle
2878 parser = .{ .iter = .{ .bytes = "~~hello", .i = 3 } };
1633 parser = .{ .bytes = "~~hello", .i = 3 };
28791634 try testing.expectEqual('e', parser.char());
28801635
28811636 // character exists - iterator at the end
2882 parser = .{ .iter = .{ .bytes = "~~hello", .i = 6 } };
1637 parser = .{ .bytes = "~~hello", .i = 6 };
28831638 try testing.expectEqual('o', parser.char());
28841639
28851640 // character doesn't exist - iterator beyond the length of the string
2886 parser = .{ .iter = .{ .bytes = "~~hello", .i = 7 } };
1641 parser = .{ .bytes = "~~hello", .i = 7 };
28871642 try testing.expectEqual(null, parser.char());
28881643}
28891644
28901645test "parser maybe" {
28911646 // character exists - iterator at 0
2892 var parser: Parser = .{ .iter = .{ .bytes = "hello world", .i = 0 } };
1647 var parser: Parser = .{ .bytes = "hello world", .i = 0 };
28931648 try testing.expect(parser.maybe('h'));
28941649
28951650 // character exists - iterator at space
2896 parser = .{ .iter = .{ .bytes = "hello world", .i = 5 } };
1651 parser = .{ .bytes = "hello world", .i = 5 };
28971652 try testing.expect(parser.maybe(' '));
28981653
28991654 // character exists - iterator at the end
2900 parser = .{ .iter = .{ .bytes = "hello world", .i = 10 } };
1655 parser = .{ .bytes = "hello world", .i = 10 };
29011656 try testing.expect(parser.maybe('d'));
29021657
29031658 // character doesn't exist - iterator beyond the length of the string
2904 parser = .{ .iter = .{ .bytes = "hello world", .i = 11 } };
1659 parser = .{ .bytes = "hello world", .i = 11 };
29051660 try testing.expect(!parser.maybe('e'));
29061661}
29071662
29081663test "parser number" {
29091664 // input is a single digit natural number - iterator at 0
2910 var parser: Parser = .{ .iter = .{ .bytes = "7", .i = 0 } };
1665 var parser: Parser = .{ .bytes = "7", .i = 0 };
29111666 try testing.expect(7 == parser.number());
29121667
29131668 // input is a two digit natural number - iterator at 1
2914 parser = .{ .iter = .{ .bytes = "29", .i = 1 } };
1669 parser = .{ .bytes = "29", .i = 1 };
29151670 try testing.expect(9 == parser.number());
29161671
29171672 // input is a two digit natural number - iterator beyond the length of the string
2918 parser = .{ .iter = .{ .bytes = "32", .i = 2 } };
1673 parser = .{ .bytes = "32", .i = 2 };
29191674 try testing.expectEqual(null, parser.number());
29201675
29211676 // input is an integer
2922 parser = .{ .iter = .{ .bytes = "0", .i = 0 } };
1677 parser = .{ .bytes = "0", .i = 0 };
29231678 try testing.expect(0 == parser.number());
29241679
29251680 // input is a negative integer
2926 parser = .{ .iter = .{ .bytes = "-2", .i = 0 } };
1681 parser = .{ .bytes = "-2", .i = 0 };
29271682 try testing.expectEqual(null, parser.number());
29281683
29291684 // input is a string
2930 parser = .{ .iter = .{ .bytes = "no_number", .i = 2 } };
1685 parser = .{ .bytes = "no_number", .i = 2 };
29311686 try testing.expectEqual(null, parser.number());
29321687
29331688 // input is a single character string
2934 parser = .{ .iter = .{ .bytes = "n", .i = 0 } };
1689 parser = .{ .bytes = "n", .i = 0 };
29351690 try testing.expectEqual(null, parser.number());
29361691
29371692 // input is an empty string
2938 parser = .{ .iter = .{ .bytes = "", .i = 0 } };
1693 parser = .{ .bytes = "", .i = 0 };
29391694 try testing.expectEqual(null, parser.number());
29401695}
29411696
29421697test "parser specifier" {
29431698 { // input string is a digit; iterator at 0
29441699 const expected: Specifier = Specifier{ .number = 1 };
2945 var parser: Parser = .{ .iter = .{ .bytes = "1", .i = 0 } };
1700 var parser: Parser = .{ .bytes = "1", .i = 0 };
29461701
29471702 const result = try parser.specifier();
29481703 try testing.expect(expected.number == result.number);
......@@ -2950,7 +1705,7 @@ test "parser specifier" {
29501705
29511706 { // input string is a two digit number; iterator at 0
29521707 const digit: Specifier = Specifier{ .number = 42 };
2953 var parser: Parser = .{ .iter = .{ .bytes = "42", .i = 0 } };
1708 var parser: Parser = .{ .bytes = "42", .i = 0 };
29541709
29551710 const result = try parser.specifier();
29561711 try testing.expect(digit.number == result.number);
......@@ -2958,7 +1713,7 @@ test "parser specifier" {
29581713
29591714 { // input string is a two digit number digit; iterator at 1
29601715 const digit: Specifier = Specifier{ .number = 8 };
2961 var parser: Parser = .{ .iter = .{ .bytes = "28", .i = 1 } };
1716 var parser: Parser = .{ .bytes = "28", .i = 1 };
29621717
29631718 const result = try parser.specifier();
29641719 try testing.expect(digit.number == result.number);
......@@ -2966,7 +1721,7 @@ test "parser specifier" {
29661721
29671722 { // input string is a two digit number with square brackets; iterator at 0
29681723 const digit: Specifier = Specifier{ .named = "15" };
2969 var parser: Parser = .{ .iter = .{ .bytes = "[15]", .i = 0 } };
1724 var parser: Parser = .{ .bytes = "[15]", .i = 0 };
29701725
29711726 const result = try parser.specifier();
29721727 try testing.expectEqualStrings(digit.named, result.named);
......@@ -2974,21 +1729,21 @@ test "parser specifier" {
29741729
29751730 { // input string is not a number and contains square brackets; iterator at 0
29761731 const digit: Specifier = Specifier{ .named = "hello" };
2977 var parser: Parser = .{ .iter = .{ .bytes = "[hello]", .i = 0 } };
1732 var parser: Parser = .{ .bytes = "[hello]", .i = 0 };
29781733
29791734 const result = try parser.specifier();
29801735 try testing.expectEqualStrings(digit.named, result.named);
29811736 }
29821737
29831738 { // input string is not a number and doesn't contain closing square bracket; iterator at 0
2984 var parser: Parser = .{ .iter = .{ .bytes = "[hello", .i = 0 } };
1739 var parser: Parser = .{ .bytes = "[hello", .i = 0 };
29851740
29861741 const result = parser.specifier();
29871742 try testing.expectError(@field(anyerror, "Expected closing ]"), result);
29881743 }
29891744
29901745 { // input string is not a number and doesn't contain closing square bracket; iterator at 2
2991 var parser: Parser = .{ .iter = .{ .bytes = "[[[[hello", .i = 2 } };
1746 var parser: Parser = .{ .bytes = "[[[[hello", .i = 2 };
29921747
29931748 const result = parser.specifier();
29941749 try testing.expectError(@field(anyerror, "Expected closing ]"), result);
......@@ -2996,7 +1751,7 @@ test "parser specifier" {
29961751
29971752 { // input string is not a number and contains unbalanced square brackets; iterator at 0
29981753 const digit: Specifier = Specifier{ .named = "[[hello" };
2999 var parser: Parser = .{ .iter = .{ .bytes = "[[[hello]", .i = 0 } };
1754 var parser: Parser = .{ .bytes = "[[[hello]", .i = 0 };
30001755
30011756 const result = try parser.specifier();
30021757 try testing.expectEqualStrings(digit.named, result.named);
......@@ -3004,7 +1759,7 @@ test "parser specifier" {
30041759
30051760 { // input string is not a number and contains unbalanced square brackets; iterator at 1
30061761 const digit: Specifier = Specifier{ .named = "[[hello" };
3007 var parser: Parser = .{ .iter = .{ .bytes = "[[[[hello]]]]]", .i = 1 } };
1762 var parser: Parser = .{ .bytes = "[[[[hello]]]]]", .i = 1 };
30081763
30091764 const result = try parser.specifier();
30101765 try testing.expectEqualStrings(digit.named, result.named);
......@@ -3012,9 +1767,13 @@ test "parser specifier" {
30121767
30131768 { // input string is neither a digit nor a named argument
30141769 const char: Specifier = Specifier{ .none = {} };
3015 var parser: Parser = .{ .iter = .{ .bytes = "hello", .i = 0 } };
1770 var parser: Parser = .{ .bytes = "hello", .i = 0 };
30161771
30171772 const result = try parser.specifier();
30181773 try testing.expectEqual(char.none, result.none);
30191774 }
30201775}
1776
1777test {
1778 _ = float;
1779}
lib/std/fmt/float.zig created+1695
......@@ -0,0 +1,1695 @@
1//! This file implements the ryu floating point conversion algorithm:
2//! https://dl.acm.org/doi/pdf/10.1145/3360595
3
4const std = @import("std");
5const expectFmt = std.testing.expectFmt;
6
7const special_exponent = 0x7fffffff;
8
9/// Any buffer used for `format` must be at least this large. This is asserted. A runtime check will
10/// additionally be performed if more bytes are required.
11pub const min_buffer_size = 53;
12
13/// Returns the minimum buffer size needed to print every float of a specific type and format.
14pub fn bufferSize(comptime mode: Mode, comptime T: type) comptime_int {
15 comptime std.debug.assert(@typeInfo(T) == .float);
16 return switch (mode) {
17 .scientific => 53,
18 // Based on minimum subnormal values.
19 .decimal => switch (@bitSizeOf(T)) {
20 16 => @max(15, min_buffer_size),
21 32 => 55,
22 64 => 347,
23 80 => 4996,
24 128 => 5011,
25 else => unreachable,
26 },
27 };
28}
29
30pub const Error = error{
31 BufferTooSmall,
32};
33
34pub const Mode = enum {
35 scientific,
36 decimal,
37};
38
39pub const Options = struct {
40 mode: Mode = .scientific,
41 precision: ?usize = null,
42};
43
44/// Format a floating-point value and write it to buffer. Returns a slice to the buffer containing
45/// the string representation.
46///
47/// Full precision is the default. Any full precision float can be reparsed with std.fmt.parseFloat
48/// unambiguously.
49///
50/// Scientific mode is recommended generally as the output is more compact and any type can be
51/// written in full precision using a buffer of only `min_buffer_size`.
52///
53/// When printing full precision decimals, use `bufferSize` to get the required space. It is
54/// recommended to bound decimal output with a fixed precision to reduce the required buffer size.
55pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
56 const v = switch (@TypeOf(value)) {
57 // comptime_float internally is a f128; this preserves precision.
58 comptime_float => @as(f128, value),
59 else => value,
60 };
61
62 const T = @TypeOf(v);
63 comptime std.debug.assert(@typeInfo(T) == .float);
64 const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
65
66 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
67 const tables = switch (DT) {
68 u64 => if (@import("builtin").mode == .ReleaseSmall) &Backend64_TablesSmall else &Backend64_TablesFull,
69 u128 => &Backend128_Tables,
70 else => unreachable,
71 };
72
73 const has_explicit_leading_bit = std.math.floatMantissaBits(T) - std.math.floatFractionalBits(T) != 0;
74 const d = binaryToDecimal(DT, @as(I, @bitCast(v)), std.math.floatMantissaBits(T), std.math.floatExponentBits(T), has_explicit_leading_bit, tables);
75
76 return switch (options.mode) {
77 .scientific => formatScientific(DT, buf, d, options.precision),
78 .decimal => formatDecimal(DT, buf, d, options.precision),
79 };
80}
81
82pub fn FloatDecimal(comptime T: type) type {
83 comptime std.debug.assert(T == u64 or T == u128);
84 return struct {
85 mantissa: T,
86 exponent: i32,
87 sign: bool,
88 };
89}
90
91fn copySpecialStr(buf: []u8, f: anytype) []const u8 {
92 if (f.sign) {
93 buf[0] = '-';
94 }
95 const offset: usize = @intFromBool(f.sign);
96 if (f.mantissa != 0) {
97 @memcpy(buf[offset..][0..3], "nan");
98 return buf[0 .. 3 + offset];
99 }
100 @memcpy(buf[offset..][0..3], "inf");
101 return buf[0 .. 3 + offset];
102}
103
104fn writeDecimal(buf: []u8, value: anytype, count: usize) void {
105 var i: usize = 0;
106
107 while (i + 2 < count) : (i += 2) {
108 const c: u8 = @intCast(value.* % 100);
109 value.* /= 100;
110 const d = std.fmt.digits2(c);
111 buf[count - i - 1] = d[1];
112 buf[count - i - 2] = d[0];
113 }
114
115 while (i < count) : (i += 1) {
116 const c: u8 = @intCast(value.* % 10);
117 value.* /= 10;
118 buf[count - i - 1] = '0' + c;
119 }
120}
121
122fn isPowerOf10(n_: u128) bool {
123 var n = n_;
124 while (n != 0) : (n /= 10) {
125 if (n % 10 != 0) return false;
126 }
127 return true;
128}
129
130const RoundMode = enum {
131 /// 1234.56 = precision 2
132 decimal,
133 /// 1.23456e3 = precision 5
134 scientific,
135};
136
137fn round(comptime T: type, f: FloatDecimal(T), mode: RoundMode, precision: usize) FloatDecimal(T) {
138 var round_digit: usize = 0;
139 var output = f.mantissa;
140 var exp = f.exponent;
141 const olength = decimalLength(output);
142
143 switch (mode) {
144 .decimal => {
145 if (f.exponent > 0) {
146 round_digit = (olength - 1) + precision + @as(usize, @intCast(f.exponent));
147 } else {
148 const min_exp_required = @as(usize, @intCast(-f.exponent));
149 if (precision + olength > min_exp_required) {
150 round_digit = precision + olength - min_exp_required;
151 }
152 }
153 },
154 .scientific => {
155 round_digit = 1 + precision;
156 },
157 }
158
159 if (round_digit < olength) {
160 var nlength = olength;
161 for (round_digit + 1..olength) |_| {
162 output /= 10;
163 exp += 1;
164 nlength -= 1;
165 }
166
167 if (output % 10 >= 5) {
168 output /= 10;
169 output += 1;
170 exp += 1;
171
172 // e.g. 9999 -> 10000
173 if (isPowerOf10(output)) {
174 output /= 10;
175 exp += 1;
176 }
177 }
178 }
179
180 return .{
181 .mantissa = output,
182 .exponent = exp,
183 .sign = f.sign,
184 };
185}
186
187/// Write a FloatDecimal to a buffer in scientific form.
188///
189/// The buffer provided must be greater than `min_buffer_size` in length. If no precision is
190/// specified, this function will never return an error. If a precision is specified, up to
191/// `8 + precision` bytes will be written to the buffer. An error will be returned if the content
192/// will not fit.
193///
194/// It is recommended to bound decimal formatting with an exact precision.
195pub fn formatScientific(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) Error![]const u8 {
196 std.debug.assert(buf.len >= min_buffer_size);
197 var f = f_;
198
199 if (f.exponent == special_exponent) {
200 return copySpecialStr(buf, f);
201 }
202
203 if (precision) |prec| {
204 f = round(T, f, .scientific, prec);
205 }
206
207 var output = f.mantissa;
208 const olength = decimalLength(output);
209
210 if (precision) |prec| {
211 // fixed bound: sign(1) + leading_digit(1) + point(1) + exp_sign(1) + exp_max(4)
212 const req_bytes = 8 + prec;
213 if (buf.len < req_bytes) {
214 return error.BufferTooSmall;
215 }
216 }
217
218 // Step 5: Print the scientific representation
219 var index: usize = 0;
220 if (f.sign) {
221 buf[index] = '-';
222 index += 1;
223 }
224
225 // 1.12345
226 writeDecimal(buf[index + 2 ..], &output, olength - 1);
227 buf[index] = '0' + @as(u8, @intCast(output % 10));
228 buf[index + 1] = '.';
229 index += 2;
230 const dp_index = index;
231 if (olength > 1) index += olength - 1 else index -= 1;
232
233 if (precision) |prec| {
234 index += @intFromBool(olength == 1);
235 if (prec > olength - 1) {
236 const len = prec - (olength - 1);
237 @memset(buf[index..][0..len], '0');
238 index += len;
239 } else {
240 index = dp_index + prec - @intFromBool(prec == 0);
241 }
242 }
243
244 // e100
245 buf[index] = 'e';
246 index += 1;
247 var exp = f.exponent + @as(i32, @intCast(olength)) - 1;
248 if (exp < 0) {
249 buf[index] = '-';
250 index += 1;
251 exp = -exp;
252 }
253 var uexp: u32 = @intCast(exp);
254 const elength = decimalLength(uexp);
255 writeDecimal(buf[index..], &uexp, elength);
256 index += elength;
257
258 return buf[0..index];
259}
260
261/// Write a FloatDecimal to a buffer in decimal form.
262///
263/// The buffer provided must be greater than `min_buffer_size` bytes in length. If no precision is
264/// specified, this may still return an error. If precision is specified, `2 + precision` bytes will
265/// always be written.
266pub fn formatDecimal(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) Error![]const u8 {
267 std.debug.assert(buf.len >= min_buffer_size);
268 var f = f_;
269
270 if (f.exponent == special_exponent) {
271 return copySpecialStr(buf, f);
272 }
273
274 if (precision) |prec| {
275 f = round(T, f, .decimal, prec);
276 }
277
278 var output = f.mantissa;
279 const olength = decimalLength(output);
280
281 // fixed bound: leading_digit(1) + point(1)
282 const req_bytes = if (f.exponent >= 0)
283 @as(usize, 2) + @abs(f.exponent) + olength + (precision orelse 0)
284 else
285 @as(usize, 2) + @max(@abs(f.exponent) + olength, precision orelse 0);
286 if (buf.len < req_bytes) {
287 return error.BufferTooSmall;
288 }
289
290 // Step 5: Print the decimal representation
291 var index: usize = 0;
292 if (f.sign) {
293 buf[index] = '-';
294 index += 1;
295 }
296
297 const dp_offset = f.exponent + cast_i32(olength);
298 if (dp_offset <= 0) {
299 // 0.000001234
300 buf[index] = '0';
301 buf[index + 1] = '.';
302 index += 2;
303 const dp_index = index;
304
305 const dp_poffset: u32 = @intCast(-dp_offset);
306 @memset(buf[index..][0..dp_poffset], '0');
307 index += dp_poffset;
308 writeDecimal(buf[index..], &output, olength);
309 index += olength;
310
311 if (precision) |prec| {
312 const dp_written = index - dp_index;
313 if (prec > dp_written) {
314 @memset(buf[index..][0 .. prec - dp_written], '0');
315 }
316 index = dp_index + prec - @intFromBool(prec == 0);
317 }
318 } else {
319 // 123456000
320 const dp_uoffset: usize = @intCast(dp_offset);
321 if (dp_uoffset >= olength) {
322 writeDecimal(buf[index..], &output, olength);
323 index += olength;
324 @memset(buf[index..][0 .. dp_uoffset - olength], '0');
325 index += dp_uoffset - olength;
326
327 if (precision) |prec| {
328 if (prec != 0) {
329 buf[index] = '.';
330 index += 1;
331 @memset(buf[index..][0..prec], '0');
332 index += prec;
333 }
334 }
335 } else {
336 // 12345.6789
337 writeDecimal(buf[index + dp_uoffset + 1 ..], &output, olength - dp_uoffset);
338 buf[index + dp_uoffset] = '.';
339 const dp_index = index + dp_uoffset + 1;
340 writeDecimal(buf[index..], &output, dp_uoffset);
341 index += olength + 1;
342
343 if (precision) |prec| {
344 const dp_written = olength - dp_uoffset;
345 if (prec > dp_written) {
346 @memset(buf[index..][0 .. prec - dp_written], '0');
347 }
348 index = dp_index + prec - @intFromBool(prec == 0);
349 }
350 }
351 }
352
353 return buf[0..index];
354}
355
356fn cast_i32(v: anytype) i32 {
357 return @intCast(v);
358}
359
360/// Convert a binary float representation to decimal.
361pub fn binaryToDecimal(comptime T: type, bits: T, mantissa_bits: std.math.Log2Int(T), exponent_bits: u5, explicit_leading_bit: bool, comptime tables: anytype) FloatDecimal(T) {
362 if (T != tables.T) {
363 @compileError("table type does not match backend type: " ++ @typeName(tables.T) ++ " != " ++ @typeName(T));
364 }
365
366 const bias = (@as(u32, 1) << (exponent_bits - 1)) - 1;
367 const ieee_sign = ((bits >> (mantissa_bits + exponent_bits)) & 1) != 0;
368 const ieee_mantissa = bits & ((@as(T, 1) << mantissa_bits) - 1);
369 const ieee_exponent: u32 = @intCast((bits >> mantissa_bits) & ((@as(T, 1) << exponent_bits) - 1));
370
371 if (ieee_exponent == 0 and ieee_mantissa == 0) {
372 return .{
373 .mantissa = 0,
374 .exponent = 0,
375 .sign = ieee_sign,
376 };
377 }
378 if (ieee_exponent == ((@as(u32, 1) << exponent_bits) - 1)) {
379 return .{
380 .mantissa = if (explicit_leading_bit) ieee_mantissa & ((@as(T, 1) << (mantissa_bits - 1)) - 1) else ieee_mantissa,
381 .exponent = special_exponent,
382 .sign = ieee_sign,
383 };
384 }
385
386 var e2: i32 = undefined;
387 var m2: T = undefined;
388 if (explicit_leading_bit) {
389 if (ieee_exponent == 0) {
390 e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2;
391 } else {
392 e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2;
393 }
394 m2 = ieee_mantissa;
395 } else {
396 if (ieee_exponent == 0) {
397 e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) - 2;
398 m2 = ieee_mantissa;
399 } else {
400 e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) - 2;
401 m2 = (@as(T, 1) << mantissa_bits) | ieee_mantissa;
402 }
403 }
404 const even = (m2 & 1) == 0;
405 const accept_bounds = even;
406
407 // Step 2: Determine the interval of legal decimal representations.
408 const mv = 4 * m2;
409 const mm_shift: u1 = @intFromBool((ieee_mantissa != if (explicit_leading_bit) (@as(T, 1) << (mantissa_bits - 1)) else 0) or (ieee_exponent == 0));
410
411 // Step 3: Convert to a decimal power base using 128-bit arithmetic.
412 var vr: T = undefined;
413 var vp: T = undefined;
414 var vm: T = undefined;
415 var e10: i32 = undefined;
416 var vm_is_trailing_zeros = false;
417 var vr_is_trailing_zeros = false;
418 if (e2 >= 0) {
419 const q: u32 = log10Pow2(@intCast(e2)) - @intFromBool(e2 > 3);
420 e10 = cast_i32(q);
421 const k: i32 = @intCast(tables.POW5_INV_BITCOUNT + pow5Bits(q) - 1);
422 const i: u32 = @intCast(-e2 + cast_i32(q) + k);
423
424 const pow5 = tables.computeInvPow5(q);
425 vr = tables.mulShift(4 * m2, &pow5, i);
426 vp = tables.mulShift(4 * m2 + 2, &pow5, i);
427 vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, i);
428
429 if (q <= tables.bound1) {
430 if (mv % 5 == 0) {
431 vr_is_trailing_zeros = multipleOfPowerOf5(mv, if (tables.adjust_q) q -% 1 else q);
432 } else if (accept_bounds) {
433 vm_is_trailing_zeros = multipleOfPowerOf5(mv - 1 - mm_shift, q);
434 } else {
435 vp -= @intFromBool(multipleOfPowerOf5(mv + 2, q));
436 }
437 }
438 } else {
439 const q: u32 = log10Pow5(@intCast(-e2)) - @intFromBool(-e2 > 1);
440 e10 = cast_i32(q) + e2;
441 const i: i32 = -e2 - cast_i32(q);
442 const k: i32 = cast_i32(pow5Bits(@intCast(i))) - tables.POW5_BITCOUNT;
443 const j: u32 = @intCast(cast_i32(q) - k);
444
445 const pow5 = tables.computePow5(@intCast(i));
446 vr = tables.mulShift(4 * m2, &pow5, j);
447 vp = tables.mulShift(4 * m2 + 2, &pow5, j);
448 vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, j);
449
450 if (q <= 1) {
451 vr_is_trailing_zeros = true;
452 if (accept_bounds) {
453 vm_is_trailing_zeros = mm_shift == 1;
454 } else {
455 vp -= 1;
456 }
457 } else if (q < tables.bound2) {
458 vr_is_trailing_zeros = multipleOfPowerOf2(mv, if (tables.adjust_q) q - 1 else q);
459 }
460 }
461
462 // Step 4: Find the shortest decimal representation in the interval of legal representations.
463 var removed: u32 = 0;
464 var last_removed_digit: u8 = 0;
465
466 while (vp / 10 > vm / 10) {
467 vm_is_trailing_zeros = vm_is_trailing_zeros and vm % 10 == 0;
468 vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0;
469 last_removed_digit = @intCast(vr % 10);
470 vr /= 10;
471 vp /= 10;
472 vm /= 10;
473 removed += 1;
474 }
475
476 if (vm_is_trailing_zeros) {
477 while (vm % 10 == 0) {
478 vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0;
479 last_removed_digit = @intCast(vr % 10);
480 vr /= 10;
481 vp /= 10;
482 vm /= 10;
483 removed += 1;
484 }
485 }
486
487 if (vr_is_trailing_zeros and (last_removed_digit == 5) and (vr % 2 == 0)) {
488 last_removed_digit = 4;
489 }
490
491 return .{
492 .mantissa = vr + @intFromBool((vr == vm and (!accept_bounds or !vm_is_trailing_zeros)) or last_removed_digit >= 5),
493 .exponent = e10 + cast_i32(removed),
494 .sign = ieee_sign,
495 };
496}
497
498fn decimalLength(v: anytype) u32 {
499 switch (@TypeOf(v)) {
500 u32, u64 => {
501 std.debug.assert(v < 100000000000000000);
502 if (v >= 10000000000000000) return 17;
503 if (v >= 1000000000000000) return 16;
504 if (v >= 100000000000000) return 15;
505 if (v >= 10000000000000) return 14;
506 if (v >= 1000000000000) return 13;
507 if (v >= 100000000000) return 12;
508 if (v >= 10000000000) return 11;
509 if (v >= 1000000000) return 10;
510 if (v >= 100000000) return 9;
511 if (v >= 10000000) return 8;
512 if (v >= 1000000) return 7;
513 if (v >= 100000) return 6;
514 if (v >= 10000) return 5;
515 if (v >= 1000) return 4;
516 if (v >= 100) return 3;
517 if (v >= 10) return 2;
518 return 1;
519 },
520 u128 => {
521 const LARGEST_POW10 = (@as(u128, 5421010862427522170) << 64) | 687399551400673280;
522 var p10 = LARGEST_POW10;
523 var i: u32 = 39;
524 while (i > 0) : (i -= 1) {
525 if (v >= p10) return i;
526 p10 /= 10;
527 }
528 return 1;
529 },
530 else => unreachable,
531 }
532}
533
534// floor(log_10(2^e))
535fn log10Pow2(e: u32) u32 {
536 std.debug.assert(e <= 1 << 15);
537 return @intCast((@as(u64, @intCast(e)) * 169464822037455) >> 49);
538}
539
540// floor(log_10(5^e))
541fn log10Pow5(e: u32) u32 {
542 std.debug.assert(e <= 1 << 15);
543 return @intCast((@as(u64, @intCast(e)) * 196742565691928) >> 48);
544}
545
546// if (e == 0) 1 else ceil(log_2(5^e))
547fn pow5Bits(e: u32) u32 {
548 std.debug.assert(e <= 1 << 15);
549 return @intCast(((@as(u64, @intCast(e)) * 163391164108059) >> 46) + 1);
550}
551
552fn pow5Factor(value_: anytype) u32 {
553 var count: u32 = 0;
554 var value = value_;
555 while (value > 0) : ({
556 count += 1;
557 value /= 5;
558 }) {
559 if (value % 5 != 0) return count;
560 }
561 return 0;
562}
563
564fn multipleOfPowerOf5(value: anytype, p: u32) bool {
565 const T = @TypeOf(value);
566 std.debug.assert(@typeInfo(T) == .int);
567 return pow5Factor(value) >= p;
568}
569
570fn multipleOfPowerOf2(value: anytype, p: u32) bool {
571 const T = @TypeOf(value);
572 std.debug.assert(@typeInfo(T) == .int);
573 return (value & ((@as(T, 1) << @as(std.math.Log2Int(T), @intCast(p))) - 1)) == 0;
574}
575
576fn mulShift128(m: u128, mul: *const [4]u64, j: u32) u128 {
577 std.debug.assert(j > 128);
578 const a: [2]u64 = .{ @truncate(m), @truncate(m >> 64) };
579 const r = mul_128_256_shift(&a, mul, j, 0);
580 return (@as(u128, r[1]) << 64) | r[0];
581}
582
583fn mul_128_256_shift(a: *const [2]u64, b: *const [4]u64, shift: u32, corr: u32) [4]u64 {
584 std.debug.assert(shift > 0);
585 std.debug.assert(shift < 256);
586
587 const b00 = @as(u128, a[0]) * b[0];
588 const b01 = @as(u128, a[0]) * b[1];
589 const b02 = @as(u128, a[0]) * b[2];
590 const b03 = @as(u128, a[0]) * b[3];
591 const b10 = @as(u128, a[1]) * b[0];
592 const b11 = @as(u128, a[1]) * b[1];
593 const b12 = @as(u128, a[1]) * b[2];
594 const b13 = @as(u128, a[1]) * b[3];
595
596 const s0 = b00;
597 const s1 = b01 +% b10;
598 const c1: u128 = @intFromBool(s1 < b01);
599 const s2 = b02 +% b11;
600 const c2: u128 = @intFromBool(s2 < b02);
601 const s3 = b03 +% b12;
602 const c3: u128 = @intFromBool(s3 < b03);
603
604 const p0 = s0 +% (s1 << 64);
605 const d0: u128 = @intFromBool(p0 < b00);
606 const q1 = s2 +% (s1 >> 64) +% (s3 << 64);
607 const d1: u128 = @intFromBool(q1 < s2);
608 const p1 = q1 +% (c1 << 64) +% d0;
609 const d2: u128 = @intFromBool(p1 < q1);
610 const p2 = b13 +% (s3 >> 64) +% c2 +% (c3 << 64) +% d1 +% d2;
611
612 var r0: u128 = undefined;
613 var r1: u128 = undefined;
614 if (shift < 128) {
615 const cshift: u7 = @intCast(shift);
616 const sshift: u7 = @intCast(128 - shift);
617 r0 = corr +% ((p0 >> cshift) | (p1 << sshift));
618 r1 = ((p1 >> cshift) | (p2 << sshift)) +% @intFromBool(r0 < corr);
619 } else if (shift == 128) {
620 r0 = corr +% p1;
621 r1 = p2 +% @intFromBool(r0 < corr);
622 } else {
623 const ashift: u7 = @intCast(shift - 128);
624 const sshift: u7 = @intCast(256 - shift);
625 r0 = corr +% ((p1 >> ashift) | (p2 << sshift));
626 r1 = (p2 >> ashift) +% @intFromBool(r0 < corr);
627 }
628
629 return .{ @truncate(r0), @truncate(r0 >> 64), @truncate(r1), @truncate(r1 >> 64) };
630}
631
632pub const Backend128_Tables = struct {
633 const T = u128;
634 const mulShift = mulShift128;
635 const POW5_INV_BITCOUNT = FLOAT128_POW5_INV_BITCOUNT;
636 const POW5_BITCOUNT = FLOAT128_POW5_BITCOUNT;
637
638 const bound1 = 55;
639 const bound2 = 127;
640 const adjust_q = true;
641
642 fn computePow5(i: u32) [4]u64 {
643 const base = i / FLOAT128_POW5_TABLE_SIZE;
644 const base2 = base * FLOAT128_POW5_TABLE_SIZE;
645 const mul = &FLOAT128_POW5_SPLIT[base];
646 if (i == base2) {
647 return mul.*;
648 } else {
649 const offset = i - base2;
650 const m = &FLOAT128_POW5_TABLE[offset];
651 const delta = pow5Bits(i) - pow5Bits(base2);
652
653 const shift: u6 = @intCast(2 * (i % 32));
654 const corr: u32 = @intCast((FLOAT128_POW5_ERRORS[i / 32] >> shift) & 3);
655 return mul_128_256_shift(m, mul, delta, corr);
656 }
657 }
658
659 fn computeInvPow5(i: u32) [4]u64 {
660 const base = (i + FLOAT128_POW5_TABLE_SIZE - 1) / FLOAT128_POW5_TABLE_SIZE;
661 const base2 = base * FLOAT128_POW5_TABLE_SIZE;
662 const mul = &FLOAT128_POW5_INV_SPLIT[base]; // 1 / 5^base2
663 if (i == base2) {
664 return .{ mul[0] + 1, mul[1], mul[2], mul[3] };
665 } else {
666 const offset = base2 - i;
667 const m = &FLOAT128_POW5_TABLE[offset]; // 5^offset
668 const delta = pow5Bits(base2) - pow5Bits(i);
669
670 const shift: u6 = @intCast(2 * (i % 32));
671 const corr: u32 = @intCast(((FLOAT128_POW5_INV_ERRORS[i / 32] >> shift) & 3) + 1);
672 return mul_128_256_shift(m, mul, delta, corr);
673 }
674 }
675};
676
677fn mulShift64(m: u64, mul: *const [2]u64, j: u32) u64 {
678 std.debug.assert(j > 64);
679 const b0 = @as(u128, m) * mul[0];
680 const b2 = @as(u128, m) * mul[1];
681
682 if (j < 128) {
683 const shift: u6 = @intCast(j - 64);
684 return @intCast(((b0 >> 64) + b2) >> shift);
685 } else {
686 return 0;
687 }
688}
689
690pub const Backend64_TablesFull = struct {
691 const T = u64;
692 const mulShift = mulShift64;
693 const POW5_INV_BITCOUNT = FLOAT64_POW5_INV_BITCOUNT;
694 const POW5_BITCOUNT = FLOAT64_POW5_BITCOUNT;
695
696 const bound1 = 21;
697 const bound2 = 63;
698 const adjust_q = false;
699
700 fn computePow5(i: u32) [2]u64 {
701 return FLOAT64_POW5_SPLIT[i];
702 }
703
704 fn computeInvPow5(i: u32) [2]u64 {
705 return FLOAT64_POW5_INV_SPLIT[i];
706 }
707};
708
709pub const Backend64_TablesSmall = struct {
710 const T = u64;
711 const mulShift = mulShift64;
712 const POW5_INV_BITCOUNT = FLOAT64_POW5_INV_BITCOUNT;
713 const POW5_BITCOUNT = FLOAT64_POW5_BITCOUNT;
714
715 const bound1 = 21;
716 const bound2 = 63;
717 const adjust_q = false;
718
719 fn computePow5(i: u32) [2]u64 {
720 const base = i / FLOAT64_POW5_TABLE_SIZE;
721 const base2 = base * FLOAT64_POW5_TABLE_SIZE;
722 const mul = &FLOAT64_POW5_SPLIT2[base];
723 if (i == base2) {
724 return .{ mul[0], mul[1] };
725 } else {
726 const offset = i - base2;
727 const m = FLOAT64_POW5_TABLE[offset];
728 const b0 = @as(u128, m) * mul[0];
729 const b2 = @as(u128, m) * mul[1];
730 const delta: u7 = @intCast(pow5Bits(i) - pow5Bits(base2));
731 const shift: u5 = @intCast((i % 16) << 1);
732 const shifted_sum = ((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((FLOAT64_POW5_OFFSETS[i / 16] >> shift) & 3);
733 return .{ @truncate(shifted_sum), @truncate(shifted_sum >> 64) };
734 }
735 }
736
737 fn computeInvPow5(i: u32) [2]u64 {
738 const base = (i + FLOAT64_POW5_TABLE_SIZE - 1) / FLOAT64_POW5_TABLE_SIZE;
739 const base2 = base * FLOAT64_POW5_TABLE_SIZE;
740 const mul = &FLOAT64_POW5_INV_SPLIT2[base]; // 1 / 5^base2
741 if (i == base2) {
742 return .{ mul[0], mul[1] };
743 } else {
744 const offset = base2 - i;
745 const m = FLOAT64_POW5_TABLE[offset]; // 5^offset
746 const b0 = @as(u128, m) * (mul[0] - 1);
747 const b2 = @as(u128, m) * mul[1]; // 1/5^base2 * 5^offset = 1/5^(base2-offset) = 1/5^i
748 const delta: u7 = @intCast(pow5Bits(base2) - pow5Bits(i));
749 const shift: u5 = @intCast((i % 16) << 1);
750 const shifted_sum = ((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((FLOAT64_POW5_INV_OFFSETS[i / 16] >> shift) & 3);
751 return .{ @truncate(shifted_sum), @truncate(shifted_sum >> 64) };
752 }
753 }
754};
755
756const FLOAT64_POW5_INV_BITCOUNT = 125;
757const FLOAT64_POW5_BITCOUNT = 125;
758
759// zig fmt: off
760//
761// f64 small tables: 816 bytes
762
763const FLOAT64_POW5_TABLE_SIZE: comptime_int = FLOAT64_POW5_TABLE.len;
764
765const FLOAT64_POW5_TABLE: [26]u64 = .{
766 1, 5,
767 25, 125,
768 625, 3125,
769 15625, 78125,
770 390625, 1953125,
771 9765625, 48828125,
772 244140625, 1220703125,
773 6103515625, 30517578125,
774 152587890625, 762939453125,
775 3814697265625, 19073486328125,
776 95367431640625, 476837158203125,
777 2384185791015625, 11920928955078125,
778 59604644775390625, 298023223876953125,
779};
780
781const FLOAT64_POW5_SPLIT2: [13][2]u64 = .{
782 .{ 0, 1152921504606846976 },
783 .{ 0, 1490116119384765625 },
784 .{ 1032610780636961552, 1925929944387235853 },
785 .{ 7910200175544436838, 1244603055572228341 },
786 .{ 16941905809032713930, 1608611746708759036 },
787 .{ 13024893955298202172, 2079081953128979843 },
788 .{ 6607496772837067824, 1343575221513417750 },
789 .{ 17332926989895652603, 1736530273035216783 },
790 .{ 13037379183483547984, 2244412773384604712 },
791 .{ 1605989338741628675, 1450417759929778918 },
792 .{ 9630225068416591280, 1874621017369538693 },
793 .{ 665883850346957067, 1211445438634777304 },
794 .{ 14931890668723713708, 1565756531257009982 }
795};
796
797const FLOAT64_POW5_OFFSETS: [21]u32 = .{
798 0x00000000, 0x00000000, 0x00000000, 0x00000000,
799 0x40000000, 0x59695995, 0x55545555, 0x56555515,
800 0x41150504, 0x40555410, 0x44555145, 0x44504540,
801 0x45555550, 0x40004000, 0x96440440, 0x55565565,
802 0x54454045, 0x40154151, 0x55559155, 0x51405555,
803 0x00000105,
804};
805
806const FLOAT64_POW5_INV_SPLIT2: [15][2]u64 = .{
807 .{ 1, 2305843009213693952 },
808 .{ 5955668970331000884, 1784059615882449851 },
809 .{ 8982663654677661702, 1380349269358112757 },
810 .{ 7286864317269821294, 2135987035920910082 },
811 .{ 7005857020398200553, 1652639921975621497 },
812 .{ 17965325103354776697, 1278668206209430417 },
813 .{ 8928596168509315048, 1978643211784836272 },
814 .{ 10075671573058298858, 1530901034580419511 },
815 .{ 597001226353042382, 1184477304306571148 },
816 .{ 1527430471115325346, 1832889850782397517 },
817 .{ 12533209867169019542, 1418129833677084982 },
818 .{ 5577825024675947042, 2194449627517475473 },
819 .{ 11006974540203867551, 1697873161311732311 },
820 .{ 10313493231639821582, 1313665730009899186 },
821 .{ 12701016819766672773, 2032799256770390445 }
822};
823
824const FLOAT64_POW5_INV_OFFSETS: [19]u32 = .{
825 0x54544554, 0x04055545, 0x10041000, 0x00400414,
826 0x40010000, 0x41155555, 0x00000454, 0x00010044,
827 0x40000000, 0x44000041, 0x50454450, 0x55550054,
828 0x51655554, 0x40004000, 0x01000001, 0x00010500,
829 0x51515411, 0x05555554, 0x00000000,
830};
831
832
833// zig fmt: off
834
835// f64 full tables: 10688 bytes
836
837const FLOAT64_POW5_SPLIT: [326][2]u64 = .{
838 .{ 0, 1152921504606846976 }, .{ 0, 1441151880758558720 },
839 .{ 0, 1801439850948198400 }, .{ 0, 2251799813685248000 },
840 .{ 0, 1407374883553280000 }, .{ 0, 1759218604441600000 },
841 .{ 0, 2199023255552000000 }, .{ 0, 1374389534720000000 },
842 .{ 0, 1717986918400000000 }, .{ 0, 2147483648000000000 },
843 .{ 0, 1342177280000000000 }, .{ 0, 1677721600000000000 },
844 .{ 0, 2097152000000000000 }, .{ 0, 1310720000000000000 },
845 .{ 0, 1638400000000000000 }, .{ 0, 2048000000000000000 },
846 .{ 0, 1280000000000000000 }, .{ 0, 1600000000000000000 },
847 .{ 0, 2000000000000000000 }, .{ 0, 1250000000000000000 },
848 .{ 0, 1562500000000000000 }, .{ 0, 1953125000000000000 },
849 .{ 0, 1220703125000000000 }, .{ 0, 1525878906250000000 },
850 .{ 0, 1907348632812500000 }, .{ 0, 1192092895507812500 },
851 .{ 0, 1490116119384765625 }, .{ 4611686018427387904, 1862645149230957031 },
852 .{ 9799832789158199296, 1164153218269348144 }, .{ 12249790986447749120, 1455191522836685180 },
853 .{ 15312238733059686400, 1818989403545856475 }, .{ 14528612397897220096, 2273736754432320594 },
854 .{ 13692068767113150464, 1421085471520200371 }, .{ 12503399940464050176, 1776356839400250464 },
855 .{ 15629249925580062720, 2220446049250313080 }, .{ 9768281203487539200, 1387778780781445675 },
856 .{ 7598665485932036096, 1734723475976807094 }, .{ 274959820560269312, 2168404344971008868 },
857 .{ 9395221924704944128, 1355252715606880542 }, .{ 2520655369026404352, 1694065894508600678 },
858 .{ 12374191248137781248, 2117582368135750847 }, .{ 14651398557727195136, 1323488980084844279 },
859 .{ 13702562178731606016, 1654361225106055349 }, .{ 3293144668132343808, 2067951531382569187 },
860 .{ 18199116482078572544, 1292469707114105741 }, .{ 8913837547316051968, 1615587133892632177 },
861 .{ 15753982952572452864, 2019483917365790221 }, .{ 12152082354571476992, 1262177448353618888 },
862 .{ 15190102943214346240, 1577721810442023610 }, .{ 9764256642163156992, 1972152263052529513 },
863 .{ 17631875447420442880, 1232595164407830945 }, .{ 8204786253993389888, 1540743955509788682 },
864 .{ 1032610780636961552, 1925929944387235853 }, .{ 2951224747111794922, 1203706215242022408 },
865 .{ 3689030933889743652, 1504632769052528010 }, .{ 13834660704216955373, 1880790961315660012 },
866 .{ 17870034976990372916, 1175494350822287507 }, .{ 17725857702810578241, 1469367938527859384 },
867 .{ 3710578054803671186, 1836709923159824231 }, .{ 26536550077201078, 2295887403949780289 },
868 .{ 11545800389866720434, 1434929627468612680 }, .{ 14432250487333400542, 1793662034335765850 },
869 .{ 8816941072311974870, 2242077542919707313 }, .{ 17039803216263454053, 1401298464324817070 },
870 .{ 12076381983474541759, 1751623080406021338 }, .{ 5872105442488401391, 2189528850507526673 },
871 .{ 15199280947623720629, 1368455531567204170 }, .{ 9775729147674874978, 1710569414459005213 },
872 .{ 16831347453020981627, 2138211768073756516 }, .{ 1296220121283337709, 1336382355046097823 },
873 .{ 15455333206886335848, 1670477943807622278 }, .{ 10095794471753144002, 2088097429759527848 },
874 .{ 6309871544845715001, 1305060893599704905 }, .{ 12499025449484531656, 1631326116999631131 },
875 .{ 11012095793428276666, 2039157646249538914 }, .{ 11494245889320060820, 1274473528905961821 },
876 .{ 532749306367912313, 1593091911132452277 }, .{ 5277622651387278295, 1991364888915565346 },
877 .{ 7910200175544436838, 1244603055572228341 }, .{ 14499436237857933952, 1555753819465285426 },
878 .{ 8900923260467641632, 1944692274331606783 }, .{ 12480606065433357876, 1215432671457254239 },
879 .{ 10989071563364309441, 1519290839321567799 }, .{ 9124653435777998898, 1899113549151959749 },
880 .{ 8008751406574943263, 1186945968219974843 }, .{ 5399253239791291175, 1483682460274968554 },
881 .{ 15972438586593889776, 1854603075343710692 }, .{ 759402079766405302, 1159126922089819183 },
882 .{ 14784310654990170340, 1448908652612273978 }, .{ 9257016281882937117, 1811135815765342473 },
883 .{ 16182956370781059300, 2263919769706678091 }, .{ 7808504722524468110, 1414949856066673807 },
884 .{ 5148944884728197234, 1768687320083342259 }, .{ 1824495087482858639, 2210859150104177824 },
885 .{ 1140309429676786649, 1381786968815111140 }, .{ 1425386787095983311, 1727233711018888925 },
886 .{ 6393419502297367043, 2159042138773611156 }, .{ 13219259225790630210, 1349401336733506972 },
887 .{ 16524074032238287762, 1686751670916883715 }, .{ 16043406521870471799, 2108439588646104644 },
888 .{ 803757039314269066, 1317774742903815403 }, .{ 14839754354425000045, 1647218428629769253 },
889 .{ 4714634887749086344, 2059023035787211567 }, .{ 9864175832484260821, 1286889397367007229 },
890 .{ 16941905809032713930, 1608611746708759036 }, .{ 2730638187581340797, 2010764683385948796 },
891 .{ 10930020904093113806, 1256727927116217997 }, .{ 18274212148543780162, 1570909908895272496 },
892 .{ 4396021111970173586, 1963637386119090621 }, .{ 5053356204195052443, 1227273366324431638 },
893 .{ 15540067292098591362, 1534091707905539547 }, .{ 14813398096695851299, 1917614634881924434 },
894 .{ 13870059828862294966, 1198509146801202771 }, .{ 12725888767650480803, 1498136433501503464 },
895 .{ 15907360959563101004, 1872670541876879330 }, .{ 14553786618154326031, 1170419088673049581 },
896 .{ 4357175217410743827, 1463023860841311977 }, .{ 10058155040190817688, 1828779826051639971 },
897 .{ 7961007781811134206, 2285974782564549964 }, .{ 14199001900486734687, 1428734239102843727 },
898 .{ 13137066357181030455, 1785917798878554659 }, .{ 11809646928048900164, 2232397248598193324 },
899 .{ 16604401366885338411, 1395248280373870827 }, .{ 16143815690179285109, 1744060350467338534 },
900 .{ 10956397575869330579, 2180075438084173168 }, .{ 6847748484918331612, 1362547148802608230 },
901 .{ 17783057643002690323, 1703183936003260287 }, .{ 17617136035325974999, 2128979920004075359 },
902 .{ 17928239049719816230, 1330612450002547099 }, .{ 17798612793722382384, 1663265562503183874 },
903 .{ 13024893955298202172, 2079081953128979843 }, .{ 5834715712847682405, 1299426220705612402 },
904 .{ 16516766677914378815, 1624282775882015502 }, .{ 11422586310538197711, 2030353469852519378 },
905 .{ 11750802462513761473, 1268970918657824611 }, .{ 10076817059714813937, 1586213648322280764 },
906 .{ 12596021324643517422, 1982767060402850955 }, .{ 5566670318688504437, 1239229412751781847 },
907 .{ 2346651879933242642, 1549036765939727309 }, .{ 7545000868343941206, 1936295957424659136 },
908 .{ 4715625542714963254, 1210184973390411960 }, .{ 5894531928393704067, 1512731216738014950 },
909 .{ 16591536947346905892, 1890914020922518687 }, .{ 17287239619732898039, 1181821263076574179 },
910 .{ 16997363506238734644, 1477276578845717724 }, .{ 2799960309088866689, 1846595723557147156 },
911 .{ 10973347230035317489, 1154122327223216972 }, .{ 13716684037544146861, 1442652909029021215 },
912 .{ 12534169028502795672, 1803316136286276519 }, .{ 11056025267201106687, 2254145170357845649 },
913 .{ 18439230838069161439, 1408840731473653530 }, .{ 13825666510731675991, 1761050914342066913 },
914 .{ 3447025083132431277, 2201313642927583642 }, .{ 6766076695385157452, 1375821026829739776 },
915 .{ 8457595869231446815, 1719776283537174720 }, .{ 10571994836539308519, 2149720354421468400 },
916 .{ 6607496772837067824, 1343575221513417750 }, .{ 17482743002901110588, 1679469026891772187 },
917 .{ 17241742735199000331, 2099336283614715234 }, .{ 15387775227926763111, 1312085177259197021 },
918 .{ 5399660979626290177, 1640106471573996277 }, .{ 11361262242960250625, 2050133089467495346 },
919 .{ 11712474920277544544, 1281333180917184591 }, .{ 10028907631919542777, 1601666476146480739 },
920 .{ 7924448521472040567, 2002083095183100924 }, .{ 14176152362774801162, 1251301934489438077 },
921 .{ 3885132398186337741, 1564127418111797597 }, .{ 9468101516160310080, 1955159272639746996 },
922 .{ 15140935484454969608, 1221974545399841872 }, .{ 479425281859160394, 1527468181749802341 },
923 .{ 5210967620751338397, 1909335227187252926 }, .{ 17091912818251750210, 1193334516992033078 },
924 .{ 12141518985959911954, 1491668146240041348 }, .{ 15176898732449889943, 1864585182800051685 },
925 .{ 11791404716994875166, 1165365739250032303 }, .{ 10127569877816206054, 1456707174062540379 },
926 .{ 8047776328842869663, 1820883967578175474 }, .{ 836348374198811271, 2276104959472719343 },
927 .{ 7440246761515338900, 1422565599670449589 }, .{ 13911994470321561530, 1778206999588061986 },
928 .{ 8166621051047176104, 2222758749485077483 }, .{ 2798295147690791113, 1389224218428173427 },
929 .{ 17332926989895652603, 1736530273035216783 }, .{ 17054472718942177850, 2170662841294020979 },
930 .{ 8353202440125167204, 1356664275808763112 }, .{ 10441503050156459005, 1695830344760953890 },
931 .{ 3828506775840797949, 2119787930951192363 }, .{ 86973725686804766, 1324867456844495227 },
932 .{ 13943775212390669669, 1656084321055619033 }, .{ 3594660960206173375, 2070105401319523792 },
933 .{ 2246663100128858359, 1293815875824702370 }, .{ 12031700912015848757, 1617269844780877962 },
934 .{ 5816254103165035138, 2021587305976097453 }, .{ 5941001823691840913, 1263492066235060908 },
935 .{ 7426252279614801142, 1579365082793826135 }, .{ 4671129331091113523, 1974206353492282669 },
936 .{ 5225298841145639904, 1233878970932676668 }, .{ 6531623551432049880, 1542348713665845835 },
937 .{ 3552843420862674446, 1927935892082307294 }, .{ 16055585193321335241, 1204959932551442058 },
938 .{ 10846109454796893243, 1506199915689302573 }, .{ 18169322836923504458, 1882749894611628216 },
939 .{ 11355826773077190286, 1176718684132267635 }, .{ 9583097447919099954, 1470898355165334544 },
940 .{ 11978871809898874942, 1838622943956668180 }, .{ 14973589762373593678, 2298278679945835225 },
941 .{ 2440964573842414192, 1436424174966147016 }, .{ 3051205717303017741, 1795530218707683770 },
942 .{ 13037379183483547984, 2244412773384604712 }, .{ 8148361989677217490, 1402757983365377945 },
943 .{ 14797138505523909766, 1753447479206722431 }, .{ 13884737113477499304, 2191809349008403039 },
944 .{ 15595489723564518921, 1369880843130251899 }, .{ 14882676136028260747, 1712351053912814874 },
945 .{ 9379973133180550126, 2140438817391018593 }, .{ 17391698254306313589, 1337774260869386620 },
946 .{ 3292878744173340370, 1672217826086733276 }, .{ 4116098430216675462, 2090272282608416595 },
947 .{ 266718509671728212, 1306420176630260372 }, .{ 333398137089660265, 1633025220787825465 },
948 .{ 5028433689789463235, 2041281525984781831 }, .{ 10060300083759496378, 1275800953740488644 },
949 .{ 12575375104699370472, 1594751192175610805 }, .{ 1884160825592049379, 1993438990219513507 },
950 .{ 17318501580490888525, 1245899368887195941 }, .{ 7813068920331446945, 1557374211108994927 },
951 .{ 5154650131986920777, 1946717763886243659 }, .{ 915813323278131534, 1216698602428902287 },
952 .{ 14979824709379828129, 1520873253036127858 }, .{ 9501408849870009354, 1901091566295159823 },
953 .{ 12855909558809837702, 1188182228934474889 }, .{ 2234828893230133415, 1485227786168093612 },
954 .{ 2793536116537666769, 1856534732710117015 }, .{ 8663489100477123587, 1160334207943823134 },
955 .{ 1605989338741628675, 1450417759929778918 }, .{ 11230858710281811652, 1813022199912223647 },
956 .{ 9426887369424876662, 2266277749890279559 }, .{ 12809333633531629769, 1416423593681424724 },
957 .{ 16011667041914537212, 1770529492101780905 }, .{ 6179525747111007803, 2213161865127226132 },
958 .{ 13085575628799155685, 1383226165704516332 }, .{ 16356969535998944606, 1729032707130645415 },
959 .{ 15834525901571292854, 2161290883913306769 }, .{ 2979049660840976177, 1350806802445816731 },
960 .{ 17558870131333383934, 1688508503057270913 }, .{ 8113529608884566205, 2110635628821588642 },
961 .{ 9682642023980241782, 1319147268013492901 }, .{ 16714988548402690132, 1648934085016866126 },
962 .{ 11670363648648586857, 2061167606271082658 }, .{ 11905663298832754689, 1288229753919426661 },
963 .{ 1047021068258779650, 1610287192399283327 }, .{ 15143834390605638274, 2012858990499104158 },
964 .{ 4853210475701136017, 1258036869061940099 }, .{ 1454827076199032118, 1572546086327425124 },
965 .{ 1818533845248790147, 1965682607909281405 }, .{ 3442426662494187794, 1228551629943300878 },
966 .{ 13526405364972510550, 1535689537429126097 }, .{ 3072948650933474476, 1919611921786407622 },
967 .{ 15755650962115585259, 1199757451116504763 }, .{ 15082877684217093670, 1499696813895630954 },
968 .{ 9630225068416591280, 1874621017369538693 }, .{ 8324733676974063502, 1171638135855961683 },
969 .{ 5794231077790191473, 1464547669819952104 }, .{ 7242788847237739342, 1830684587274940130 },
970 .{ 18276858095901949986, 2288355734093675162 }, .{ 16034722328366106645, 1430222333808546976 },
971 .{ 1596658836748081690, 1787777917260683721 }, .{ 6607509564362490017, 2234722396575854651 },
972 .{ 1823850468512862308, 1396701497859909157 }, .{ 6891499104068465790, 1745876872324886446 },
973 .{ 17837745916940358045, 2182346090406108057 }, .{ 4231062170446641922, 1363966306503817536 },
974 .{ 5288827713058302403, 1704957883129771920 }, .{ 6611034641322878003, 2131197353912214900 },
975 .{ 13355268687681574560, 1331998346195134312 }, .{ 16694085859601968200, 1664997932743917890 },
976 .{ 11644235287647684442, 2081247415929897363 }, .{ 4971804045566108824, 1300779634956185852 },
977 .{ 6214755056957636030, 1625974543695232315 }, .{ 3156757802769657134, 2032468179619040394 },
978 .{ 6584659645158423613, 1270292612261900246 }, .{ 17454196593302805324, 1587865765327375307 },
979 .{ 17206059723201118751, 1984832206659219134 }, .{ 6142101308573311315, 1240520129162011959 },
980 .{ 3065940617289251240, 1550650161452514949 }, .{ 8444111790038951954, 1938312701815643686 },
981 .{ 665883850346957067, 1211445438634777304 }, .{ 832354812933696334, 1514306798293471630 },
982 .{ 10263815553021896226, 1892883497866839537 }, .{ 17944099766707154901, 1183052186166774710 },
983 .{ 13206752671529167818, 1478815232708468388 }, .{ 16508440839411459773, 1848519040885585485 },
984 .{ 12623618533845856310, 1155324400553490928 }, .{ 15779523167307320387, 1444155500691863660 },
985 .{ 1277659885424598868, 1805194375864829576 }, .{ 1597074856780748586, 2256492969831036970 },
986 .{ 5609857803915355770, 1410308106144398106 }, .{ 16235694291748970521, 1762885132680497632 },
987 .{ 1847873790976661535, 2203606415850622041 }, .{ 12684136165428883219, 1377254009906638775 },
988 .{ 11243484188358716120, 1721567512383298469 }, .{ 219297180166231438, 2151959390479123087 },
989 .{ 7054589765244976505, 1344974619049451929 }, .{ 13429923224983608535, 1681218273811814911 },
990 .{ 12175718012802122765, 2101522842264768639 }, .{ 14527352785642408584, 1313451776415480399 },
991 .{ 13547504963625622826, 1641814720519350499 }, .{ 12322695186104640628, 2052268400649188124 },
992 .{ 16925056528170176201, 1282667750405742577 }, .{ 7321262604930556539, 1603334688007178222 },
993 .{ 18374950293017971482, 2004168360008972777 }, .{ 4566814905495150320, 1252605225005607986 },
994 .{ 14931890668723713708, 1565756531257009982 }, .{ 9441491299049866327, 1957195664071262478 },
995 .{ 1289246043478778550, 1223247290044539049 }, .{ 6223243572775861092, 1529059112555673811 },
996 .{ 3167368447542438461, 1911323890694592264 }, .{ 1979605279714024038, 1194577431684120165 },
997 .{ 7086192618069917952, 1493221789605150206 }, .{ 18081112809442173248, 1866527237006437757 },
998 .{ 13606538515115052232, 1166579523129023598 }, .{ 7784801107039039482, 1458224403911279498 },
999 .{ 507629346944023544, 1822780504889099373 }, .{ 5246222702107417334, 2278475631111374216 },
1000 .{ 3278889188817135834, 1424047269444608885 }, .{ 8710297504448807696, 1780059086805761106 }
1001};
1002
1003const FLOAT64_POW5_INV_SPLIT: [342][2]u64 = .{
1004 .{ 1, 2305843009213693952 }, .{ 11068046444225730970, 1844674407370955161 },
1005 .{ 5165088340638674453, 1475739525896764129 }, .{ 7821419487252849886, 1180591620717411303 },
1006 .{ 8824922364862649494, 1888946593147858085 }, .{ 7059937891890119595, 1511157274518286468 },
1007 .{ 13026647942995916322, 1208925819614629174 }, .{ 9774590264567735146, 1934281311383406679 },
1008 .{ 11509021026396098440, 1547425049106725343 }, .{ 16585914450600699399, 1237940039285380274 },
1009 .{ 15469416676735388068, 1980704062856608439 }, .{ 16064882156130220778, 1584563250285286751 },
1010 .{ 9162556910162266299, 1267650600228229401 }, .{ 7281393426775805432, 2028240960365167042 },
1011 .{ 16893161185646375315, 1622592768292133633 }, .{ 2446482504291369283, 1298074214633706907 },
1012 .{ 7603720821608101175, 2076918743413931051 }, .{ 2393627842544570617, 1661534994731144841 },
1013 .{ 16672297533003297786, 1329227995784915872 }, .{ 11918280793837635165, 2126764793255865396 },
1014 .{ 5845275820328197809, 1701411834604692317 }, .{ 15744267100488289217, 1361129467683753853 },
1015 .{ 3054734472329800808, 2177807148294006166 }, .{ 17201182836831481939, 1742245718635204932 },
1016 .{ 6382248639981364905, 1393796574908163946 }, .{ 2832900194486363201, 2230074519853062314 },
1017 .{ 5955668970331000884, 1784059615882449851 }, .{ 1075186361522890384, 1427247692705959881 },
1018 .{ 12788344622662355584, 2283596308329535809 }, .{ 13920024512871794791, 1826877046663628647 },
1019 .{ 3757321980813615186, 1461501637330902918 }, .{ 10384555214134712795, 1169201309864722334 },
1020 .{ 5547241898389809503, 1870722095783555735 }, .{ 4437793518711847602, 1496577676626844588 },
1021 .{ 10928932444453298728, 1197262141301475670 }, .{ 17486291911125277965, 1915619426082361072 },
1022 .{ 6610335899416401726, 1532495540865888858 }, .{ 12666966349016942027, 1225996432692711086 },
1023 .{ 12888448528943286597, 1961594292308337738 }, .{ 17689456452638449924, 1569275433846670190 },
1024 .{ 14151565162110759939, 1255420347077336152 }, .{ 7885109000409574610, 2008672555323737844 },
1025 .{ 9997436015069570011, 1606938044258990275 }, .{ 7997948812055656009, 1285550435407192220 },
1026 .{ 12796718099289049614, 2056880696651507552 }, .{ 2858676849947419045, 1645504557321206042 },
1027 .{ 13354987924183666206, 1316403645856964833 }, .{ 17678631863951955605, 2106245833371143733 },
1028 .{ 3074859046935833515, 1684996666696914987 }, .{ 13527933681774397782, 1347997333357531989 },
1029 .{ 10576647446613305481, 2156795733372051183 }, .{ 15840015586774465031, 1725436586697640946 },
1030 .{ 8982663654677661702, 1380349269358112757 }, .{ 18061610662226169046, 2208558830972980411 },
1031 .{ 10759939715039024913, 1766847064778384329 }, .{ 12297300586773130254, 1413477651822707463 },
1032 .{ 15986332124095098083, 2261564242916331941 }, .{ 9099716884534168143, 1809251394333065553 },
1033 .{ 14658471137111155161, 1447401115466452442 }, .{ 4348079280205103483, 1157920892373161954 },
1034 .{ 14335624477811986218, 1852673427797059126 }, .{ 7779150767507678651, 1482138742237647301 },
1035 .{ 2533971799264232598, 1185710993790117841 }, .{ 15122401323048503126, 1897137590064188545 },
1036 .{ 12097921058438802501, 1517710072051350836 }, .{ 5988988032009131678, 1214168057641080669 },
1037 .{ 16961078480698431330, 1942668892225729070 }, .{ 13568862784558745064, 1554135113780583256 },
1038 .{ 7165741412905085728, 1243308091024466605 }, .{ 11465186260648137165, 1989292945639146568 },
1039 .{ 16550846638002330379, 1591434356511317254 }, .{ 16930026125143774626, 1273147485209053803 },
1040 .{ 4951948911778577463, 2037035976334486086 }, .{ 272210314680951647, 1629628781067588869 },
1041 .{ 3907117066486671641, 1303703024854071095 }, .{ 6251387306378674625, 2085924839766513752 },
1042 .{ 16069156289328670670, 1668739871813211001 }, .{ 9165976216721026213, 1334991897450568801 },
1043 .{ 7286864317269821294, 2135987035920910082 }, .{ 16897537898041588005, 1708789628736728065 },
1044 .{ 13518030318433270404, 1367031702989382452 }, .{ 6871453250525591353, 2187250724783011924 },
1045 .{ 9186511415162383406, 1749800579826409539 }, .{ 11038557946871817048, 1399840463861127631 },
1046 .{ 10282995085511086630, 2239744742177804210 }, .{ 8226396068408869304, 1791795793742243368 },
1047 .{ 13959814484210916090, 1433436634993794694 }, .{ 11267656730511734774, 2293498615990071511 },
1048 .{ 5324776569667477496, 1834798892792057209 }, .{ 7949170070475892320, 1467839114233645767 },
1049 .{ 17427382500606444826, 1174271291386916613 }, .{ 5747719112518849781, 1878834066219066582 },
1050 .{ 15666221734240810795, 1503067252975253265 }, .{ 12532977387392648636, 1202453802380202612 },
1051 .{ 5295368560860596524, 1923926083808324180 }, .{ 4236294848688477220, 1539140867046659344 },
1052 .{ 7078384693692692099, 1231312693637327475 }, .{ 11325415509908307358, 1970100309819723960 },
1053 .{ 9060332407926645887, 1576080247855779168 }, .{ 14626963555825137356, 1260864198284623334 },
1054 .{ 12335095245094488799, 2017382717255397335 }, .{ 9868076196075591040, 1613906173804317868 },
1055 .{ 15273158586344293478, 1291124939043454294 }, .{ 13369007293925138595, 2065799902469526871 },
1056 .{ 7005857020398200553, 1652639921975621497 }, .{ 16672732060544291412, 1322111937580497197 },
1057 .{ 11918976037903224966, 2115379100128795516 }, .{ 5845832015580669650, 1692303280103036413 },
1058 .{ 12055363241948356366, 1353842624082429130 }, .{ 841837113407818570, 2166148198531886609 },
1059 .{ 4362818505468165179, 1732918558825509287 }, .{ 14558301248600263113, 1386334847060407429 },
1060 .{ 12225235553534690011, 2218135755296651887 }, .{ 2401490813343931363, 1774508604237321510 },
1061 .{ 1921192650675145090, 1419606883389857208 }, .{ 17831303500047873437, 2271371013423771532 },
1062 .{ 6886345170554478103, 1817096810739017226 }, .{ 1819727321701672159, 1453677448591213781 },
1063 .{ 16213177116328979020, 1162941958872971024 }, .{ 14873036941900635463, 1860707134196753639 },
1064 .{ 15587778368262418694, 1488565707357402911 }, .{ 8780873879868024632, 1190852565885922329 },
1065 .{ 2981351763563108441, 1905364105417475727 }, .{ 13453127855076217722, 1524291284333980581 },
1066 .{ 7073153469319063855, 1219433027467184465 }, .{ 11317045550910502167, 1951092843947495144 },
1067 .{ 12742985255470312057, 1560874275157996115 }, .{ 10194388204376249646, 1248699420126396892 },
1068 .{ 1553625868034358140, 1997919072202235028 }, .{ 8621598323911307159, 1598335257761788022 },
1069 .{ 17965325103354776697, 1278668206209430417 }, .{ 13987124906400001422, 2045869129935088668 },
1070 .{ 121653480894270168, 1636695303948070935 }, .{ 97322784715416134, 1309356243158456748 },
1071 .{ 14913111714512307107, 2094969989053530796 }, .{ 8241140556867935363, 1675975991242824637 },
1072 .{ 17660958889720079260, 1340780792994259709 }, .{ 17189487779326395846, 2145249268790815535 },
1073 .{ 13751590223461116677, 1716199415032652428 }, .{ 18379969808252713988, 1372959532026121942 },
1074 .{ 14650556434236701088, 2196735251241795108 }, .{ 652398703163629901, 1757388200993436087 },
1075 .{ 11589965406756634890, 1405910560794748869 }, .{ 7475898206584884855, 2249456897271598191 },
1076 .{ 2291369750525997561, 1799565517817278553 }, .{ 9211793429904618695, 1439652414253822842 },
1077 .{ 18428218302589300235, 2303443862806116547 }, .{ 7363877012587619542, 1842755090244893238 },
1078 .{ 13269799239553916280, 1474204072195914590 }, .{ 10615839391643133024, 1179363257756731672 },
1079 .{ 2227947767661371545, 1886981212410770676 }, .{ 16539753473096738529, 1509584969928616540 },
1080 .{ 13231802778477390823, 1207667975942893232 }, .{ 6413489186596184024, 1932268761508629172 },
1081 .{ 16198837793502678189, 1545815009206903337 }, .{ 5580372605318321905, 1236652007365522670 },
1082 .{ 8928596168509315048, 1978643211784836272 }, .{ 18210923379033183008, 1582914569427869017 },
1083 .{ 7190041073742725760, 1266331655542295214 }, .{ 436019273762630246, 2026130648867672343 },
1084 .{ 7727513048493924843, 1620904519094137874 }, .{ 9871359253537050198, 1296723615275310299 },
1085 .{ 4726128361433549347, 2074757784440496479 }, .{ 7470251503888749801, 1659806227552397183 },
1086 .{ 13354898832594820487, 1327844982041917746 }, .{ 13989140502667892133, 2124551971267068394 },
1087 .{ 14880661216876224029, 1699641577013654715 }, .{ 11904528973500979224, 1359713261610923772 },
1088 .{ 4289851098633925465, 2175541218577478036 }, .{ 18189276137874781665, 1740432974861982428 },
1089 .{ 3483374466074094362, 1392346379889585943 }, .{ 1884050330976640656, 2227754207823337509 },
1090 .{ 5196589079523222848, 1782203366258670007 }, .{ 15225317707844309248, 1425762693006936005 },
1091 .{ 5913764258841343181, 2281220308811097609 }, .{ 8420360221814984868, 1824976247048878087 },
1092 .{ 17804334621677718864, 1459980997639102469 }, .{ 17932816512084085415, 1167984798111281975 },
1093 .{ 10245762345624985047, 1868775676978051161 }, .{ 4507261061758077715, 1495020541582440929 },
1094 .{ 7295157664148372495, 1196016433265952743 }, .{ 7982903447895485668, 1913626293225524389 },
1095 .{ 10075671573058298858, 1530901034580419511 }, .{ 4371188443704728763, 1224720827664335609 },
1096 .{ 14372599139411386667, 1959553324262936974 }, .{ 15187428126271019657, 1567642659410349579 },
1097 .{ 15839291315758726049, 1254114127528279663 }, .{ 3206773216762499739, 2006582604045247462 },
1098 .{ 13633465017635730761, 1605266083236197969 }, .{ 14596120828850494932, 1284212866588958375 },
1099 .{ 4907049252451240275, 2054740586542333401 }, .{ 236290587219081897, 1643792469233866721 },
1100 .{ 14946427728742906810, 1315033975387093376 }, .{ 16535586736504830250, 2104054360619349402 },
1101 .{ 5849771759720043554, 1683243488495479522 }, .{ 15747863852001765813, 1346594790796383617 },
1102 .{ 10439186904235184007, 2154551665274213788 }, .{ 15730047152871967852, 1723641332219371030 },
1103 .{ 12584037722297574282, 1378913065775496824 }, .{ 9066413911450387881, 2206260905240794919 },
1104 .{ 10942479943902220628, 1765008724192635935 }, .{ 8753983955121776503, 1412006979354108748 },
1105 .{ 10317025513452932081, 2259211166966573997 }, .{ 874922781278525018, 1807368933573259198 },
1106 .{ 8078635854506640661, 1445895146858607358 }, .{ 13841606313089133175, 1156716117486885886 },
1107 .{ 14767872471458792434, 1850745787979017418 }, .{ 746251532941302978, 1480596630383213935 },
1108 .{ 597001226353042382, 1184477304306571148 }, .{ 15712597221132509104, 1895163686890513836 },
1109 .{ 8880728962164096960, 1516130949512411069 }, .{ 10793931984473187891, 1212904759609928855 },
1110 .{ 17270291175157100626, 1940647615375886168 }, .{ 2748186495899949531, 1552518092300708935 },
1111 .{ 2198549196719959625, 1242014473840567148 }, .{ 18275073973719576693, 1987223158144907436 },
1112 .{ 10930710364233751031, 1589778526515925949 }, .{ 12433917106128911148, 1271822821212740759 },
1113 .{ 8826220925580526867, 2034916513940385215 }, .{ 7060976740464421494, 1627933211152308172 },
1114 .{ 16716827836597268165, 1302346568921846537 }, .{ 11989529279587987770, 2083754510274954460 },
1115 .{ 9591623423670390216, 1667003608219963568 }, .{ 15051996368420132820, 1333602886575970854 },
1116 .{ 13015147745246481542, 2133764618521553367 }, .{ 3033420566713364587, 1707011694817242694 },
1117 .{ 6116085268112601993, 1365609355853794155 }, .{ 9785736428980163188, 2184974969366070648 },
1118 .{ 15207286772667951197, 1747979975492856518 }, .{ 1097782973908629988, 1398383980394285215 },
1119 .{ 1756452758253807981, 2237414368630856344 }, .{ 5094511021344956708, 1789931494904685075 },
1120 .{ 4075608817075965366, 1431945195923748060 }, .{ 6520974107321544586, 2291112313477996896 },
1121 .{ 1527430471115325346, 1832889850782397517 }, .{ 12289990821117991246, 1466311880625918013 },
1122 .{ 17210690286378213644, 1173049504500734410 }, .{ 9090360384495590213, 1876879207201175057 },
1123 .{ 18340334751822203140, 1501503365760940045 }, .{ 14672267801457762512, 1201202692608752036 },
1124 .{ 16096930852848599373, 1921924308174003258 }, .{ 1809498238053148529, 1537539446539202607 },
1125 .{ 12515645034668249793, 1230031557231362085 }, .{ 1578287981759648052, 1968050491570179337 },
1126 .{ 12330676829633449412, 1574440393256143469 }, .{ 13553890278448669853, 1259552314604914775 },
1127 .{ 3239480371808320148, 2015283703367863641 }, .{ 17348979556414297411, 1612226962694290912 },
1128 .{ 6500486015647617283, 1289781570155432730 }, .{ 10400777625036187652, 2063650512248692368 },
1129 .{ 15699319729512770768, 1650920409798953894 }, .{ 16248804598352126938, 1320736327839163115 },
1130 .{ 7551343283653851484, 2113178124542660985 }, .{ 6041074626923081187, 1690542499634128788 },
1131 .{ 12211557331022285596, 1352433999707303030 }, .{ 1091747655926105338, 2163894399531684849 },
1132 .{ 4562746939482794594, 1731115519625347879 }, .{ 7339546366328145998, 1384892415700278303 },
1133 .{ 8053925371383123274, 2215827865120445285 }, .{ 6443140297106498619, 1772662292096356228 },
1134 .{ 12533209867169019542, 1418129833677084982 }, .{ 5295740528502789974, 2269007733883335972 },
1135 .{ 15304638867027962949, 1815206187106668777 }, .{ 4865013464138549713, 1452164949685335022 },
1136 .{ 14960057215536570740, 1161731959748268017 }, .{ 9178696285890871890, 1858771135597228828 },
1137 .{ 14721654658196518159, 1487016908477783062 }, .{ 4398626097073393881, 1189613526782226450 },
1138 .{ 7037801755317430209, 1903381642851562320 }, .{ 5630241404253944167, 1522705314281249856 },
1139 .{ 814844308661245011, 1218164251424999885 }, .{ 1303750893857992017, 1949062802279999816 },
1140 .{ 15800395974054034906, 1559250241823999852 }, .{ 5261619149759407279, 1247400193459199882 },
1141 .{ 12107939454356961969, 1995840309534719811 }, .{ 5997002748743659252, 1596672247627775849 },
1142 .{ 8486951013736837725, 1277337798102220679 }, .{ 2511075177753209390, 2043740476963553087 },
1143 .{ 13076906586428298482, 1634992381570842469 }, .{ 14150874083884549109, 1307993905256673975 },
1144 .{ 4194654460505726958, 2092790248410678361 }, .{ 18113118827372222859, 1674232198728542688 },
1145 .{ 3422448617672047318, 1339385758982834151 }, .{ 16543964232501006678, 2143017214372534641 },
1146 .{ 9545822571258895019, 1714413771498027713 }, .{ 15015355686490936662, 1371531017198422170 },
1147 .{ 5577825024675947042, 2194449627517475473 }, .{ 11840957649224578280, 1755559702013980378 },
1148 .{ 16851463748863483271, 1404447761611184302 }, .{ 12204946739213931940, 2247116418577894884 },
1149 .{ 13453306206113055875, 1797693134862315907 }, .{ 3383947335406624054, 1438154507889852726 },
1150 .{ 16482362180876329456, 2301047212623764361 }, .{ 9496540929959153242, 1840837770099011489 },
1151 .{ 11286581558709232917, 1472670216079209191 }, .{ 5339916432225476010, 1178136172863367353 },
1152 .{ 4854517476818851293, 1885017876581387765 }, .{ 3883613981455081034, 1508014301265110212 },
1153 .{ 14174937629389795797, 1206411441012088169 }, .{ 11611853762797942306, 1930258305619341071 },
1154 .{ 5600134195496443521, 1544206644495472857 }, .{ 15548153800622885787, 1235365315596378285 },
1155 .{ 6430302007287065643, 1976584504954205257 }, .{ 16212288050055383484, 1581267603963364205 },
1156 .{ 12969830440044306787, 1265014083170691364 }, .{ 9683682259845159889, 2024022533073106183 },
1157 .{ 15125643437359948558, 1619218026458484946 }, .{ 8411165935146048523, 1295374421166787957 },
1158 .{ 17147214310975587960, 2072599073866860731 }, .{ 10028422634038560045, 1658079259093488585 },
1159 .{ 8022738107230848036, 1326463407274790868 }, .{ 9147032156827446534, 2122341451639665389 },
1160 .{ 11006974540203867551, 1697873161311732311 }, .{ 5116230817421183718, 1358298529049385849 },
1161 .{ 15564666937357714594, 2173277646479017358 }, .{ 1383687105660440706, 1738622117183213887 },
1162 .{ 12174996128754083534, 1390897693746571109 }, .{ 8411947361780802685, 2225436309994513775 },
1163 .{ 6729557889424642148, 1780349047995611020 }, .{ 5383646311539713719, 1424279238396488816 },
1164 .{ 1235136468979721303, 2278846781434382106 }, .{ 15745504434151418335, 1823077425147505684 },
1165 .{ 16285752362063044992, 1458461940118004547 }, .{ 5649904260166615347, 1166769552094403638 },
1166 .{ 5350498001524674232, 1866831283351045821 }, .{ 591049586477829062, 1493465026680836657 },
1167 .{ 11540886113407994219, 1194772021344669325 }, .{ 18673707743239135, 1911635234151470921 },
1168 .{ 14772334225162232601, 1529308187321176736 }, .{ 8128518565387875758, 1223446549856941389 },
1169 .{ 1937583260394870242, 1957514479771106223 }, .{ 8928764237799716840, 1566011583816884978 },
1170 .{ 14521709019723594119, 1252809267053507982 }, .{ 8477339172590109297, 2004494827285612772 },
1171 .{ 17849917782297818407, 1603595861828490217 }, .{ 6901236596354434079, 1282876689462792174 },
1172 .{ 18420676183650915173, 2052602703140467478 }, .{ 3668494502695001169, 1642082162512373983 },
1173 .{ 10313493231639821582, 1313665730009899186 }, .{ 9122891541139893884, 2101865168015838698 },
1174 .{ 14677010862395735754, 1681492134412670958 }, .{ 673562245690857633, 1345193707530136767 }
1175};
1176
1177// zig fmt: off
1178//
1179// f128 small tables: 9072 bytes
1180
1181const FLOAT128_POW5_INV_BITCOUNT = 249;
1182const FLOAT128_POW5_BITCOUNT = 249;
1183const FLOAT128_POW5_TABLE_SIZE: comptime_int = FLOAT128_POW5_TABLE.len;
1184
1185const FLOAT128_POW5_TABLE: [56][2]u64 = .{
1186 .{ 1, 0 },
1187 .{ 5, 0 },
1188 .{ 25, 0 },
1189 .{ 125, 0 },
1190 .{ 625, 0 },
1191 .{ 3125, 0 },
1192 .{ 15625, 0 },
1193 .{ 78125, 0 },
1194 .{ 390625, 0 },
1195 .{ 1953125, 0 },
1196 .{ 9765625, 0 },
1197 .{ 48828125, 0 },
1198 .{ 244140625, 0 },
1199 .{ 1220703125, 0 },
1200 .{ 6103515625, 0 },
1201 .{ 30517578125, 0 },
1202 .{ 152587890625, 0 },
1203 .{ 762939453125, 0 },
1204 .{ 3814697265625, 0 },
1205 .{ 19073486328125, 0 },
1206 .{ 95367431640625, 0 },
1207 .{ 476837158203125, 0 },
1208 .{ 2384185791015625, 0 },
1209 .{ 11920928955078125, 0 },
1210 .{ 59604644775390625, 0 },
1211 .{ 298023223876953125, 0 },
1212 .{ 1490116119384765625, 0 },
1213 .{ 7450580596923828125, 0 },
1214 .{ 359414837200037393, 2 },
1215 .{ 1797074186000186965, 10 },
1216 .{ 8985370930000934825, 50 },
1217 .{ 8033366502585570893, 252 },
1218 .{ 3273344365508751233, 1262 },
1219 .{ 16366721827543756165, 6310 },
1220 .{ 8046632842880574361, 31554 },
1221 .{ 3339676066983768573, 157772 },
1222 .{ 16698380334918842865, 788860 },
1223 .{ 9704925379756007861, 3944304 },
1224 .{ 11631138751360936073, 19721522 },
1225 .{ 2815461535676025517, 98607613 },
1226 .{ 14077307678380127585, 493038065 },
1227 .{ 15046306170771983077, 2465190328 },
1228 .{ 1444554559021708921, 12325951644 },
1229 .{ 7222772795108544605, 61629758220 },
1230 .{ 17667119901833171409, 308148791101 },
1231 .{ 14548623214327650581, 1540743955509 },
1232 .{ 17402883850509598057, 7703719777548 },
1233 .{ 13227442957709783821, 38518598887744 },
1234 .{ 10796982567420264257, 192592994438723 },
1235 .{ 17091424689682218053, 962964972193617 },
1236 .{ 11670147153572883801, 4814824860968089 },
1237 .{ 3010503546735764157, 24074124304840448 },
1238 .{ 15052517733678820785, 120370621524202240 },
1239 .{ 1475612373555897461, 601853107621011204 },
1240 .{ 7378061867779487305, 3009265538105056020 },
1241 .{ 18443565265187884909, 15046327690525280101 },
1242};
1243
1244const FLOAT128_POW5_SPLIT: [89][4]u64 = .{
1245 .{ 0, 0, 0, 72057594037927936 },
1246 .{ 0, 5206161169240293376, 4575641699882439235, 73468396926392969 },
1247 .{ 3360510775605221349, 6983200512169538081, 4325643253124434363, 74906821675075173 },
1248 .{ 11917660854915489451, 9652941469841108803, 946308467778435600, 76373409087490117 },
1249 .{ 1994853395185689235, 16102657350889591545, 6847013871814915412, 77868710555449746 },
1250 .{ 958415760277438274, 15059347134713823592, 7329070255463483331, 79393288266368765 },
1251 .{ 2065144883315240188, 7145278325844925976, 14718454754511147343, 80947715414629833 },
1252 .{ 8980391188862868935, 13709057401304208685, 8230434828742694591, 82532576417087045 },
1253 .{ 432148644612782575, 7960151582448466064, 12056089168559840552, 84148467132788711 },
1254 .{ 484109300864744403, 15010663910730448582, 16824949663447227068, 85795995087002057 },
1255 .{ 14793711725276144220, 16494403799991899904, 10145107106505865967, 87475779699624060 },
1256 .{ 15427548291869817042, 12330588654550505203, 13980791795114552342, 89188452518064298 },
1257 .{ 9979404135116626552, 13477446383271537499, 14459862802511591337, 90934657454687378 },
1258 .{ 12385121150303452775, 9097130814231585614, 6523855782339765207, 92715051028904201 },
1259 .{ 1822931022538209743, 16062974719797586441, 3619180286173516788, 94530302614003091 },
1260 .{ 12318611738248470829, 13330752208259324507, 10986694768744162601, 96381094688813589 },
1261 .{ 13684493829640282333, 7674802078297225834, 15208116197624593182, 98268123094297527 },
1262 .{ 5408877057066295332, 6470124174091971006, 15112713923117703147, 100192097295163851 },
1263 .{ 11407083166564425062, 18189998238742408185, 4337638702446708282, 102153740646605557 },
1264 .{ 4112405898036935485, 924624216579956435, 14251108172073737125, 104153790666259019 },
1265 .{ 16996739107011444789, 10015944118339042475, 2395188869672266257, 106192999311487969 },
1266 .{ 4588314690421337879, 5339991768263654604, 15441007590670620066, 108272133262096356 },
1267 .{ 2286159977890359825, 14329706763185060248, 5980012964059367667, 110391974208576409 },
1268 .{ 9654767503237031099, 11293544302844823188, 11739932712678287805, 112553319146000238 },
1269 .{ 11362964448496095896, 7990659682315657680, 251480263940996374, 114756980673665505 },
1270 .{ 1423410421096377129, 14274395557581462179, 16553482793602208894, 117003787300607788 },
1271 .{ 2070444190619093137, 11517140404712147401, 11657844572835578076, 119294583757094535 },
1272 .{ 7648316884775828921, 15264332483297977688, 247182277434709002, 121630231312217685 },
1273 .{ 17410896758132241352, 10923914482914417070, 13976383996795783649, 124011608097704390 },
1274 .{ 9542674537907272703, 3079432708831728956, 14235189590642919676, 126439609438067572 },
1275 .{ 10364666969937261816, 8464573184892924210, 12758646866025101190, 128915148187220428 },
1276 .{ 14720354822146013883, 11480204489231511423, 7449876034836187038, 131439155071681461 },
1277 .{ 1692907053653558553, 17835392458598425233, 1754856712536736598, 134012579040499057 },
1278 .{ 5620591334531458755, 11361776175667106627, 13350215315297937856, 136636387622027174 },
1279 .{ 17455759733928092601, 10362573084069962561, 11246018728801810510, 139311567287686283 },
1280 .{ 2465404073814044982, 17694822665274381860, 1509954037718722697, 142039123822846312 },
1281 .{ 2152236053329638369, 11202280800589637091, 16388426812920420176, 72410041352485523 },
1282 .{ 17319024055671609028, 10944982848661280484, 2457150158022562661, 73827744744583080 },
1283 .{ 17511219308535248024, 5122059497846768077, 2089605804219668451, 75273205100637900 },
1284 .{ 10082673333144031533, 14429008783411894887, 12842832230171903890, 76746965869337783 },
1285 .{ 16196653406315961184, 10260180891682904501, 10537411930446752461, 78249581139456266 },
1286 .{ 15084422041749743389, 234835370106753111, 16662517110286225617, 79781615848172976 },
1287 .{ 8199644021067702606, 3787318116274991885, 7438130039325743106, 81343645993472659 },
1288 .{ 12039493937039359765, 9773822153580393709, 5945428874398357806, 82936258850702722 },
1289 .{ 984543865091303961, 7975107621689454830, 6556665988501773347, 84560053193370726 },
1290 .{ 9633317878125234244, 16099592426808915028, 9706674539190598200, 86215639518264828 },
1291 .{ 6860695058870476186, 4471839111886709592, 7828342285492709568, 87903640274981819 },
1292 .{ 14583324717644598331, 4496120889473451238, 5290040788305728466, 89624690099949049 },
1293 .{ 18093669366515003715, 12879506572606942994, 18005739787089675377, 91379436055028227 },
1294 .{ 17997493966862379937, 14646222655265145582, 10265023312844161858, 93168537870790806 },
1295 .{ 12283848109039722318, 11290258077250314935, 9878160025624946825, 94992668194556404 },
1296 .{ 8087752761883078164, 5262596608437575693, 11093553063763274413, 96852512843287537 },
1297 .{ 15027787746776840781, 12250273651168257752, 9290470558712181914, 98748771061435726 },
1298 .{ 15003915578366724489, 2937334162439764327, 5404085603526796602, 100682155783835929 },
1299 .{ 5225610465224746757, 14932114897406142027, 2774647558180708010, 102653393903748137 },
1300 .{ 17112957703385190360, 12069082008339002412, 3901112447086388439, 104663226546146909 },
1301 .{ 4062324464323300238, 3992768146772240329, 15757196565593695724, 106712409346361594 },
1302 .{ 5525364615810306701, 11855206026704935156, 11344868740897365300, 108801712734172003 },
1303 .{ 9274143661888462646, 4478365862348432381, 18010077872551661771, 110931922223466333 },
1304 .{ 12604141221930060148, 8930937759942591500, 9382183116147201338, 113103838707570263 },
1305 .{ 14513929377491886653, 1410646149696279084, 587092196850797612, 115318278760358235 },
1306 .{ 2226851524999454362, 7717102471110805679, 7187441550995571734, 117576074943260147 },
1307 .{ 5527526061344932763, 2347100676188369132, 16976241418824030445, 119878076118278875 },
1308 .{ 6088479778147221611, 17669593130014777580, 10991124207197663546, 122225147767136307 },
1309 .{ 11107734086759692041, 3391795220306863431, 17233960908859089158, 124618172316667879 },
1310 .{ 7913172514655155198, 17726879005381242552, 641069866244011540, 127058049470587962 },
1311 .{ 12596991768458713949, 15714785522479904446, 6035972567136116512, 129545696547750811 },
1312 .{ 16901996933781815980, 4275085211437148707, 14091642539965169063, 132082048827034281 },
1313 .{ 7524574627987869240, 15661204384239316051, 2444526454225712267, 134668059898975949 },
1314 .{ 8199251625090479942, 6803282222165044067, 16064817666437851504, 137304702024293857 },
1315 .{ 4453256673338111920, 15269922543084434181, 3139961729834750852, 139992966499426682 },
1316 .{ 15841763546372731299, 3013174075437671812, 4383755396295695606, 142733864029230733 },
1317 .{ 9771896230907310329, 4900659362437687569, 12386126719044266361, 72764212553486967 },
1318 .{ 9420455527449565190, 1859606122611023693, 6555040298902684281, 74188850200884818 },
1319 .{ 5146105983135678095, 2287300449992174951, 4325371679080264751, 75641380576797959 },
1320 .{ 11019359372592553360, 8422686425957443718, 7175176077944048210, 77122349788024458 },
1321 .{ 11005742969399620716, 4132174559240043701, 9372258443096612118, 78632314633490790 },
1322 .{ 8887589641394725840, 8029899502466543662, 14582206497241572853, 80171842813591127 },
1323 .{ 360247523705545899, 12568341805293354211, 14653258284762517866, 81741513143625247 },
1324 .{ 12314272731984275834, 4740745023227177044, 6141631472368337539, 83341915771415304 },
1325 .{ 441052047733984759, 7940090120939869826, 11750200619921094248, 84973652399183278 },
1326 .{ 3436657868127012749, 9187006432149937667, 16389726097323041290, 86637336509772529 },
1327 .{ 13490220260784534044, 15339072891382896702, 8846102360835316895, 88333593597298497 },
1328 .{ 4125672032094859833, 158347675704003277, 10592598512749774447, 90063061402315272 },
1329 .{ 12189928252974395775, 2386931199439295891, 7009030566469913276, 91826390151586454 },
1330 .{ 9256479608339282969, 2844900158963599229, 11148388908923225596, 93624242802550437 },
1331 .{ 11584393507658707408, 2863659090805147914, 9873421561981063551, 95457295292572042 },
1332 .{ 13984297296943171390, 1931468383973130608, 12905719743235082319, 97326236793074198 },
1333 .{ 5837045222254987499, 10213498696735864176, 14893951506257020749, 99231769968645227 },
1334};
1335
1336// Unfortunately, the results are sometimes off by one or two. We use an additional
1337// lookup table to store those cases and adjust the result.
1338const FLOAT128_POW5_ERRORS: [156]u64 = .{
1339 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x9555596400000000,
1340 0x65a6569525565555, 0x4415551445449655, 0x5105015504144541, 0x65a69969a6965964,
1341 0x5054955969959656, 0x5105154515554145, 0x4055511051591555, 0x5500514455550115,
1342 0x0041140014145515, 0x1005440545511051, 0x0014405450411004, 0x0414440010500000,
1343 0x0044000440010040, 0x5551155000004001, 0x4554555454544114, 0x5150045544005441,
1344 0x0001111400054501, 0x6550955555554554, 0x1504159645559559, 0x4105055141454545,
1345 0x1411541410405454, 0x0415555044545555, 0x0014154115405550, 0x1540055040411445,
1346 0x0000000500000000, 0x5644000000000000, 0x1155555591596555, 0x0410440054569565,
1347 0x5145100010010005, 0x0555041405500150, 0x4141450455140450, 0x0000000144000140,
1348 0x5114004001105410, 0x4444100404005504, 0x0414014410001015, 0x5145055155555015,
1349 0x0141041444445540, 0x0000100451541414, 0x4105041104155550, 0x0500501150451145,
1350 0x1001050000004114, 0x5551504400141045, 0x5110545410151454, 0x0100001400004040,
1351 0x5040010111040000, 0x0140000150541100, 0x4400140400104110, 0x5011014405545004,
1352 0x0000000044155440, 0x0000000010000000, 0x1100401444440001, 0x0040401010055111,
1353 0x5155155551405454, 0x0444440015514411, 0x0054505054014101, 0x0451015441115511,
1354 0x1541411401140551, 0x4155104514445110, 0x4141145450145515, 0x5451445055155050,
1355 0x4400515554110054, 0x5111145104501151, 0x565a655455500501, 0x5565555555525955,
1356 0x0550511500405695, 0x4415504051054544, 0x6555595965555554, 0x0100915915555655,
1357 0x5540001510001001, 0x5450051414000544, 0x1405010555555551, 0x5555515555644155,
1358 0x5555055595496555, 0x5451045004415000, 0x5450510144040144, 0x5554155555556455,
1359 0x5051555495415555, 0x5555554555555545, 0x0000000010005455, 0x4000005000040000,
1360 0x5565555555555954, 0x5554559555555505, 0x9645545495552555, 0x4000400055955564,
1361 0x0040000000000001, 0x4004100100000000, 0x5540040440000411, 0x4565555955545644,
1362 0x1140659549651556, 0x0100000410010000, 0x5555515400004001, 0x5955545555155255,
1363 0x5151055545505556, 0x5051454510554515, 0x0501500050415554, 0x5044154005441005,
1364 0x1455445450550455, 0x0010144055144545, 0x0000401100000004, 0x1050145050000010,
1365 0x0415004554011540, 0x1000510100151150, 0x0100040400001144, 0x0000000000000000,
1366 0x0550004400000100, 0x0151145041451151, 0x0000400400005450, 0x0000100044010004,
1367 0x0100054100050040, 0x0504400005410010, 0x4011410445500105, 0x0000404000144411,
1368 0x0101504404500000, 0x0000005044400400, 0x0000000014000100, 0x0404440414000000,
1369 0x5554100410000140, 0x4555455544505555, 0x5454105055455455, 0x0115454155454015,
1370 0x4404110000045100, 0x4400001100101501, 0x6596955956966a94, 0x0040655955665965,
1371 0x5554144400100155, 0xa549495401011041, 0x5596555565955555, 0x5569965959549555,
1372 0x969565a655555456, 0x0000001000000000, 0x0000000040000140, 0x0000040100000000,
1373 0x1415454400000000, 0x5410415411454114, 0x0400040104000154, 0x0504045000000411,
1374 0x0000001000000010, 0x5554000000001040, 0x5549155551556595, 0x1455541055515555,
1375 0x0510555454554541, 0x9555555555540455, 0x6455456555556465, 0x4524565555654514,
1376 0x5554655255559545, 0x9555455441155556, 0x0000000051515555, 0x0010005040000550,
1377 0x5044044040000000, 0x1045040440010500, 0x0000400000040000, 0x0000000000000000,
1378};
1379
1380const FLOAT128_POW5_INV_SPLIT: [89][4]u64 = .{
1381 .{ 0, 0, 0, 144115188075855872 },
1382 .{ 1573859546583440065, 2691002611772552616, 6763753280790178510, 141347765182270746 },
1383 .{ 12960290449513840412, 12345512957918226762, 18057899791198622765, 138633484706040742 },
1384 .{ 7615871757716765416, 9507132263365501332, 4879801712092008245, 135971326161092377 },
1385 .{ 7869961150745287587, 5804035291554591636, 8883897266325833928, 133360288657597085 },
1386 .{ 2942118023529634767, 15128191429820565086, 10638459445243230718, 130799390525667397 },
1387 .{ 14188759758411913794, 5362791266439207815, 8068821289119264054, 128287668946279217 },
1388 .{ 7183196927902545212, 1952291723540117099, 12075928209936341512, 125824179589281448 },
1389 .{ 5672588001402349748, 17892323620748423487, 9874578446960390364, 123407996258356868 },
1390 .{ 4442590541217566325, 4558254706293456445, 10343828952663182727, 121038210542800766 },
1391 .{ 3005560928406962566, 2082271027139057888, 13961184524927245081, 118713931475986426 },
1392 .{ 13299058168408384786, 17834349496131278595, 9029906103900731664, 116434285200389047 },
1393 .{ 5414878118283973035, 13079825470227392078, 17897304791683760280, 114198414639042157 },
1394 .{ 14609755883382484834, 14991702445765844156, 3269802549772755411, 112005479173303009 },
1395 .{ 15967774957605076027, 2511532636717499923, 16221038267832563171, 109854654326805788 },
1396 .{ 9269330061621627145, 3332501053426257392, 16223281189403734630, 107745131455483836 },
1397 .{ 16739559299223642282, 1873986623300664530, 6546709159471442872, 105676117443544318 },
1398 .{ 17116435360051202055, 1359075105581853924, 2038341371621886470, 103646834405281051 },
1399 .{ 17144715798009627550, 3201623802661132408, 9757551605154622431, 101656519392613377 },
1400 .{ 17580479792687825857, 6546633380567327312, 15099972427870912398, 99704424108241124 },
1401 .{ 9726477118325522902, 14578369026754005435, 11728055595254428803, 97789814624307808 },
1402 .{ 134593949518343635, 5715151379816901985, 1660163707976377376, 95911971106466306 },
1403 .{ 5515914027713859358, 7124354893273815720, 5548463282858794077, 94070187543243255 },
1404 .{ 6188403395862945512, 5681264392632320838, 15417410852121406654, 92263771480600430 },
1405 .{ 15908890877468271457, 10398888261125597540, 4817794962769172309, 90492043761593298 },
1406 .{ 1413077535082201005, 12675058125384151580, 7731426132303759597, 88754338271028867 },
1407 .{ 1486733163972670293, 11369385300195092554, 11610016711694864110, 87050001685026843 },
1408 .{ 8788596583757589684, 3978580923851924802, 9255162428306775812, 85378393225389919 },
1409 .{ 7203518319660962120, 15044736224407683725, 2488132019818199792, 83738884418690858 },
1410 .{ 4004175967662388707, 18236988667757575407, 15613100370957482671, 82130858859985791 },
1411 .{ 18371903370586036463, 53497579022921640, 16465963977267203307, 80553711981064899 },
1412 .{ 10170778323887491315, 1999668801648976001, 10209763593579456445, 79006850823153334 },
1413 .{ 17108131712433974546, 16825784443029944237, 2078700786753338945, 77489693813976938 },
1414 .{ 17221789422665858532, 12145427517550446164, 5391414622238668005, 76001670549108934 },
1415 .{ 4859588996898795878, 1715798948121313204, 3950858167455137171, 74542221577515387 },
1416 .{ 13513469241795711526, 631367850494860526, 10517278915021816160, 73110798191218799 },
1417 .{ 11757513142672073111, 2581974932255022228, 17498959383193606459, 143413724438001539 },
1418 .{ 14524355192525042817, 5640643347559376447, 1309659274756813016, 140659771648132296 },
1419 .{ 2765095348461978538, 11021111021896007722, 3224303603779962366, 137958702611185230 },
1420 .{ 12373410389187981037, 13679193545685856195, 11644609038462631561, 135309501808182158 },
1421 .{ 12813176257562780151, 3754199046160268020, 9954691079802960722, 132711173221007413 },
1422 .{ 17557452279667723458, 3237799193992485824, 17893947919029030695, 130162739957935629 },
1423 .{ 14634200999559435155, 4123869946105211004, 6955301747350769239, 127663243886350468 },
1424 .{ 2185352760627740240, 2864813346878886844, 13049218671329690184, 125211745272516185 },
1425 .{ 6143438674322183002, 10464733336980678750, 6982925169933978309, 122807322428266620 },
1426 .{ 1099509117817174576, 10202656147550524081, 754997032816608484, 120449071364478757 },
1427 .{ 2410631293559367023, 17407273750261453804, 15307291918933463037, 118136105451200587 },
1428 .{ 12224968375134586697, 1664436604907828062, 11506086230137787358, 115867555084305488 },
1429 .{ 3495926216898000888, 18392536965197424288, 10992889188570643156, 113642567358547782 },
1430 .{ 8744506286256259680, 3966568369496879937, 18342264969761820037, 111460305746896569 },
1431 .{ 7689600520560455039, 5254331190877624630, 9628558080573245556, 109319949786027263 },
1432 .{ 11862637625618819436, 3456120362318976488, 14690471063106001082, 107220694767852583 },
1433 .{ 5697330450030126444, 12424082405392918899, 358204170751754904, 105161751436977040 },
1434 .{ 11257457505097373622, 15373192700214208870, 671619062372033814, 103142345693961148 },
1435 .{ 16850355018477166700, 1913910419361963966, 4550257919755970531, 101161718304283822 },
1436 .{ 9670835567561997011, 10584031339132130638, 3060560222974851757, 99219124612893520 },
1437 .{ 7698686577353054710, 11689292838639130817, 11806331021588878241, 97313834264240819 },
1438 .{ 12233569599615692137, 3347791226108469959, 10333904326094451110, 95445130927687169 },
1439 .{ 13049400362825383933, 17142621313007799680, 3790542585289224168, 93612312028186576 },
1440 .{ 12430457242474442072, 5625077542189557960, 14765055286236672238, 91814688482138969 },
1441 .{ 4759444137752473128, 2230562561567025078, 4954443037339580076, 90051584438315940 },
1442 .{ 7246913525170274758, 8910297835195760709, 4015904029508858381, 88322337023761438 },
1443 .{ 12854430245836432067, 8135139748065431455, 11548083631386317976, 86626296094571907 },
1444 .{ 4848827254502687803, 4789491250196085625, 3988192420450664125, 84962823991462151 },
1445 .{ 7435538409611286684, 904061756819742353, 14598026519493048444, 83331295300025028 },
1446 .{ 11042616160352530997, 8948390828345326218, 10052651191118271927, 81731096615594853 },
1447 .{ 11059348291563778943, 11696515766184685544, 3783210511290897367, 80161626312626082 },
1448 .{ 7020010856491885826, 5025093219346041680, 8960210401638911765, 78622294318500592 },
1449 .{ 17732844474490699984, 7820866704994446502, 6088373186798844243, 77112521891678506 },
1450 .{ 688278527545590501, 3045610706602776618, 8684243536999567610, 75631741404109150 },
1451 .{ 2734573255120657297, 3903146411440697663, 9470794821691856713, 74179396127820347 },
1452 .{ 15996457521023071259, 4776627823451271680, 12394856457265744744, 72754940025605801 },
1453 .{ 13492065758834518331, 7390517611012222399, 1630485387832860230, 142715675091463768 },
1454 .{ 13665021627282055864, 9897834675523659302, 17907668136755296849, 139975126841173266 },
1455 .{ 9603773719399446181, 10771916301484339398, 10672699855989487527, 137287204938390542 },
1456 .{ 3630218541553511265, 8139010004241080614, 2876479648932814543, 134650898807055963 },
1457 .{ 8318835909686377084, 9525369258927993371, 2796120270400437057, 132065217277054270 },
1458 .{ 11190003059043290163, 12424345635599592110, 12539346395388933763, 129529188211565064 },
1459 .{ 8701968833973242276, 820569587086330727, 2315591597351480110, 127041858141569228 },
1460 .{ 5115113890115690487, 16906305245394587826, 9899749468931071388, 124602291907373862 },
1461 .{ 15543535488939245974, 10945189844466391399, 3553863472349432246, 122209572307020975 },
1462 .{ 7709257252608325038, 1191832167690640880, 15077137020234258537, 119862799751447719 },
1463 .{ 7541333244210021737, 9790054727902174575, 5160944773155322014, 117561091926268545 },
1464 .{ 12297384708782857832, 1281328873123467374, 4827925254630475769, 115303583460052092 },
1465 .{ 13243237906232367265, 15873887428139547641, 3607993172301799599, 113089425598968120 },
1466 .{ 11384616453739611114, 15184114243769211033, 13148448124803481057, 110917785887682141 },
1467 .{ 17727970963596660683, 1196965221832671990, 14537830463956404138, 108787847856377790 },
1468 .{ 17241367586707330931, 8880584684128262874, 11173506540726547818, 106698810713789254 },
1469 .{ 7184427196661305643, 14332510582433188173, 14230167953789677901, 104649889046128358 },
1470};
1471
1472const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{
1473 0x1144155514145504, 0x0000541555401141, 0x0000000000000000, 0x0154454000000000,
1474 0x4114105515544440, 0x0001001111500415, 0x4041411410011000, 0x5550114515155014,
1475 0x1404100041554551, 0x0515000450404410, 0x5054544401140004, 0x5155501005555105,
1476 0x1144141000105515, 0x0541500000500000, 0x1104105540444140, 0x4000015055514110,
1477 0x0054010450004005, 0x4155515404100005, 0x5155145045155555, 0x1511555515440558,
1478 0x5558544555515555, 0x0000000000000010, 0x5004000000000050, 0x1415510100000010,
1479 0x4545555444514500, 0x5155151555555551, 0x1441540144044554, 0x5150104045544400,
1480 0x5450545401444040, 0x5554455045501400, 0x4655155555555145, 0x1000010055455055,
1481 0x1000004000055004, 0x4455405104000005, 0x4500114504150545, 0x0000000014000000,
1482 0x5450000000000000, 0x5514551511445555, 0x4111501040555451, 0x4515445500054444,
1483 0x5101500104100441, 0x1545115155545055, 0x0000000000000000, 0x1554000000100000,
1484 0x5555545595551555, 0x5555051851455955, 0x5555555555555559, 0x0000400011001555,
1485 0x0000004400040000, 0x5455511555554554, 0x5614555544115445, 0x6455156145555155,
1486 0x5455855455415455, 0x5515555144555545, 0x0114400000145155, 0x0000051000450511,
1487 0x4455154554445100, 0x4554150141544455, 0x65955555559a5965, 0x5555555854559559,
1488 0x9569654559616595, 0x1040044040005565, 0x1010010500011044, 0x1554015545154540,
1489 0x4440555401545441, 0x1014441450550105, 0x4545400410504145, 0x5015111541040151,
1490 0x5145051154000410, 0x1040001044545044, 0x4001400000151410, 0x0540000044040000,
1491 0x0510555454411544, 0x0400054054141550, 0x1001041145001100, 0x0000000140000000,
1492 0x0000000014100000, 0x1544005454000140, 0x4050055505445145, 0x0011511104504155,
1493 0x5505544415045055, 0x1155154445515554, 0x0000000000004555, 0x0000000000000000,
1494 0x5101010510400004, 0x1514045044440400, 0x5515519555515555, 0x4554545441555545,
1495 0x1551055955551515, 0x0150000011505515, 0x0044005040400000, 0x0004001004010050,
1496 0x0000051004450414, 0x0114001101001144, 0x0401000001000001, 0x4500010001000401,
1497 0x0004100000005000, 0x0105000441101100, 0x0455455550454540, 0x5404050144105505,
1498 0x4101510540555455, 0x1055541411451555, 0x5451445110115505, 0x1154110010101545,
1499 0x1145140450054055, 0x5555565415551554, 0x1550559555555555, 0x5555541545045141,
1500 0x4555455450500100, 0x5510454545554555, 0x1510140115045455, 0x1001050040111510,
1501 0x5555454555555504, 0x9954155545515554, 0x6596656555555555, 0x0140410051555559,
1502 0x0011104010001544, 0x965669659a680501, 0x5655a55955556955, 0x4015111014404514,
1503 0x1414155554505145, 0x0540040011051404, 0x1010000000015005, 0x0010054050004410,
1504 0x5041104014000100, 0x4440010500100001, 0x1155510504545554, 0x0450151545115541,
1505 0x4000100400110440, 0x1004440010514440, 0x0000115050450000, 0x0545404455541500,
1506 0x1051051555505101, 0x5505144554544144, 0x4550545555515550, 0x0015400450045445,
1507 0x4514155400554415, 0x4555055051050151, 0x1511441450001014, 0x4544554510404414,
1508 0x4115115545545450, 0x5500541555551555, 0x5550010544155015, 0x0144414045545500,
1509 0x4154050001050150, 0x5550511111000145, 0x1114504055000151, 0x5104041101451040,
1510 0x0010501401051441, 0x0010501450504401, 0x4554585440044444, 0x5155555951450455,
1511 0x0040000400105555, 0x0000000000000001,
1512};
1513
1514// zig fmt: on
1515
1516const builtin = @import("builtin");
1517
1518fn check(comptime T: type, value: T, comptime expected: []const u8) !void {
1519 const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
1520
1521 var buf: [6000]u8 = undefined;
1522 const value_bits: I = @bitCast(value);
1523 const s = try render(&buf, value, .{});
1524 try std.testing.expectEqualStrings(expected, s);
1525
1526 if (T == f80 and builtin.target.os.tag == .windows and builtin.target.cpu.arch == .x86_64) return;
1527
1528 const o = try std.fmt.parseFloat(T, s);
1529 const o_bits: I = @bitCast(o);
1530
1531 if (std.math.isNan(value)) {
1532 try std.testing.expect(std.math.isNan(o));
1533 } else {
1534 try std.testing.expectEqual(value_bits, o_bits);
1535 }
1536}
1537
1538test "format f32" {
1539 try check(f32, 0.0, "0e0");
1540 try check(f32, -0.0, "-0e0");
1541 try check(f32, 1.0, "1e0");
1542 try check(f32, -1.0, "-1e0");
1543 try check(f32, std.math.nan(f32), "nan");
1544 try check(f32, std.math.inf(f32), "inf");
1545 try check(f32, -std.math.inf(f32), "-inf");
1546 try check(f32, 1.1754944e-38, "1.1754944e-38");
1547 try check(f32, @bitCast(@as(u32, 0x7f7fffff)), "3.4028235e38");
1548 try check(f32, @bitCast(@as(u32, 1)), "1e-45");
1549 try check(f32, 3.355445E7, "3.355445e7");
1550 try check(f32, 8.999999e9, "9e9");
1551 try check(f32, 3.4366717e10, "3.436672e10");
1552 try check(f32, 3.0540412e5, "3.0540412e5");
1553 try check(f32, 8.0990312e3, "8.0990312e3");
1554 try check(f32, 2.4414062e-4, "2.4414062e-4");
1555 try check(f32, 2.4414062e-3, "2.4414062e-3");
1556 try check(f32, 4.3945312e-3, "4.3945312e-3");
1557 try check(f32, 6.3476562e-3, "6.3476562e-3");
1558 try check(f32, 4.7223665e21, "4.7223665e21");
1559 try check(f32, 8388608.0, "8.388608e6");
1560 try check(f32, 1.6777216e7, "1.6777216e7");
1561 try check(f32, 3.3554436e7, "3.3554436e7");
1562 try check(f32, 6.7131496e7, "6.7131496e7");
1563 try check(f32, 1.9310392e-38, "1.9310392e-38");
1564 try check(f32, -2.47e-43, "-2.47e-43");
1565 try check(f32, 1.993244e-38, "1.993244e-38");
1566 try check(f32, 4103.9003, "4.1039004e3");
1567 try check(f32, 5.3399997e9, "5.3399997e9");
1568 try check(f32, 6.0898e-39, "6.0898e-39");
1569 try check(f32, 0.0010310042, "1.0310042e-3");
1570 try check(f32, 2.8823261e17, "2.882326e17");
1571 try check(f32, 7.038531e-26, "7.038531e-26");
1572 try check(f32, 9.2234038e17, "9.223404e17");
1573 try check(f32, 6.7108872e7, "6.710887e7");
1574 try check(f32, 1.0e-44, "1e-44");
1575 try check(f32, 2.816025e14, "2.816025e14");
1576 try check(f32, 9.223372e18, "9.223372e18");
1577 try check(f32, 1.5846085e29, "1.5846086e29");
1578 try check(f32, 1.1811161e19, "1.1811161e19");
1579 try check(f32, 5.368709e18, "5.368709e18");
1580 try check(f32, 4.6143165e18, "4.6143166e18");
1581 try check(f32, 0.007812537, "7.812537e-3");
1582 try check(f32, 1.4e-45, "1e-45");
1583 try check(f32, 1.18697724e20, "1.18697725e20");
1584 try check(f32, 1.00014165e-36, "1.00014165e-36");
1585 try check(f32, 200.0, "2e2");
1586 try check(f32, 3.3554432e7, "3.3554432e7");
1587
1588 try check(f32, 1.0, "1e0");
1589 try check(f32, 1.2, "1.2e0");
1590 try check(f32, 1.23, "1.23e0");
1591 try check(f32, 1.234, "1.234e0");
1592 try check(f32, 1.2345, "1.2345e0");
1593 try check(f32, 1.23456, "1.23456e0");
1594 try check(f32, 1.234567, "1.234567e0");
1595 try check(f32, 1.2345678, "1.2345678e0");
1596 try check(f32, 1.23456735e-36, "1.23456735e-36");
1597}
1598
1599test "format f64" {
1600 try check(f64, 0.0, "0e0");
1601 try check(f64, -0.0, "-0e0");
1602 try check(f64, 1.0, "1e0");
1603 try check(f64, -1.0, "-1e0");
1604 try check(f64, std.math.nan(f64), "nan");
1605 try check(f64, std.math.inf(f64), "inf");
1606 try check(f64, -std.math.inf(f64), "-inf");
1607 try check(f64, 2.2250738585072014e-308, "2.2250738585072014e-308");
1608 try check(f64, @bitCast(@as(u64, 0x7fefffffffffffff)), "1.7976931348623157e308");
1609 try check(f64, @bitCast(@as(u64, 1)), "5e-324");
1610 try check(f64, 2.98023223876953125e-8, "2.9802322387695312e-8");
1611 try check(f64, -2.109808898695963e16, "-2.109808898695963e16");
1612 try check(f64, 4.940656e-318, "4.940656e-318");
1613 try check(f64, 1.18575755e-316, "1.18575755e-316");
1614 try check(f64, 2.989102097996e-312, "2.989102097996e-312");
1615 try check(f64, 9.0608011534336e15, "9.0608011534336e15");
1616 try check(f64, 4.708356024711512e18, "4.708356024711512e18");
1617 try check(f64, 9.409340012568248e18, "9.409340012568248e18");
1618 try check(f64, 1.2345678, "1.2345678e0");
1619 try check(f64, @bitCast(@as(u64, 0x4830f0cf064dd592)), "5.764607523034235e39");
1620 try check(f64, @bitCast(@as(u64, 0x4840f0cf064dd592)), "1.152921504606847e40");
1621 try check(f64, @bitCast(@as(u64, 0x4850f0cf064dd592)), "2.305843009213694e40");
1622
1623 try check(f64, 1, "1e0");
1624 try check(f64, 1.2, "1.2e0");
1625 try check(f64, 1.23, "1.23e0");
1626 try check(f64, 1.234, "1.234e0");
1627 try check(f64, 1.2345, "1.2345e0");
1628 try check(f64, 1.23456, "1.23456e0");
1629 try check(f64, 1.234567, "1.234567e0");
1630 try check(f64, 1.2345678, "1.2345678e0");
1631 try check(f64, 1.23456789, "1.23456789e0");
1632 try check(f64, 1.234567895, "1.234567895e0");
1633 try check(f64, 1.2345678901, "1.2345678901e0");
1634 try check(f64, 1.23456789012, "1.23456789012e0");
1635 try check(f64, 1.234567890123, "1.234567890123e0");
1636 try check(f64, 1.2345678901234, "1.2345678901234e0");
1637 try check(f64, 1.23456789012345, "1.23456789012345e0");
1638 try check(f64, 1.234567890123456, "1.234567890123456e0");
1639 try check(f64, 1.2345678901234567, "1.2345678901234567e0");
1640
1641 try check(f64, 4.294967294, "4.294967294e0");
1642 try check(f64, 4.294967295, "4.294967295e0");
1643 try check(f64, 4.294967296, "4.294967296e0");
1644 try check(f64, 4.294967297, "4.294967297e0");
1645 try check(f64, 4.294967298, "4.294967298e0");
1646}
1647
1648test "format f80" {
1649 try check(f80, 0.0, "0e0");
1650 try check(f80, -0.0, "-0e0");
1651 try check(f80, 1.0, "1e0");
1652 try check(f80, -1.0, "-1e0");
1653 try check(f80, std.math.nan(f80), "nan");
1654 try check(f80, std.math.inf(f80), "inf");
1655 try check(f80, -std.math.inf(f80), "-inf");
1656
1657 try check(f80, 2.2250738585072014e-308, "2.2250738585072014e-308");
1658 try check(f80, 2.98023223876953125e-8, "2.98023223876953125e-8");
1659 try check(f80, -2.109808898695963e16, "-2.109808898695963e16");
1660 try check(f80, 4.940656e-318, "4.940656e-318");
1661 try check(f80, 1.18575755e-316, "1.18575755e-316");
1662 try check(f80, 2.989102097996e-312, "2.989102097996e-312");
1663 try check(f80, 9.0608011534336e15, "9.0608011534336e15");
1664 try check(f80, 4.708356024711512e18, "4.708356024711512e18");
1665 try check(f80, 9.409340012568248e18, "9.409340012568248e18");
1666 try check(f80, 1.2345678, "1.2345678e0");
1667}
1668
1669test "format f128" {
1670 try check(f128, 0.0, "0e0");
1671 try check(f128, -0.0, "-0e0");
1672 try check(f128, 1.0, "1e0");
1673 try check(f128, -1.0, "-1e0");
1674 try check(f128, std.math.nan(f128), "nan");
1675 try check(f128, std.math.inf(f128), "inf");
1676 try check(f128, -std.math.inf(f128), "-inf");
1677
1678 try check(f128, 2.2250738585072014e-308, "2.2250738585072014e-308");
1679 try check(f128, 2.98023223876953125e-8, "2.98023223876953125e-8");
1680 try check(f128, -2.109808898695963e16, "-2.109808898695963e16");
1681 try check(f128, 4.940656e-318, "4.940656e-318");
1682 try check(f128, 1.18575755e-316, "1.18575755e-316");
1683 try check(f128, 2.989102097996e-312, "2.989102097996e-312");
1684 try check(f128, 9.0608011534336e15, "9.0608011534336e15");
1685 try check(f128, 4.708356024711512e18, "4.708356024711512e18");
1686 try check(f128, 9.409340012568248e18, "9.409340012568248e18");
1687 try check(f128, 1.2345678, "1.2345678e0");
1688}
1689
1690test "format float to decimal with zero precision" {
1691 try expectFmt("5", "{d:.0}", .{5});
1692 try expectFmt("6", "{d:.0}", .{6});
1693 try expectFmt("7", "{d:.0}", .{7});
1694 try expectFmt("8", "{d:.0}", .{8});
1695}
lib/std/fmt/format_float.zig deleted-1695
......@@ -1,1695 +0,0 @@
1//! This file implements the ryu floating point conversion algorithm:
2//! https://dl.acm.org/doi/pdf/10.1145/3360595
3
4const std = @import("std");
5const expectFmt = std.testing.expectFmt;
6
7const special_exponent = 0x7fffffff;
8
9/// Any buffer used for `format` must be at least this large. This is asserted. A runtime check will
10/// additionally be performed if more bytes are required.
11pub const min_buffer_size = 53;
12
13/// Returns the minimum buffer size needed to print every float of a specific type and format.
14pub fn bufferSize(comptime mode: Format, comptime T: type) comptime_int {
15 comptime std.debug.assert(@typeInfo(T) == .float);
16 return switch (mode) {
17 .scientific => 53,
18 // Based on minimum subnormal values.
19 .decimal => switch (@bitSizeOf(T)) {
20 16 => @max(15, min_buffer_size),
21 32 => 55,
22 64 => 347,
23 80 => 4996,
24 128 => 5011,
25 else => unreachable,
26 },
27 };
28}
29
30pub const FormatError = error{
31 BufferTooSmall,
32};
33
34pub const Format = enum {
35 scientific,
36 decimal,
37};
38
39pub const FormatOptions = struct {
40 mode: Format = .scientific,
41 precision: ?usize = null,
42};
43
44/// Format a floating-point value and write it to buffer. Returns a slice to the buffer containing
45/// the string representation.
46///
47/// Full precision is the default. Any full precision float can be reparsed with std.fmt.parseFloat
48/// unambiguously.
49///
50/// Scientific mode is recommended generally as the output is more compact and any type can be
51/// written in full precision using a buffer of only `min_buffer_size`.
52///
53/// When printing full precision decimals, use `bufferSize` to get the required space. It is
54/// recommended to bound decimal output with a fixed precision to reduce the required buffer size.
55pub fn formatFloat(buf: []u8, v_: anytype, options: FormatOptions) FormatError![]const u8 {
56 const v = switch (@TypeOf(v_)) {
57 // comptime_float internally is a f128; this preserves precision.
58 comptime_float => @as(f128, v_),
59 else => v_,
60 };
61
62 const T = @TypeOf(v);
63 comptime std.debug.assert(@typeInfo(T) == .float);
64 const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
65
66 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
67 const tables = switch (DT) {
68 u64 => if (@import("builtin").mode == .ReleaseSmall) &Backend64_TablesSmall else &Backend64_TablesFull,
69 u128 => &Backend128_Tables,
70 else => unreachable,
71 };
72
73 const has_explicit_leading_bit = std.math.floatMantissaBits(T) - std.math.floatFractionalBits(T) != 0;
74 const d = binaryToDecimal(DT, @as(I, @bitCast(v)), std.math.floatMantissaBits(T), std.math.floatExponentBits(T), has_explicit_leading_bit, tables);
75
76 return switch (options.mode) {
77 .scientific => formatScientific(DT, buf, d, options.precision),
78 .decimal => formatDecimal(DT, buf, d, options.precision),
79 };
80}
81
82pub fn FloatDecimal(comptime T: type) type {
83 comptime std.debug.assert(T == u64 or T == u128);
84 return struct {
85 mantissa: T,
86 exponent: i32,
87 sign: bool,
88 };
89}
90
91fn copySpecialStr(buf: []u8, f: anytype) []const u8 {
92 if (f.sign) {
93 buf[0] = '-';
94 }
95 const offset: usize = @intFromBool(f.sign);
96 if (f.mantissa != 0) {
97 @memcpy(buf[offset..][0..3], "nan");
98 return buf[0 .. 3 + offset];
99 }
100 @memcpy(buf[offset..][0..3], "inf");
101 return buf[0 .. 3 + offset];
102}
103
104fn writeDecimal(buf: []u8, value: anytype, count: usize) void {
105 var i: usize = 0;
106
107 while (i + 2 < count) : (i += 2) {
108 const c: u8 = @intCast(value.* % 100);
109 value.* /= 100;
110 const d = std.fmt.digits2(c);
111 buf[count - i - 1] = d[1];
112 buf[count - i - 2] = d[0];
113 }
114
115 while (i < count) : (i += 1) {
116 const c: u8 = @intCast(value.* % 10);
117 value.* /= 10;
118 buf[count - i - 1] = '0' + c;
119 }
120}
121
122fn isPowerOf10(n_: u128) bool {
123 var n = n_;
124 while (n != 0) : (n /= 10) {
125 if (n % 10 != 0) return false;
126 }
127 return true;
128}
129
130const RoundMode = enum {
131 /// 1234.56 = precision 2
132 decimal,
133 /// 1.23456e3 = precision 5
134 scientific,
135};
136
137fn round(comptime T: type, f: FloatDecimal(T), mode: RoundMode, precision: usize) FloatDecimal(T) {
138 var round_digit: usize = 0;
139 var output = f.mantissa;
140 var exp = f.exponent;
141 const olength = decimalLength(output);
142
143 switch (mode) {
144 .decimal => {
145 if (f.exponent > 0) {
146 round_digit = (olength - 1) + precision + @as(usize, @intCast(f.exponent));
147 } else {
148 const min_exp_required = @as(usize, @intCast(-f.exponent));
149 if (precision + olength > min_exp_required) {
150 round_digit = precision + olength - min_exp_required;
151 }
152 }
153 },
154 .scientific => {
155 round_digit = 1 + precision;
156 },
157 }
158
159 if (round_digit < olength) {
160 var nlength = olength;
161 for (round_digit + 1..olength) |_| {
162 output /= 10;
163 exp += 1;
164 nlength -= 1;
165 }
166
167 if (output % 10 >= 5) {
168 output /= 10;
169 output += 1;
170 exp += 1;
171
172 // e.g. 9999 -> 10000
173 if (isPowerOf10(output)) {
174 output /= 10;
175 exp += 1;
176 }
177 }
178 }
179
180 return .{
181 .mantissa = output,
182 .exponent = exp,
183 .sign = f.sign,
184 };
185}
186
187/// Write a FloatDecimal to a buffer in scientific form.
188///
189/// The buffer provided must be greater than `min_buffer_size` in length. If no precision is
190/// specified, this function will never return an error. If a precision is specified, up to
191/// `8 + precision` bytes will be written to the buffer. An error will be returned if the content
192/// will not fit.
193///
194/// It is recommended to bound decimal formatting with an exact precision.
195pub fn formatScientific(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) FormatError![]const u8 {
196 std.debug.assert(buf.len >= min_buffer_size);
197 var f = f_;
198
199 if (f.exponent == special_exponent) {
200 return copySpecialStr(buf, f);
201 }
202
203 if (precision) |prec| {
204 f = round(T, f, .scientific, prec);
205 }
206
207 var output = f.mantissa;
208 const olength = decimalLength(output);
209
210 if (precision) |prec| {
211 // fixed bound: sign(1) + leading_digit(1) + point(1) + exp_sign(1) + exp_max(4)
212 const req_bytes = 8 + prec;
213 if (buf.len < req_bytes) {
214 return error.BufferTooSmall;
215 }
216 }
217
218 // Step 5: Print the scientific representation
219 var index: usize = 0;
220 if (f.sign) {
221 buf[index] = '-';
222 index += 1;
223 }
224
225 // 1.12345
226 writeDecimal(buf[index + 2 ..], &output, olength - 1);
227 buf[index] = '0' + @as(u8, @intCast(output % 10));
228 buf[index + 1] = '.';
229 index += 2;
230 const dp_index = index;
231 if (olength > 1) index += olength - 1 else index -= 1;
232
233 if (precision) |prec| {
234 index += @intFromBool(olength == 1);
235 if (prec > olength - 1) {
236 const len = prec - (olength - 1);
237 @memset(buf[index..][0..len], '0');
238 index += len;
239 } else {
240 index = dp_index + prec - @intFromBool(prec == 0);
241 }
242 }
243
244 // e100
245 buf[index] = 'e';
246 index += 1;
247 var exp = f.exponent + @as(i32, @intCast(olength)) - 1;
248 if (exp < 0) {
249 buf[index] = '-';
250 index += 1;
251 exp = -exp;
252 }
253 var uexp: u32 = @intCast(exp);
254 const elength = decimalLength(uexp);
255 writeDecimal(buf[index..], &uexp, elength);
256 index += elength;
257
258 return buf[0..index];
259}
260
261/// Write a FloatDecimal to a buffer in decimal form.
262///
263/// The buffer provided must be greater than `min_buffer_size` bytes in length. If no precision is
264/// specified, this may still return an error. If precision is specified, `2 + precision` bytes will
265/// always be written.
266pub fn formatDecimal(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) FormatError![]const u8 {
267 std.debug.assert(buf.len >= min_buffer_size);
268 var f = f_;
269
270 if (f.exponent == special_exponent) {
271 return copySpecialStr(buf, f);
272 }
273
274 if (precision) |prec| {
275 f = round(T, f, .decimal, prec);
276 }
277
278 var output = f.mantissa;
279 const olength = decimalLength(output);
280
281 // fixed bound: leading_digit(1) + point(1)
282 const req_bytes = if (f.exponent >= 0)
283 @as(usize, 2) + @abs(f.exponent) + olength + (precision orelse 0)
284 else
285 @as(usize, 2) + @max(@abs(f.exponent) + olength, precision orelse 0);
286 if (buf.len < req_bytes) {
287 return error.BufferTooSmall;
288 }
289
290 // Step 5: Print the decimal representation
291 var index: usize = 0;
292 if (f.sign) {
293 buf[index] = '-';
294 index += 1;
295 }
296
297 const dp_offset = f.exponent + cast_i32(olength);
298 if (dp_offset <= 0) {
299 // 0.000001234
300 buf[index] = '0';
301 buf[index + 1] = '.';
302 index += 2;
303 const dp_index = index;
304
305 const dp_poffset: u32 = @intCast(-dp_offset);
306 @memset(buf[index..][0..dp_poffset], '0');
307 index += dp_poffset;
308 writeDecimal(buf[index..], &output, olength);
309 index += olength;
310
311 if (precision) |prec| {
312 const dp_written = index - dp_index;
313 if (prec > dp_written) {
314 @memset(buf[index..][0 .. prec - dp_written], '0');
315 }
316 index = dp_index + prec - @intFromBool(prec == 0);
317 }
318 } else {
319 // 123456000
320 const dp_uoffset: usize = @intCast(dp_offset);
321 if (dp_uoffset >= olength) {
322 writeDecimal(buf[index..], &output, olength);
323 index += olength;
324 @memset(buf[index..][0 .. dp_uoffset - olength], '0');
325 index += dp_uoffset - olength;
326
327 if (precision) |prec| {
328 if (prec != 0) {
329 buf[index] = '.';
330 index += 1;
331 @memset(buf[index..][0..prec], '0');
332 index += prec;
333 }
334 }
335 } else {
336 // 12345.6789
337 writeDecimal(buf[index + dp_uoffset + 1 ..], &output, olength - dp_uoffset);
338 buf[index + dp_uoffset] = '.';
339 const dp_index = index + dp_uoffset + 1;
340 writeDecimal(buf[index..], &output, dp_uoffset);
341 index += olength + 1;
342
343 if (precision) |prec| {
344 const dp_written = olength - dp_uoffset;
345 if (prec > dp_written) {
346 @memset(buf[index..][0 .. prec - dp_written], '0');
347 }
348 index = dp_index + prec - @intFromBool(prec == 0);
349 }
350 }
351 }
352
353 return buf[0..index];
354}
355
356fn cast_i32(v: anytype) i32 {
357 return @intCast(v);
358}
359
360/// Convert a binary float representation to decimal.
361pub fn binaryToDecimal(comptime T: type, bits: T, mantissa_bits: std.math.Log2Int(T), exponent_bits: u5, explicit_leading_bit: bool, comptime tables: anytype) FloatDecimal(T) {
362 if (T != tables.T) {
363 @compileError("table type does not match backend type: " ++ @typeName(tables.T) ++ " != " ++ @typeName(T));
364 }
365
366 const bias = (@as(u32, 1) << (exponent_bits - 1)) - 1;
367 const ieee_sign = ((bits >> (mantissa_bits + exponent_bits)) & 1) != 0;
368 const ieee_mantissa = bits & ((@as(T, 1) << mantissa_bits) - 1);
369 const ieee_exponent: u32 = @intCast((bits >> mantissa_bits) & ((@as(T, 1) << exponent_bits) - 1));
370
371 if (ieee_exponent == 0 and ieee_mantissa == 0) {
372 return .{
373 .mantissa = 0,
374 .exponent = 0,
375 .sign = ieee_sign,
376 };
377 }
378 if (ieee_exponent == ((@as(u32, 1) << exponent_bits) - 1)) {
379 return .{
380 .mantissa = if (explicit_leading_bit) ieee_mantissa & ((@as(T, 1) << (mantissa_bits - 1)) - 1) else ieee_mantissa,
381 .exponent = special_exponent,
382 .sign = ieee_sign,
383 };
384 }
385
386 var e2: i32 = undefined;
387 var m2: T = undefined;
388 if (explicit_leading_bit) {
389 if (ieee_exponent == 0) {
390 e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2;
391 } else {
392 e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2;
393 }
394 m2 = ieee_mantissa;
395 } else {
396 if (ieee_exponent == 0) {
397 e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) - 2;
398 m2 = ieee_mantissa;
399 } else {
400 e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) - 2;
401 m2 = (@as(T, 1) << mantissa_bits) | ieee_mantissa;
402 }
403 }
404 const even = (m2 & 1) == 0;
405 const accept_bounds = even;
406
407 // Step 2: Determine the interval of legal decimal representations.
408 const mv = 4 * m2;
409 const mm_shift: u1 = @intFromBool((ieee_mantissa != if (explicit_leading_bit) (@as(T, 1) << (mantissa_bits - 1)) else 0) or (ieee_exponent == 0));
410
411 // Step 3: Convert to a decimal power base using 128-bit arithmetic.
412 var vr: T = undefined;
413 var vp: T = undefined;
414 var vm: T = undefined;
415 var e10: i32 = undefined;
416 var vm_is_trailing_zeros = false;
417 var vr_is_trailing_zeros = false;
418 if (e2 >= 0) {
419 const q: u32 = log10Pow2(@intCast(e2)) - @intFromBool(e2 > 3);
420 e10 = cast_i32(q);
421 const k: i32 = @intCast(tables.POW5_INV_BITCOUNT + pow5Bits(q) - 1);
422 const i: u32 = @intCast(-e2 + cast_i32(q) + k);
423
424 const pow5 = tables.computeInvPow5(q);
425 vr = tables.mulShift(4 * m2, &pow5, i);
426 vp = tables.mulShift(4 * m2 + 2, &pow5, i);
427 vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, i);
428
429 if (q <= tables.bound1) {
430 if (mv % 5 == 0) {
431 vr_is_trailing_zeros = multipleOfPowerOf5(mv, if (tables.adjust_q) q -% 1 else q);
432 } else if (accept_bounds) {
433 vm_is_trailing_zeros = multipleOfPowerOf5(mv - 1 - mm_shift, q);
434 } else {
435 vp -= @intFromBool(multipleOfPowerOf5(mv + 2, q));
436 }
437 }
438 } else {
439 const q: u32 = log10Pow5(@intCast(-e2)) - @intFromBool(-e2 > 1);
440 e10 = cast_i32(q) + e2;
441 const i: i32 = -e2 - cast_i32(q);
442 const k: i32 = cast_i32(pow5Bits(@intCast(i))) - tables.POW5_BITCOUNT;
443 const j: u32 = @intCast(cast_i32(q) - k);
444
445 const pow5 = tables.computePow5(@intCast(i));
446 vr = tables.mulShift(4 * m2, &pow5, j);
447 vp = tables.mulShift(4 * m2 + 2, &pow5, j);
448 vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, j);
449
450 if (q <= 1) {
451 vr_is_trailing_zeros = true;
452 if (accept_bounds) {
453 vm_is_trailing_zeros = mm_shift == 1;
454 } else {
455 vp -= 1;
456 }
457 } else if (q < tables.bound2) {
458 vr_is_trailing_zeros = multipleOfPowerOf2(mv, if (tables.adjust_q) q - 1 else q);
459 }
460 }
461
462 // Step 4: Find the shortest decimal representation in the interval of legal representations.
463 var removed: u32 = 0;
464 var last_removed_digit: u8 = 0;
465
466 while (vp / 10 > vm / 10) {
467 vm_is_trailing_zeros = vm_is_trailing_zeros and vm % 10 == 0;
468 vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0;
469 last_removed_digit = @intCast(vr % 10);
470 vr /= 10;
471 vp /= 10;
472 vm /= 10;
473 removed += 1;
474 }
475
476 if (vm_is_trailing_zeros) {
477 while (vm % 10 == 0) {
478 vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0;
479 last_removed_digit = @intCast(vr % 10);
480 vr /= 10;
481 vp /= 10;
482 vm /= 10;
483 removed += 1;
484 }
485 }
486
487 if (vr_is_trailing_zeros and (last_removed_digit == 5) and (vr % 2 == 0)) {
488 last_removed_digit = 4;
489 }
490
491 return .{
492 .mantissa = vr + @intFromBool((vr == vm and (!accept_bounds or !vm_is_trailing_zeros)) or last_removed_digit >= 5),
493 .exponent = e10 + cast_i32(removed),
494 .sign = ieee_sign,
495 };
496}
497
498fn decimalLength(v: anytype) u32 {
499 switch (@TypeOf(v)) {
500 u32, u64 => {
501 std.debug.assert(v < 100000000000000000);
502 if (v >= 10000000000000000) return 17;
503 if (v >= 1000000000000000) return 16;
504 if (v >= 100000000000000) return 15;
505 if (v >= 10000000000000) return 14;
506 if (v >= 1000000000000) return 13;
507 if (v >= 100000000000) return 12;
508 if (v >= 10000000000) return 11;
509 if (v >= 1000000000) return 10;
510 if (v >= 100000000) return 9;
511 if (v >= 10000000) return 8;
512 if (v >= 1000000) return 7;
513 if (v >= 100000) return 6;
514 if (v >= 10000) return 5;
515 if (v >= 1000) return 4;
516 if (v >= 100) return 3;
517 if (v >= 10) return 2;
518 return 1;
519 },
520 u128 => {
521 const LARGEST_POW10 = (@as(u128, 5421010862427522170) << 64) | 687399551400673280;
522 var p10 = LARGEST_POW10;
523 var i: u32 = 39;
524 while (i > 0) : (i -= 1) {
525 if (v >= p10) return i;
526 p10 /= 10;
527 }
528 return 1;
529 },
530 else => unreachable,
531 }
532}
533
534// floor(log_10(2^e))
535fn log10Pow2(e: u32) u32 {
536 std.debug.assert(e <= 1 << 15);
537 return @intCast((@as(u64, @intCast(e)) * 169464822037455) >> 49);
538}
539
540// floor(log_10(5^e))
541fn log10Pow5(e: u32) u32 {
542 std.debug.assert(e <= 1 << 15);
543 return @intCast((@as(u64, @intCast(e)) * 196742565691928) >> 48);
544}
545
546// if (e == 0) 1 else ceil(log_2(5^e))
547fn pow5Bits(e: u32) u32 {
548 std.debug.assert(e <= 1 << 15);
549 return @intCast(((@as(u64, @intCast(e)) * 163391164108059) >> 46) + 1);
550}
551
552fn pow5Factor(value_: anytype) u32 {
553 var count: u32 = 0;
554 var value = value_;
555 while (value > 0) : ({
556 count += 1;
557 value /= 5;
558 }) {
559 if (value % 5 != 0) return count;
560 }
561 return 0;
562}
563
564fn multipleOfPowerOf5(value: anytype, p: u32) bool {
565 const T = @TypeOf(value);
566 std.debug.assert(@typeInfo(T) == .int);
567 return pow5Factor(value) >= p;
568}
569
570fn multipleOfPowerOf2(value: anytype, p: u32) bool {
571 const T = @TypeOf(value);
572 std.debug.assert(@typeInfo(T) == .int);
573 return (value & ((@as(T, 1) << @as(std.math.Log2Int(T), @intCast(p))) - 1)) == 0;
574}
575
576fn mulShift128(m: u128, mul: *const [4]u64, j: u32) u128 {
577 std.debug.assert(j > 128);
578 const a: [2]u64 = .{ @truncate(m), @truncate(m >> 64) };
579 const r = mul_128_256_shift(&a, mul, j, 0);
580 return (@as(u128, r[1]) << 64) | r[0];
581}
582
583fn mul_128_256_shift(a: *const [2]u64, b: *const [4]u64, shift: u32, corr: u32) [4]u64 {
584 std.debug.assert(shift > 0);
585 std.debug.assert(shift < 256);
586
587 const b00 = @as(u128, a[0]) * b[0];
588 const b01 = @as(u128, a[0]) * b[1];
589 const b02 = @as(u128, a[0]) * b[2];
590 const b03 = @as(u128, a[0]) * b[3];
591 const b10 = @as(u128, a[1]) * b[0];
592 const b11 = @as(u128, a[1]) * b[1];
593 const b12 = @as(u128, a[1]) * b[2];
594 const b13 = @as(u128, a[1]) * b[3];
595
596 const s0 = b00;
597 const s1 = b01 +% b10;
598 const c1: u128 = @intFromBool(s1 < b01);
599 const s2 = b02 +% b11;
600 const c2: u128 = @intFromBool(s2 < b02);
601 const s3 = b03 +% b12;
602 const c3: u128 = @intFromBool(s3 < b03);
603
604 const p0 = s0 +% (s1 << 64);
605 const d0: u128 = @intFromBool(p0 < b00);
606 const q1 = s2 +% (s1 >> 64) +% (s3 << 64);
607 const d1: u128 = @intFromBool(q1 < s2);
608 const p1 = q1 +% (c1 << 64) +% d0;
609 const d2: u128 = @intFromBool(p1 < q1);
610 const p2 = b13 +% (s3 >> 64) +% c2 +% (c3 << 64) +% d1 +% d2;
611
612 var r0: u128 = undefined;
613 var r1: u128 = undefined;
614 if (shift < 128) {
615 const cshift: u7 = @intCast(shift);
616 const sshift: u7 = @intCast(128 - shift);
617 r0 = corr +% ((p0 >> cshift) | (p1 << sshift));
618 r1 = ((p1 >> cshift) | (p2 << sshift)) +% @intFromBool(r0 < corr);
619 } else if (shift == 128) {
620 r0 = corr +% p1;
621 r1 = p2 +% @intFromBool(r0 < corr);
622 } else {
623 const ashift: u7 = @intCast(shift - 128);
624 const sshift: u7 = @intCast(256 - shift);
625 r0 = corr +% ((p1 >> ashift) | (p2 << sshift));
626 r1 = (p2 >> ashift) +% @intFromBool(r0 < corr);
627 }
628
629 return .{ @truncate(r0), @truncate(r0 >> 64), @truncate(r1), @truncate(r1 >> 64) };
630}
631
632pub const Backend128_Tables = struct {
633 const T = u128;
634 const mulShift = mulShift128;
635 const POW5_INV_BITCOUNT = FLOAT128_POW5_INV_BITCOUNT;
636 const POW5_BITCOUNT = FLOAT128_POW5_BITCOUNT;
637
638 const bound1 = 55;
639 const bound2 = 127;
640 const adjust_q = true;
641
642 fn computePow5(i: u32) [4]u64 {
643 const base = i / FLOAT128_POW5_TABLE_SIZE;
644 const base2 = base * FLOAT128_POW5_TABLE_SIZE;
645 const mul = &FLOAT128_POW5_SPLIT[base];
646 if (i == base2) {
647 return mul.*;
648 } else {
649 const offset = i - base2;
650 const m = &FLOAT128_POW5_TABLE[offset];
651 const delta = pow5Bits(i) - pow5Bits(base2);
652
653 const shift: u6 = @intCast(2 * (i % 32));
654 const corr: u32 = @intCast((FLOAT128_POW5_ERRORS[i / 32] >> shift) & 3);
655 return mul_128_256_shift(m, mul, delta, corr);
656 }
657 }
658
659 fn computeInvPow5(i: u32) [4]u64 {
660 const base = (i + FLOAT128_POW5_TABLE_SIZE - 1) / FLOAT128_POW5_TABLE_SIZE;
661 const base2 = base * FLOAT128_POW5_TABLE_SIZE;
662 const mul = &FLOAT128_POW5_INV_SPLIT[base]; // 1 / 5^base2
663 if (i == base2) {
664 return .{ mul[0] + 1, mul[1], mul[2], mul[3] };
665 } else {
666 const offset = base2 - i;
667 const m = &FLOAT128_POW5_TABLE[offset]; // 5^offset
668 const delta = pow5Bits(base2) - pow5Bits(i);
669
670 const shift: u6 = @intCast(2 * (i % 32));
671 const corr: u32 = @intCast(((FLOAT128_POW5_INV_ERRORS[i / 32] >> shift) & 3) + 1);
672 return mul_128_256_shift(m, mul, delta, corr);
673 }
674 }
675};
676
677fn mulShift64(m: u64, mul: *const [2]u64, j: u32) u64 {
678 std.debug.assert(j > 64);
679 const b0 = @as(u128, m) * mul[0];
680 const b2 = @as(u128, m) * mul[1];
681
682 if (j < 128) {
683 const shift: u6 = @intCast(j - 64);
684 return @intCast(((b0 >> 64) + b2) >> shift);
685 } else {
686 return 0;
687 }
688}
689
690pub const Backend64_TablesFull = struct {
691 const T = u64;
692 const mulShift = mulShift64;
693 const POW5_INV_BITCOUNT = FLOAT64_POW5_INV_BITCOUNT;
694 const POW5_BITCOUNT = FLOAT64_POW5_BITCOUNT;
695
696 const bound1 = 21;
697 const bound2 = 63;
698 const adjust_q = false;
699
700 fn computePow5(i: u32) [2]u64 {
701 return FLOAT64_POW5_SPLIT[i];
702 }
703
704 fn computeInvPow5(i: u32) [2]u64 {
705 return FLOAT64_POW5_INV_SPLIT[i];
706 }
707};
708
709pub const Backend64_TablesSmall = struct {
710 const T = u64;
711 const mulShift = mulShift64;
712 const POW5_INV_BITCOUNT = FLOAT64_POW5_INV_BITCOUNT;
713 const POW5_BITCOUNT = FLOAT64_POW5_BITCOUNT;
714
715 const bound1 = 21;
716 const bound2 = 63;
717 const adjust_q = false;
718
719 fn computePow5(i: u32) [2]u64 {
720 const base = i / FLOAT64_POW5_TABLE_SIZE;
721 const base2 = base * FLOAT64_POW5_TABLE_SIZE;
722 const mul = &FLOAT64_POW5_SPLIT2[base];
723 if (i == base2) {
724 return .{ mul[0], mul[1] };
725 } else {
726 const offset = i - base2;
727 const m = FLOAT64_POW5_TABLE[offset];
728 const b0 = @as(u128, m) * mul[0];
729 const b2 = @as(u128, m) * mul[1];
730 const delta: u7 = @intCast(pow5Bits(i) - pow5Bits(base2));
731 const shift: u5 = @intCast((i % 16) << 1);
732 const shifted_sum = ((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((FLOAT64_POW5_OFFSETS[i / 16] >> shift) & 3);
733 return .{ @truncate(shifted_sum), @truncate(shifted_sum >> 64) };
734 }
735 }
736
737 fn computeInvPow5(i: u32) [2]u64 {
738 const base = (i + FLOAT64_POW5_TABLE_SIZE - 1) / FLOAT64_POW5_TABLE_SIZE;
739 const base2 = base * FLOAT64_POW5_TABLE_SIZE;
740 const mul = &FLOAT64_POW5_INV_SPLIT2[base]; // 1 / 5^base2
741 if (i == base2) {
742 return .{ mul[0], mul[1] };
743 } else {
744 const offset = base2 - i;
745 const m = FLOAT64_POW5_TABLE[offset]; // 5^offset
746 const b0 = @as(u128, m) * (mul[0] - 1);
747 const b2 = @as(u128, m) * mul[1]; // 1/5^base2 * 5^offset = 1/5^(base2-offset) = 1/5^i
748 const delta: u7 = @intCast(pow5Bits(base2) - pow5Bits(i));
749 const shift: u5 = @intCast((i % 16) << 1);
750 const shifted_sum = ((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((FLOAT64_POW5_INV_OFFSETS[i / 16] >> shift) & 3);
751 return .{ @truncate(shifted_sum), @truncate(shifted_sum >> 64) };
752 }
753 }
754};
755
756const FLOAT64_POW5_INV_BITCOUNT = 125;
757const FLOAT64_POW5_BITCOUNT = 125;
758
759// zig fmt: off
760//
761// f64 small tables: 816 bytes
762
763const FLOAT64_POW5_TABLE_SIZE: comptime_int = FLOAT64_POW5_TABLE.len;
764
765const FLOAT64_POW5_TABLE: [26]u64 = .{
766 1, 5,
767 25, 125,
768 625, 3125,
769 15625, 78125,
770 390625, 1953125,
771 9765625, 48828125,
772 244140625, 1220703125,
773 6103515625, 30517578125,
774 152587890625, 762939453125,
775 3814697265625, 19073486328125,
776 95367431640625, 476837158203125,
777 2384185791015625, 11920928955078125,
778 59604644775390625, 298023223876953125,
779};
780
781const FLOAT64_POW5_SPLIT2: [13][2]u64 = .{
782 .{ 0, 1152921504606846976 },
783 .{ 0, 1490116119384765625 },
784 .{ 1032610780636961552, 1925929944387235853 },
785 .{ 7910200175544436838, 1244603055572228341 },
786 .{ 16941905809032713930, 1608611746708759036 },
787 .{ 13024893955298202172, 2079081953128979843 },
788 .{ 6607496772837067824, 1343575221513417750 },
789 .{ 17332926989895652603, 1736530273035216783 },
790 .{ 13037379183483547984, 2244412773384604712 },
791 .{ 1605989338741628675, 1450417759929778918 },
792 .{ 9630225068416591280, 1874621017369538693 },
793 .{ 665883850346957067, 1211445438634777304 },
794 .{ 14931890668723713708, 1565756531257009982 }
795};
796
797const FLOAT64_POW5_OFFSETS: [21]u32 = .{
798 0x00000000, 0x00000000, 0x00000000, 0x00000000,
799 0x40000000, 0x59695995, 0x55545555, 0x56555515,
800 0x41150504, 0x40555410, 0x44555145, 0x44504540,
801 0x45555550, 0x40004000, 0x96440440, 0x55565565,
802 0x54454045, 0x40154151, 0x55559155, 0x51405555,
803 0x00000105,
804};
805
806const FLOAT64_POW5_INV_SPLIT2: [15][2]u64 = .{
807 .{ 1, 2305843009213693952 },
808 .{ 5955668970331000884, 1784059615882449851 },
809 .{ 8982663654677661702, 1380349269358112757 },
810 .{ 7286864317269821294, 2135987035920910082 },
811 .{ 7005857020398200553, 1652639921975621497 },
812 .{ 17965325103354776697, 1278668206209430417 },
813 .{ 8928596168509315048, 1978643211784836272 },
814 .{ 10075671573058298858, 1530901034580419511 },
815 .{ 597001226353042382, 1184477304306571148 },
816 .{ 1527430471115325346, 1832889850782397517 },
817 .{ 12533209867169019542, 1418129833677084982 },
818 .{ 5577825024675947042, 2194449627517475473 },
819 .{ 11006974540203867551, 1697873161311732311 },
820 .{ 10313493231639821582, 1313665730009899186 },
821 .{ 12701016819766672773, 2032799256770390445 }
822};
823
824const FLOAT64_POW5_INV_OFFSETS: [19]u32 = .{
825 0x54544554, 0x04055545, 0x10041000, 0x00400414,
826 0x40010000, 0x41155555, 0x00000454, 0x00010044,
827 0x40000000, 0x44000041, 0x50454450, 0x55550054,
828 0x51655554, 0x40004000, 0x01000001, 0x00010500,
829 0x51515411, 0x05555554, 0x00000000,
830};
831
832
833// zig fmt: off
834
835// f64 full tables: 10688 bytes
836
837const FLOAT64_POW5_SPLIT: [326][2]u64 = .{
838 .{ 0, 1152921504606846976 }, .{ 0, 1441151880758558720 },
839 .{ 0, 1801439850948198400 }, .{ 0, 2251799813685248000 },
840 .{ 0, 1407374883553280000 }, .{ 0, 1759218604441600000 },
841 .{ 0, 2199023255552000000 }, .{ 0, 1374389534720000000 },
842 .{ 0, 1717986918400000000 }, .{ 0, 2147483648000000000 },
843 .{ 0, 1342177280000000000 }, .{ 0, 1677721600000000000 },
844 .{ 0, 2097152000000000000 }, .{ 0, 1310720000000000000 },
845 .{ 0, 1638400000000000000 }, .{ 0, 2048000000000000000 },
846 .{ 0, 1280000000000000000 }, .{ 0, 1600000000000000000 },
847 .{ 0, 2000000000000000000 }, .{ 0, 1250000000000000000 },
848 .{ 0, 1562500000000000000 }, .{ 0, 1953125000000000000 },
849 .{ 0, 1220703125000000000 }, .{ 0, 1525878906250000000 },
850 .{ 0, 1907348632812500000 }, .{ 0, 1192092895507812500 },
851 .{ 0, 1490116119384765625 }, .{ 4611686018427387904, 1862645149230957031 },
852 .{ 9799832789158199296, 1164153218269348144 }, .{ 12249790986447749120, 1455191522836685180 },
853 .{ 15312238733059686400, 1818989403545856475 }, .{ 14528612397897220096, 2273736754432320594 },
854 .{ 13692068767113150464, 1421085471520200371 }, .{ 12503399940464050176, 1776356839400250464 },
855 .{ 15629249925580062720, 2220446049250313080 }, .{ 9768281203487539200, 1387778780781445675 },
856 .{ 7598665485932036096, 1734723475976807094 }, .{ 274959820560269312, 2168404344971008868 },
857 .{ 9395221924704944128, 1355252715606880542 }, .{ 2520655369026404352, 1694065894508600678 },
858 .{ 12374191248137781248, 2117582368135750847 }, .{ 14651398557727195136, 1323488980084844279 },
859 .{ 13702562178731606016, 1654361225106055349 }, .{ 3293144668132343808, 2067951531382569187 },
860 .{ 18199116482078572544, 1292469707114105741 }, .{ 8913837547316051968, 1615587133892632177 },
861 .{ 15753982952572452864, 2019483917365790221 }, .{ 12152082354571476992, 1262177448353618888 },
862 .{ 15190102943214346240, 1577721810442023610 }, .{ 9764256642163156992, 1972152263052529513 },
863 .{ 17631875447420442880, 1232595164407830945 }, .{ 8204786253993389888, 1540743955509788682 },
864 .{ 1032610780636961552, 1925929944387235853 }, .{ 2951224747111794922, 1203706215242022408 },
865 .{ 3689030933889743652, 1504632769052528010 }, .{ 13834660704216955373, 1880790961315660012 },
866 .{ 17870034976990372916, 1175494350822287507 }, .{ 17725857702810578241, 1469367938527859384 },
867 .{ 3710578054803671186, 1836709923159824231 }, .{ 26536550077201078, 2295887403949780289 },
868 .{ 11545800389866720434, 1434929627468612680 }, .{ 14432250487333400542, 1793662034335765850 },
869 .{ 8816941072311974870, 2242077542919707313 }, .{ 17039803216263454053, 1401298464324817070 },
870 .{ 12076381983474541759, 1751623080406021338 }, .{ 5872105442488401391, 2189528850507526673 },
871 .{ 15199280947623720629, 1368455531567204170 }, .{ 9775729147674874978, 1710569414459005213 },
872 .{ 16831347453020981627, 2138211768073756516 }, .{ 1296220121283337709, 1336382355046097823 },
873 .{ 15455333206886335848, 1670477943807622278 }, .{ 10095794471753144002, 2088097429759527848 },
874 .{ 6309871544845715001, 1305060893599704905 }, .{ 12499025449484531656, 1631326116999631131 },
875 .{ 11012095793428276666, 2039157646249538914 }, .{ 11494245889320060820, 1274473528905961821 },
876 .{ 532749306367912313, 1593091911132452277 }, .{ 5277622651387278295, 1991364888915565346 },
877 .{ 7910200175544436838, 1244603055572228341 }, .{ 14499436237857933952, 1555753819465285426 },
878 .{ 8900923260467641632, 1944692274331606783 }, .{ 12480606065433357876, 1215432671457254239 },
879 .{ 10989071563364309441, 1519290839321567799 }, .{ 9124653435777998898, 1899113549151959749 },
880 .{ 8008751406574943263, 1186945968219974843 }, .{ 5399253239791291175, 1483682460274968554 },
881 .{ 15972438586593889776, 1854603075343710692 }, .{ 759402079766405302, 1159126922089819183 },
882 .{ 14784310654990170340, 1448908652612273978 }, .{ 9257016281882937117, 1811135815765342473 },
883 .{ 16182956370781059300, 2263919769706678091 }, .{ 7808504722524468110, 1414949856066673807 },
884 .{ 5148944884728197234, 1768687320083342259 }, .{ 1824495087482858639, 2210859150104177824 },
885 .{ 1140309429676786649, 1381786968815111140 }, .{ 1425386787095983311, 1727233711018888925 },
886 .{ 6393419502297367043, 2159042138773611156 }, .{ 13219259225790630210, 1349401336733506972 },
887 .{ 16524074032238287762, 1686751670916883715 }, .{ 16043406521870471799, 2108439588646104644 },
888 .{ 803757039314269066, 1317774742903815403 }, .{ 14839754354425000045, 1647218428629769253 },
889 .{ 4714634887749086344, 2059023035787211567 }, .{ 9864175832484260821, 1286889397367007229 },
890 .{ 16941905809032713930, 1608611746708759036 }, .{ 2730638187581340797, 2010764683385948796 },
891 .{ 10930020904093113806, 1256727927116217997 }, .{ 18274212148543780162, 1570909908895272496 },
892 .{ 4396021111970173586, 1963637386119090621 }, .{ 5053356204195052443, 1227273366324431638 },
893 .{ 15540067292098591362, 1534091707905539547 }, .{ 14813398096695851299, 1917614634881924434 },
894 .{ 13870059828862294966, 1198509146801202771 }, .{ 12725888767650480803, 1498136433501503464 },
895 .{ 15907360959563101004, 1872670541876879330 }, .{ 14553786618154326031, 1170419088673049581 },
896 .{ 4357175217410743827, 1463023860841311977 }, .{ 10058155040190817688, 1828779826051639971 },
897 .{ 7961007781811134206, 2285974782564549964 }, .{ 14199001900486734687, 1428734239102843727 },
898 .{ 13137066357181030455, 1785917798878554659 }, .{ 11809646928048900164, 2232397248598193324 },
899 .{ 16604401366885338411, 1395248280373870827 }, .{ 16143815690179285109, 1744060350467338534 },
900 .{ 10956397575869330579, 2180075438084173168 }, .{ 6847748484918331612, 1362547148802608230 },
901 .{ 17783057643002690323, 1703183936003260287 }, .{ 17617136035325974999, 2128979920004075359 },
902 .{ 17928239049719816230, 1330612450002547099 }, .{ 17798612793722382384, 1663265562503183874 },
903 .{ 13024893955298202172, 2079081953128979843 }, .{ 5834715712847682405, 1299426220705612402 },
904 .{ 16516766677914378815, 1624282775882015502 }, .{ 11422586310538197711, 2030353469852519378 },
905 .{ 11750802462513761473, 1268970918657824611 }, .{ 10076817059714813937, 1586213648322280764 },
906 .{ 12596021324643517422, 1982767060402850955 }, .{ 5566670318688504437, 1239229412751781847 },
907 .{ 2346651879933242642, 1549036765939727309 }, .{ 7545000868343941206, 1936295957424659136 },
908 .{ 4715625542714963254, 1210184973390411960 }, .{ 5894531928393704067, 1512731216738014950 },
909 .{ 16591536947346905892, 1890914020922518687 }, .{ 17287239619732898039, 1181821263076574179 },
910 .{ 16997363506238734644, 1477276578845717724 }, .{ 2799960309088866689, 1846595723557147156 },
911 .{ 10973347230035317489, 1154122327223216972 }, .{ 13716684037544146861, 1442652909029021215 },
912 .{ 12534169028502795672, 1803316136286276519 }, .{ 11056025267201106687, 2254145170357845649 },
913 .{ 18439230838069161439, 1408840731473653530 }, .{ 13825666510731675991, 1761050914342066913 },
914 .{ 3447025083132431277, 2201313642927583642 }, .{ 6766076695385157452, 1375821026829739776 },
915 .{ 8457595869231446815, 1719776283537174720 }, .{ 10571994836539308519, 2149720354421468400 },
916 .{ 6607496772837067824, 1343575221513417750 }, .{ 17482743002901110588, 1679469026891772187 },
917 .{ 17241742735199000331, 2099336283614715234 }, .{ 15387775227926763111, 1312085177259197021 },
918 .{ 5399660979626290177, 1640106471573996277 }, .{ 11361262242960250625, 2050133089467495346 },
919 .{ 11712474920277544544, 1281333180917184591 }, .{ 10028907631919542777, 1601666476146480739 },
920 .{ 7924448521472040567, 2002083095183100924 }, .{ 14176152362774801162, 1251301934489438077 },
921 .{ 3885132398186337741, 1564127418111797597 }, .{ 9468101516160310080, 1955159272639746996 },
922 .{ 15140935484454969608, 1221974545399841872 }, .{ 479425281859160394, 1527468181749802341 },
923 .{ 5210967620751338397, 1909335227187252926 }, .{ 17091912818251750210, 1193334516992033078 },
924 .{ 12141518985959911954, 1491668146240041348 }, .{ 15176898732449889943, 1864585182800051685 },
925 .{ 11791404716994875166, 1165365739250032303 }, .{ 10127569877816206054, 1456707174062540379 },
926 .{ 8047776328842869663, 1820883967578175474 }, .{ 836348374198811271, 2276104959472719343 },
927 .{ 7440246761515338900, 1422565599670449589 }, .{ 13911994470321561530, 1778206999588061986 },
928 .{ 8166621051047176104, 2222758749485077483 }, .{ 2798295147690791113, 1389224218428173427 },
929 .{ 17332926989895652603, 1736530273035216783 }, .{ 17054472718942177850, 2170662841294020979 },
930 .{ 8353202440125167204, 1356664275808763112 }, .{ 10441503050156459005, 1695830344760953890 },
931 .{ 3828506775840797949, 2119787930951192363 }, .{ 86973725686804766, 1324867456844495227 },
932 .{ 13943775212390669669, 1656084321055619033 }, .{ 3594660960206173375, 2070105401319523792 },
933 .{ 2246663100128858359, 1293815875824702370 }, .{ 12031700912015848757, 1617269844780877962 },
934 .{ 5816254103165035138, 2021587305976097453 }, .{ 5941001823691840913, 1263492066235060908 },
935 .{ 7426252279614801142, 1579365082793826135 }, .{ 4671129331091113523, 1974206353492282669 },
936 .{ 5225298841145639904, 1233878970932676668 }, .{ 6531623551432049880, 1542348713665845835 },
937 .{ 3552843420862674446, 1927935892082307294 }, .{ 16055585193321335241, 1204959932551442058 },
938 .{ 10846109454796893243, 1506199915689302573 }, .{ 18169322836923504458, 1882749894611628216 },
939 .{ 11355826773077190286, 1176718684132267635 }, .{ 9583097447919099954, 1470898355165334544 },
940 .{ 11978871809898874942, 1838622943956668180 }, .{ 14973589762373593678, 2298278679945835225 },
941 .{ 2440964573842414192, 1436424174966147016 }, .{ 3051205717303017741, 1795530218707683770 },
942 .{ 13037379183483547984, 2244412773384604712 }, .{ 8148361989677217490, 1402757983365377945 },
943 .{ 14797138505523909766, 1753447479206722431 }, .{ 13884737113477499304, 2191809349008403039 },
944 .{ 15595489723564518921, 1369880843130251899 }, .{ 14882676136028260747, 1712351053912814874 },
945 .{ 9379973133180550126, 2140438817391018593 }, .{ 17391698254306313589, 1337774260869386620 },
946 .{ 3292878744173340370, 1672217826086733276 }, .{ 4116098430216675462, 2090272282608416595 },
947 .{ 266718509671728212, 1306420176630260372 }, .{ 333398137089660265, 1633025220787825465 },
948 .{ 5028433689789463235, 2041281525984781831 }, .{ 10060300083759496378, 1275800953740488644 },
949 .{ 12575375104699370472, 1594751192175610805 }, .{ 1884160825592049379, 1993438990219513507 },
950 .{ 17318501580490888525, 1245899368887195941 }, .{ 7813068920331446945, 1557374211108994927 },
951 .{ 5154650131986920777, 1946717763886243659 }, .{ 915813323278131534, 1216698602428902287 },
952 .{ 14979824709379828129, 1520873253036127858 }, .{ 9501408849870009354, 1901091566295159823 },
953 .{ 12855909558809837702, 1188182228934474889 }, .{ 2234828893230133415, 1485227786168093612 },
954 .{ 2793536116537666769, 1856534732710117015 }, .{ 8663489100477123587, 1160334207943823134 },
955 .{ 1605989338741628675, 1450417759929778918 }, .{ 11230858710281811652, 1813022199912223647 },
956 .{ 9426887369424876662, 2266277749890279559 }, .{ 12809333633531629769, 1416423593681424724 },
957 .{ 16011667041914537212, 1770529492101780905 }, .{ 6179525747111007803, 2213161865127226132 },
958 .{ 13085575628799155685, 1383226165704516332 }, .{ 16356969535998944606, 1729032707130645415 },
959 .{ 15834525901571292854, 2161290883913306769 }, .{ 2979049660840976177, 1350806802445816731 },
960 .{ 17558870131333383934, 1688508503057270913 }, .{ 8113529608884566205, 2110635628821588642 },
961 .{ 9682642023980241782, 1319147268013492901 }, .{ 16714988548402690132, 1648934085016866126 },
962 .{ 11670363648648586857, 2061167606271082658 }, .{ 11905663298832754689, 1288229753919426661 },
963 .{ 1047021068258779650, 1610287192399283327 }, .{ 15143834390605638274, 2012858990499104158 },
964 .{ 4853210475701136017, 1258036869061940099 }, .{ 1454827076199032118, 1572546086327425124 },
965 .{ 1818533845248790147, 1965682607909281405 }, .{ 3442426662494187794, 1228551629943300878 },
966 .{ 13526405364972510550, 1535689537429126097 }, .{ 3072948650933474476, 1919611921786407622 },
967 .{ 15755650962115585259, 1199757451116504763 }, .{ 15082877684217093670, 1499696813895630954 },
968 .{ 9630225068416591280, 1874621017369538693 }, .{ 8324733676974063502, 1171638135855961683 },
969 .{ 5794231077790191473, 1464547669819952104 }, .{ 7242788847237739342, 1830684587274940130 },
970 .{ 18276858095901949986, 2288355734093675162 }, .{ 16034722328366106645, 1430222333808546976 },
971 .{ 1596658836748081690, 1787777917260683721 }, .{ 6607509564362490017, 2234722396575854651 },
972 .{ 1823850468512862308, 1396701497859909157 }, .{ 6891499104068465790, 1745876872324886446 },
973 .{ 17837745916940358045, 2182346090406108057 }, .{ 4231062170446641922, 1363966306503817536 },
974 .{ 5288827713058302403, 1704957883129771920 }, .{ 6611034641322878003, 2131197353912214900 },
975 .{ 13355268687681574560, 1331998346195134312 }, .{ 16694085859601968200, 1664997932743917890 },
976 .{ 11644235287647684442, 2081247415929897363 }, .{ 4971804045566108824, 1300779634956185852 },
977 .{ 6214755056957636030, 1625974543695232315 }, .{ 3156757802769657134, 2032468179619040394 },
978 .{ 6584659645158423613, 1270292612261900246 }, .{ 17454196593302805324, 1587865765327375307 },
979 .{ 17206059723201118751, 1984832206659219134 }, .{ 6142101308573311315, 1240520129162011959 },
980 .{ 3065940617289251240, 1550650161452514949 }, .{ 8444111790038951954, 1938312701815643686 },
981 .{ 665883850346957067, 1211445438634777304 }, .{ 832354812933696334, 1514306798293471630 },
982 .{ 10263815553021896226, 1892883497866839537 }, .{ 17944099766707154901, 1183052186166774710 },
983 .{ 13206752671529167818, 1478815232708468388 }, .{ 16508440839411459773, 1848519040885585485 },
984 .{ 12623618533845856310, 1155324400553490928 }, .{ 15779523167307320387, 1444155500691863660 },
985 .{ 1277659885424598868, 1805194375864829576 }, .{ 1597074856780748586, 2256492969831036970 },
986 .{ 5609857803915355770, 1410308106144398106 }, .{ 16235694291748970521, 1762885132680497632 },
987 .{ 1847873790976661535, 2203606415850622041 }, .{ 12684136165428883219, 1377254009906638775 },
988 .{ 11243484188358716120, 1721567512383298469 }, .{ 219297180166231438, 2151959390479123087 },
989 .{ 7054589765244976505, 1344974619049451929 }, .{ 13429923224983608535, 1681218273811814911 },
990 .{ 12175718012802122765, 2101522842264768639 }, .{ 14527352785642408584, 1313451776415480399 },
991 .{ 13547504963625622826, 1641814720519350499 }, .{ 12322695186104640628, 2052268400649188124 },
992 .{ 16925056528170176201, 1282667750405742577 }, .{ 7321262604930556539, 1603334688007178222 },
993 .{ 18374950293017971482, 2004168360008972777 }, .{ 4566814905495150320, 1252605225005607986 },
994 .{ 14931890668723713708, 1565756531257009982 }, .{ 9441491299049866327, 1957195664071262478 },
995 .{ 1289246043478778550, 1223247290044539049 }, .{ 6223243572775861092, 1529059112555673811 },
996 .{ 3167368447542438461, 1911323890694592264 }, .{ 1979605279714024038, 1194577431684120165 },
997 .{ 7086192618069917952, 1493221789605150206 }, .{ 18081112809442173248, 1866527237006437757 },
998 .{ 13606538515115052232, 1166579523129023598 }, .{ 7784801107039039482, 1458224403911279498 },
999 .{ 507629346944023544, 1822780504889099373 }, .{ 5246222702107417334, 2278475631111374216 },
1000 .{ 3278889188817135834, 1424047269444608885 }, .{ 8710297504448807696, 1780059086805761106 }
1001};
1002
1003const FLOAT64_POW5_INV_SPLIT: [342][2]u64 = .{
1004 .{ 1, 2305843009213693952 }, .{ 11068046444225730970, 1844674407370955161 },
1005 .{ 5165088340638674453, 1475739525896764129 }, .{ 7821419487252849886, 1180591620717411303 },
1006 .{ 8824922364862649494, 1888946593147858085 }, .{ 7059937891890119595, 1511157274518286468 },
1007 .{ 13026647942995916322, 1208925819614629174 }, .{ 9774590264567735146, 1934281311383406679 },
1008 .{ 11509021026396098440, 1547425049106725343 }, .{ 16585914450600699399, 1237940039285380274 },
1009 .{ 15469416676735388068, 1980704062856608439 }, .{ 16064882156130220778, 1584563250285286751 },
1010 .{ 9162556910162266299, 1267650600228229401 }, .{ 7281393426775805432, 2028240960365167042 },
1011 .{ 16893161185646375315, 1622592768292133633 }, .{ 2446482504291369283, 1298074214633706907 },
1012 .{ 7603720821608101175, 2076918743413931051 }, .{ 2393627842544570617, 1661534994731144841 },
1013 .{ 16672297533003297786, 1329227995784915872 }, .{ 11918280793837635165, 2126764793255865396 },
1014 .{ 5845275820328197809, 1701411834604692317 }, .{ 15744267100488289217, 1361129467683753853 },
1015 .{ 3054734472329800808, 2177807148294006166 }, .{ 17201182836831481939, 1742245718635204932 },
1016 .{ 6382248639981364905, 1393796574908163946 }, .{ 2832900194486363201, 2230074519853062314 },
1017 .{ 5955668970331000884, 1784059615882449851 }, .{ 1075186361522890384, 1427247692705959881 },
1018 .{ 12788344622662355584, 2283596308329535809 }, .{ 13920024512871794791, 1826877046663628647 },
1019 .{ 3757321980813615186, 1461501637330902918 }, .{ 10384555214134712795, 1169201309864722334 },
1020 .{ 5547241898389809503, 1870722095783555735 }, .{ 4437793518711847602, 1496577676626844588 },
1021 .{ 10928932444453298728, 1197262141301475670 }, .{ 17486291911125277965, 1915619426082361072 },
1022 .{ 6610335899416401726, 1532495540865888858 }, .{ 12666966349016942027, 1225996432692711086 },
1023 .{ 12888448528943286597, 1961594292308337738 }, .{ 17689456452638449924, 1569275433846670190 },
1024 .{ 14151565162110759939, 1255420347077336152 }, .{ 7885109000409574610, 2008672555323737844 },
1025 .{ 9997436015069570011, 1606938044258990275 }, .{ 7997948812055656009, 1285550435407192220 },
1026 .{ 12796718099289049614, 2056880696651507552 }, .{ 2858676849947419045, 1645504557321206042 },
1027 .{ 13354987924183666206, 1316403645856964833 }, .{ 17678631863951955605, 2106245833371143733 },
1028 .{ 3074859046935833515, 1684996666696914987 }, .{ 13527933681774397782, 1347997333357531989 },
1029 .{ 10576647446613305481, 2156795733372051183 }, .{ 15840015586774465031, 1725436586697640946 },
1030 .{ 8982663654677661702, 1380349269358112757 }, .{ 18061610662226169046, 2208558830972980411 },
1031 .{ 10759939715039024913, 1766847064778384329 }, .{ 12297300586773130254, 1413477651822707463 },
1032 .{ 15986332124095098083, 2261564242916331941 }, .{ 9099716884534168143, 1809251394333065553 },
1033 .{ 14658471137111155161, 1447401115466452442 }, .{ 4348079280205103483, 1157920892373161954 },
1034 .{ 14335624477811986218, 1852673427797059126 }, .{ 7779150767507678651, 1482138742237647301 },
1035 .{ 2533971799264232598, 1185710993790117841 }, .{ 15122401323048503126, 1897137590064188545 },
1036 .{ 12097921058438802501, 1517710072051350836 }, .{ 5988988032009131678, 1214168057641080669 },
1037 .{ 16961078480698431330, 1942668892225729070 }, .{ 13568862784558745064, 1554135113780583256 },
1038 .{ 7165741412905085728, 1243308091024466605 }, .{ 11465186260648137165, 1989292945639146568 },
1039 .{ 16550846638002330379, 1591434356511317254 }, .{ 16930026125143774626, 1273147485209053803 },
1040 .{ 4951948911778577463, 2037035976334486086 }, .{ 272210314680951647, 1629628781067588869 },
1041 .{ 3907117066486671641, 1303703024854071095 }, .{ 6251387306378674625, 2085924839766513752 },
1042 .{ 16069156289328670670, 1668739871813211001 }, .{ 9165976216721026213, 1334991897450568801 },
1043 .{ 7286864317269821294, 2135987035920910082 }, .{ 16897537898041588005, 1708789628736728065 },
1044 .{ 13518030318433270404, 1367031702989382452 }, .{ 6871453250525591353, 2187250724783011924 },
1045 .{ 9186511415162383406, 1749800579826409539 }, .{ 11038557946871817048, 1399840463861127631 },
1046 .{ 10282995085511086630, 2239744742177804210 }, .{ 8226396068408869304, 1791795793742243368 },
1047 .{ 13959814484210916090, 1433436634993794694 }, .{ 11267656730511734774, 2293498615990071511 },
1048 .{ 5324776569667477496, 1834798892792057209 }, .{ 7949170070475892320, 1467839114233645767 },
1049 .{ 17427382500606444826, 1174271291386916613 }, .{ 5747719112518849781, 1878834066219066582 },
1050 .{ 15666221734240810795, 1503067252975253265 }, .{ 12532977387392648636, 1202453802380202612 },
1051 .{ 5295368560860596524, 1923926083808324180 }, .{ 4236294848688477220, 1539140867046659344 },
1052 .{ 7078384693692692099, 1231312693637327475 }, .{ 11325415509908307358, 1970100309819723960 },
1053 .{ 9060332407926645887, 1576080247855779168 }, .{ 14626963555825137356, 1260864198284623334 },
1054 .{ 12335095245094488799, 2017382717255397335 }, .{ 9868076196075591040, 1613906173804317868 },
1055 .{ 15273158586344293478, 1291124939043454294 }, .{ 13369007293925138595, 2065799902469526871 },
1056 .{ 7005857020398200553, 1652639921975621497 }, .{ 16672732060544291412, 1322111937580497197 },
1057 .{ 11918976037903224966, 2115379100128795516 }, .{ 5845832015580669650, 1692303280103036413 },
1058 .{ 12055363241948356366, 1353842624082429130 }, .{ 841837113407818570, 2166148198531886609 },
1059 .{ 4362818505468165179, 1732918558825509287 }, .{ 14558301248600263113, 1386334847060407429 },
1060 .{ 12225235553534690011, 2218135755296651887 }, .{ 2401490813343931363, 1774508604237321510 },
1061 .{ 1921192650675145090, 1419606883389857208 }, .{ 17831303500047873437, 2271371013423771532 },
1062 .{ 6886345170554478103, 1817096810739017226 }, .{ 1819727321701672159, 1453677448591213781 },
1063 .{ 16213177116328979020, 1162941958872971024 }, .{ 14873036941900635463, 1860707134196753639 },
1064 .{ 15587778368262418694, 1488565707357402911 }, .{ 8780873879868024632, 1190852565885922329 },
1065 .{ 2981351763563108441, 1905364105417475727 }, .{ 13453127855076217722, 1524291284333980581 },
1066 .{ 7073153469319063855, 1219433027467184465 }, .{ 11317045550910502167, 1951092843947495144 },
1067 .{ 12742985255470312057, 1560874275157996115 }, .{ 10194388204376249646, 1248699420126396892 },
1068 .{ 1553625868034358140, 1997919072202235028 }, .{ 8621598323911307159, 1598335257761788022 },
1069 .{ 17965325103354776697, 1278668206209430417 }, .{ 13987124906400001422, 2045869129935088668 },
1070 .{ 121653480894270168, 1636695303948070935 }, .{ 97322784715416134, 1309356243158456748 },
1071 .{ 14913111714512307107, 2094969989053530796 }, .{ 8241140556867935363, 1675975991242824637 },
1072 .{ 17660958889720079260, 1340780792994259709 }, .{ 17189487779326395846, 2145249268790815535 },
1073 .{ 13751590223461116677, 1716199415032652428 }, .{ 18379969808252713988, 1372959532026121942 },
1074 .{ 14650556434236701088, 2196735251241795108 }, .{ 652398703163629901, 1757388200993436087 },
1075 .{ 11589965406756634890, 1405910560794748869 }, .{ 7475898206584884855, 2249456897271598191 },
1076 .{ 2291369750525997561, 1799565517817278553 }, .{ 9211793429904618695, 1439652414253822842 },
1077 .{ 18428218302589300235, 2303443862806116547 }, .{ 7363877012587619542, 1842755090244893238 },
1078 .{ 13269799239553916280, 1474204072195914590 }, .{ 10615839391643133024, 1179363257756731672 },
1079 .{ 2227947767661371545, 1886981212410770676 }, .{ 16539753473096738529, 1509584969928616540 },
1080 .{ 13231802778477390823, 1207667975942893232 }, .{ 6413489186596184024, 1932268761508629172 },
1081 .{ 16198837793502678189, 1545815009206903337 }, .{ 5580372605318321905, 1236652007365522670 },
1082 .{ 8928596168509315048, 1978643211784836272 }, .{ 18210923379033183008, 1582914569427869017 },
1083 .{ 7190041073742725760, 1266331655542295214 }, .{ 436019273762630246, 2026130648867672343 },
1084 .{ 7727513048493924843, 1620904519094137874 }, .{ 9871359253537050198, 1296723615275310299 },
1085 .{ 4726128361433549347, 2074757784440496479 }, .{ 7470251503888749801, 1659806227552397183 },
1086 .{ 13354898832594820487, 1327844982041917746 }, .{ 13989140502667892133, 2124551971267068394 },
1087 .{ 14880661216876224029, 1699641577013654715 }, .{ 11904528973500979224, 1359713261610923772 },
1088 .{ 4289851098633925465, 2175541218577478036 }, .{ 18189276137874781665, 1740432974861982428 },
1089 .{ 3483374466074094362, 1392346379889585943 }, .{ 1884050330976640656, 2227754207823337509 },
1090 .{ 5196589079523222848, 1782203366258670007 }, .{ 15225317707844309248, 1425762693006936005 },
1091 .{ 5913764258841343181, 2281220308811097609 }, .{ 8420360221814984868, 1824976247048878087 },
1092 .{ 17804334621677718864, 1459980997639102469 }, .{ 17932816512084085415, 1167984798111281975 },
1093 .{ 10245762345624985047, 1868775676978051161 }, .{ 4507261061758077715, 1495020541582440929 },
1094 .{ 7295157664148372495, 1196016433265952743 }, .{ 7982903447895485668, 1913626293225524389 },
1095 .{ 10075671573058298858, 1530901034580419511 }, .{ 4371188443704728763, 1224720827664335609 },
1096 .{ 14372599139411386667, 1959553324262936974 }, .{ 15187428126271019657, 1567642659410349579 },
1097 .{ 15839291315758726049, 1254114127528279663 }, .{ 3206773216762499739, 2006582604045247462 },
1098 .{ 13633465017635730761, 1605266083236197969 }, .{ 14596120828850494932, 1284212866588958375 },
1099 .{ 4907049252451240275, 2054740586542333401 }, .{ 236290587219081897, 1643792469233866721 },
1100 .{ 14946427728742906810, 1315033975387093376 }, .{ 16535586736504830250, 2104054360619349402 },
1101 .{ 5849771759720043554, 1683243488495479522 }, .{ 15747863852001765813, 1346594790796383617 },
1102 .{ 10439186904235184007, 2154551665274213788 }, .{ 15730047152871967852, 1723641332219371030 },
1103 .{ 12584037722297574282, 1378913065775496824 }, .{ 9066413911450387881, 2206260905240794919 },
1104 .{ 10942479943902220628, 1765008724192635935 }, .{ 8753983955121776503, 1412006979354108748 },
1105 .{ 10317025513452932081, 2259211166966573997 }, .{ 874922781278525018, 1807368933573259198 },
1106 .{ 8078635854506640661, 1445895146858607358 }, .{ 13841606313089133175, 1156716117486885886 },
1107 .{ 14767872471458792434, 1850745787979017418 }, .{ 746251532941302978, 1480596630383213935 },
1108 .{ 597001226353042382, 1184477304306571148 }, .{ 15712597221132509104, 1895163686890513836 },
1109 .{ 8880728962164096960, 1516130949512411069 }, .{ 10793931984473187891, 1212904759609928855 },
1110 .{ 17270291175157100626, 1940647615375886168 }, .{ 2748186495899949531, 1552518092300708935 },
1111 .{ 2198549196719959625, 1242014473840567148 }, .{ 18275073973719576693, 1987223158144907436 },
1112 .{ 10930710364233751031, 1589778526515925949 }, .{ 12433917106128911148, 1271822821212740759 },
1113 .{ 8826220925580526867, 2034916513940385215 }, .{ 7060976740464421494, 1627933211152308172 },
1114 .{ 16716827836597268165, 1302346568921846537 }, .{ 11989529279587987770, 2083754510274954460 },
1115 .{ 9591623423670390216, 1667003608219963568 }, .{ 15051996368420132820, 1333602886575970854 },
1116 .{ 13015147745246481542, 2133764618521553367 }, .{ 3033420566713364587, 1707011694817242694 },
1117 .{ 6116085268112601993, 1365609355853794155 }, .{ 9785736428980163188, 2184974969366070648 },
1118 .{ 15207286772667951197, 1747979975492856518 }, .{ 1097782973908629988, 1398383980394285215 },
1119 .{ 1756452758253807981, 2237414368630856344 }, .{ 5094511021344956708, 1789931494904685075 },
1120 .{ 4075608817075965366, 1431945195923748060 }, .{ 6520974107321544586, 2291112313477996896 },
1121 .{ 1527430471115325346, 1832889850782397517 }, .{ 12289990821117991246, 1466311880625918013 },
1122 .{ 17210690286378213644, 1173049504500734410 }, .{ 9090360384495590213, 1876879207201175057 },
1123 .{ 18340334751822203140, 1501503365760940045 }, .{ 14672267801457762512, 1201202692608752036 },
1124 .{ 16096930852848599373, 1921924308174003258 }, .{ 1809498238053148529, 1537539446539202607 },
1125 .{ 12515645034668249793, 1230031557231362085 }, .{ 1578287981759648052, 1968050491570179337 },
1126 .{ 12330676829633449412, 1574440393256143469 }, .{ 13553890278448669853, 1259552314604914775 },
1127 .{ 3239480371808320148, 2015283703367863641 }, .{ 17348979556414297411, 1612226962694290912 },
1128 .{ 6500486015647617283, 1289781570155432730 }, .{ 10400777625036187652, 2063650512248692368 },
1129 .{ 15699319729512770768, 1650920409798953894 }, .{ 16248804598352126938, 1320736327839163115 },
1130 .{ 7551343283653851484, 2113178124542660985 }, .{ 6041074626923081187, 1690542499634128788 },
1131 .{ 12211557331022285596, 1352433999707303030 }, .{ 1091747655926105338, 2163894399531684849 },
1132 .{ 4562746939482794594, 1731115519625347879 }, .{ 7339546366328145998, 1384892415700278303 },
1133 .{ 8053925371383123274, 2215827865120445285 }, .{ 6443140297106498619, 1772662292096356228 },
1134 .{ 12533209867169019542, 1418129833677084982 }, .{ 5295740528502789974, 2269007733883335972 },
1135 .{ 15304638867027962949, 1815206187106668777 }, .{ 4865013464138549713, 1452164949685335022 },
1136 .{ 14960057215536570740, 1161731959748268017 }, .{ 9178696285890871890, 1858771135597228828 },
1137 .{ 14721654658196518159, 1487016908477783062 }, .{ 4398626097073393881, 1189613526782226450 },
1138 .{ 7037801755317430209, 1903381642851562320 }, .{ 5630241404253944167, 1522705314281249856 },
1139 .{ 814844308661245011, 1218164251424999885 }, .{ 1303750893857992017, 1949062802279999816 },
1140 .{ 15800395974054034906, 1559250241823999852 }, .{ 5261619149759407279, 1247400193459199882 },
1141 .{ 12107939454356961969, 1995840309534719811 }, .{ 5997002748743659252, 1596672247627775849 },
1142 .{ 8486951013736837725, 1277337798102220679 }, .{ 2511075177753209390, 2043740476963553087 },
1143 .{ 13076906586428298482, 1634992381570842469 }, .{ 14150874083884549109, 1307993905256673975 },
1144 .{ 4194654460505726958, 2092790248410678361 }, .{ 18113118827372222859, 1674232198728542688 },
1145 .{ 3422448617672047318, 1339385758982834151 }, .{ 16543964232501006678, 2143017214372534641 },
1146 .{ 9545822571258895019, 1714413771498027713 }, .{ 15015355686490936662, 1371531017198422170 },
1147 .{ 5577825024675947042, 2194449627517475473 }, .{ 11840957649224578280, 1755559702013980378 },
1148 .{ 16851463748863483271, 1404447761611184302 }, .{ 12204946739213931940, 2247116418577894884 },
1149 .{ 13453306206113055875, 1797693134862315907 }, .{ 3383947335406624054, 1438154507889852726 },
1150 .{ 16482362180876329456, 2301047212623764361 }, .{ 9496540929959153242, 1840837770099011489 },
1151 .{ 11286581558709232917, 1472670216079209191 }, .{ 5339916432225476010, 1178136172863367353 },
1152 .{ 4854517476818851293, 1885017876581387765 }, .{ 3883613981455081034, 1508014301265110212 },
1153 .{ 14174937629389795797, 1206411441012088169 }, .{ 11611853762797942306, 1930258305619341071 },
1154 .{ 5600134195496443521, 1544206644495472857 }, .{ 15548153800622885787, 1235365315596378285 },
1155 .{ 6430302007287065643, 1976584504954205257 }, .{ 16212288050055383484, 1581267603963364205 },
1156 .{ 12969830440044306787, 1265014083170691364 }, .{ 9683682259845159889, 2024022533073106183 },
1157 .{ 15125643437359948558, 1619218026458484946 }, .{ 8411165935146048523, 1295374421166787957 },
1158 .{ 17147214310975587960, 2072599073866860731 }, .{ 10028422634038560045, 1658079259093488585 },
1159 .{ 8022738107230848036, 1326463407274790868 }, .{ 9147032156827446534, 2122341451639665389 },
1160 .{ 11006974540203867551, 1697873161311732311 }, .{ 5116230817421183718, 1358298529049385849 },
1161 .{ 15564666937357714594, 2173277646479017358 }, .{ 1383687105660440706, 1738622117183213887 },
1162 .{ 12174996128754083534, 1390897693746571109 }, .{ 8411947361780802685, 2225436309994513775 },
1163 .{ 6729557889424642148, 1780349047995611020 }, .{ 5383646311539713719, 1424279238396488816 },
1164 .{ 1235136468979721303, 2278846781434382106 }, .{ 15745504434151418335, 1823077425147505684 },
1165 .{ 16285752362063044992, 1458461940118004547 }, .{ 5649904260166615347, 1166769552094403638 },
1166 .{ 5350498001524674232, 1866831283351045821 }, .{ 591049586477829062, 1493465026680836657 },
1167 .{ 11540886113407994219, 1194772021344669325 }, .{ 18673707743239135, 1911635234151470921 },
1168 .{ 14772334225162232601, 1529308187321176736 }, .{ 8128518565387875758, 1223446549856941389 },
1169 .{ 1937583260394870242, 1957514479771106223 }, .{ 8928764237799716840, 1566011583816884978 },
1170 .{ 14521709019723594119, 1252809267053507982 }, .{ 8477339172590109297, 2004494827285612772 },
1171 .{ 17849917782297818407, 1603595861828490217 }, .{ 6901236596354434079, 1282876689462792174 },
1172 .{ 18420676183650915173, 2052602703140467478 }, .{ 3668494502695001169, 1642082162512373983 },
1173 .{ 10313493231639821582, 1313665730009899186 }, .{ 9122891541139893884, 2101865168015838698 },
1174 .{ 14677010862395735754, 1681492134412670958 }, .{ 673562245690857633, 1345193707530136767 }
1175};
1176
1177// zig fmt: off
1178//
1179// f128 small tables: 9072 bytes
1180
1181const FLOAT128_POW5_INV_BITCOUNT = 249;
1182const FLOAT128_POW5_BITCOUNT = 249;
1183const FLOAT128_POW5_TABLE_SIZE: comptime_int = FLOAT128_POW5_TABLE.len;
1184
1185const FLOAT128_POW5_TABLE: [56][2]u64 = .{
1186 .{ 1, 0 },
1187 .{ 5, 0 },
1188 .{ 25, 0 },
1189 .{ 125, 0 },
1190 .{ 625, 0 },
1191 .{ 3125, 0 },
1192 .{ 15625, 0 },
1193 .{ 78125, 0 },
1194 .{ 390625, 0 },
1195 .{ 1953125, 0 },
1196 .{ 9765625, 0 },
1197 .{ 48828125, 0 },
1198 .{ 244140625, 0 },
1199 .{ 1220703125, 0 },
1200 .{ 6103515625, 0 },
1201 .{ 30517578125, 0 },
1202 .{ 152587890625, 0 },
1203 .{ 762939453125, 0 },
1204 .{ 3814697265625, 0 },
1205 .{ 19073486328125, 0 },
1206 .{ 95367431640625, 0 },
1207 .{ 476837158203125, 0 },
1208 .{ 2384185791015625, 0 },
1209 .{ 11920928955078125, 0 },
1210 .{ 59604644775390625, 0 },
1211 .{ 298023223876953125, 0 },
1212 .{ 1490116119384765625, 0 },
1213 .{ 7450580596923828125, 0 },
1214 .{ 359414837200037393, 2 },
1215 .{ 1797074186000186965, 10 },
1216 .{ 8985370930000934825, 50 },
1217 .{ 8033366502585570893, 252 },
1218 .{ 3273344365508751233, 1262 },
1219 .{ 16366721827543756165, 6310 },
1220 .{ 8046632842880574361, 31554 },
1221 .{ 3339676066983768573, 157772 },
1222 .{ 16698380334918842865, 788860 },
1223 .{ 9704925379756007861, 3944304 },
1224 .{ 11631138751360936073, 19721522 },
1225 .{ 2815461535676025517, 98607613 },
1226 .{ 14077307678380127585, 493038065 },
1227 .{ 15046306170771983077, 2465190328 },
1228 .{ 1444554559021708921, 12325951644 },
1229 .{ 7222772795108544605, 61629758220 },
1230 .{ 17667119901833171409, 308148791101 },
1231 .{ 14548623214327650581, 1540743955509 },
1232 .{ 17402883850509598057, 7703719777548 },
1233 .{ 13227442957709783821, 38518598887744 },
1234 .{ 10796982567420264257, 192592994438723 },
1235 .{ 17091424689682218053, 962964972193617 },
1236 .{ 11670147153572883801, 4814824860968089 },
1237 .{ 3010503546735764157, 24074124304840448 },
1238 .{ 15052517733678820785, 120370621524202240 },
1239 .{ 1475612373555897461, 601853107621011204 },
1240 .{ 7378061867779487305, 3009265538105056020 },
1241 .{ 18443565265187884909, 15046327690525280101 },
1242};
1243
1244const FLOAT128_POW5_SPLIT: [89][4]u64 = .{
1245 .{ 0, 0, 0, 72057594037927936 },
1246 .{ 0, 5206161169240293376, 4575641699882439235, 73468396926392969 },
1247 .{ 3360510775605221349, 6983200512169538081, 4325643253124434363, 74906821675075173 },
1248 .{ 11917660854915489451, 9652941469841108803, 946308467778435600, 76373409087490117 },
1249 .{ 1994853395185689235, 16102657350889591545, 6847013871814915412, 77868710555449746 },
1250 .{ 958415760277438274, 15059347134713823592, 7329070255463483331, 79393288266368765 },
1251 .{ 2065144883315240188, 7145278325844925976, 14718454754511147343, 80947715414629833 },
1252 .{ 8980391188862868935, 13709057401304208685, 8230434828742694591, 82532576417087045 },
1253 .{ 432148644612782575, 7960151582448466064, 12056089168559840552, 84148467132788711 },
1254 .{ 484109300864744403, 15010663910730448582, 16824949663447227068, 85795995087002057 },
1255 .{ 14793711725276144220, 16494403799991899904, 10145107106505865967, 87475779699624060 },
1256 .{ 15427548291869817042, 12330588654550505203, 13980791795114552342, 89188452518064298 },
1257 .{ 9979404135116626552, 13477446383271537499, 14459862802511591337, 90934657454687378 },
1258 .{ 12385121150303452775, 9097130814231585614, 6523855782339765207, 92715051028904201 },
1259 .{ 1822931022538209743, 16062974719797586441, 3619180286173516788, 94530302614003091 },
1260 .{ 12318611738248470829, 13330752208259324507, 10986694768744162601, 96381094688813589 },
1261 .{ 13684493829640282333, 7674802078297225834, 15208116197624593182, 98268123094297527 },
1262 .{ 5408877057066295332, 6470124174091971006, 15112713923117703147, 100192097295163851 },
1263 .{ 11407083166564425062, 18189998238742408185, 4337638702446708282, 102153740646605557 },
1264 .{ 4112405898036935485, 924624216579956435, 14251108172073737125, 104153790666259019 },
1265 .{ 16996739107011444789, 10015944118339042475, 2395188869672266257, 106192999311487969 },
1266 .{ 4588314690421337879, 5339991768263654604, 15441007590670620066, 108272133262096356 },
1267 .{ 2286159977890359825, 14329706763185060248, 5980012964059367667, 110391974208576409 },
1268 .{ 9654767503237031099, 11293544302844823188, 11739932712678287805, 112553319146000238 },
1269 .{ 11362964448496095896, 7990659682315657680, 251480263940996374, 114756980673665505 },
1270 .{ 1423410421096377129, 14274395557581462179, 16553482793602208894, 117003787300607788 },
1271 .{ 2070444190619093137, 11517140404712147401, 11657844572835578076, 119294583757094535 },
1272 .{ 7648316884775828921, 15264332483297977688, 247182277434709002, 121630231312217685 },
1273 .{ 17410896758132241352, 10923914482914417070, 13976383996795783649, 124011608097704390 },
1274 .{ 9542674537907272703, 3079432708831728956, 14235189590642919676, 126439609438067572 },
1275 .{ 10364666969937261816, 8464573184892924210, 12758646866025101190, 128915148187220428 },
1276 .{ 14720354822146013883, 11480204489231511423, 7449876034836187038, 131439155071681461 },
1277 .{ 1692907053653558553, 17835392458598425233, 1754856712536736598, 134012579040499057 },
1278 .{ 5620591334531458755, 11361776175667106627, 13350215315297937856, 136636387622027174 },
1279 .{ 17455759733928092601, 10362573084069962561, 11246018728801810510, 139311567287686283 },
1280 .{ 2465404073814044982, 17694822665274381860, 1509954037718722697, 142039123822846312 },
1281 .{ 2152236053329638369, 11202280800589637091, 16388426812920420176, 72410041352485523 },
1282 .{ 17319024055671609028, 10944982848661280484, 2457150158022562661, 73827744744583080 },
1283 .{ 17511219308535248024, 5122059497846768077, 2089605804219668451, 75273205100637900 },
1284 .{ 10082673333144031533, 14429008783411894887, 12842832230171903890, 76746965869337783 },
1285 .{ 16196653406315961184, 10260180891682904501, 10537411930446752461, 78249581139456266 },
1286 .{ 15084422041749743389, 234835370106753111, 16662517110286225617, 79781615848172976 },
1287 .{ 8199644021067702606, 3787318116274991885, 7438130039325743106, 81343645993472659 },
1288 .{ 12039493937039359765, 9773822153580393709, 5945428874398357806, 82936258850702722 },
1289 .{ 984543865091303961, 7975107621689454830, 6556665988501773347, 84560053193370726 },
1290 .{ 9633317878125234244, 16099592426808915028, 9706674539190598200, 86215639518264828 },
1291 .{ 6860695058870476186, 4471839111886709592, 7828342285492709568, 87903640274981819 },
1292 .{ 14583324717644598331, 4496120889473451238, 5290040788305728466, 89624690099949049 },
1293 .{ 18093669366515003715, 12879506572606942994, 18005739787089675377, 91379436055028227 },
1294 .{ 17997493966862379937, 14646222655265145582, 10265023312844161858, 93168537870790806 },
1295 .{ 12283848109039722318, 11290258077250314935, 9878160025624946825, 94992668194556404 },
1296 .{ 8087752761883078164, 5262596608437575693, 11093553063763274413, 96852512843287537 },
1297 .{ 15027787746776840781, 12250273651168257752, 9290470558712181914, 98748771061435726 },
1298 .{ 15003915578366724489, 2937334162439764327, 5404085603526796602, 100682155783835929 },
1299 .{ 5225610465224746757, 14932114897406142027, 2774647558180708010, 102653393903748137 },
1300 .{ 17112957703385190360, 12069082008339002412, 3901112447086388439, 104663226546146909 },
1301 .{ 4062324464323300238, 3992768146772240329, 15757196565593695724, 106712409346361594 },
1302 .{ 5525364615810306701, 11855206026704935156, 11344868740897365300, 108801712734172003 },
1303 .{ 9274143661888462646, 4478365862348432381, 18010077872551661771, 110931922223466333 },
1304 .{ 12604141221930060148, 8930937759942591500, 9382183116147201338, 113103838707570263 },
1305 .{ 14513929377491886653, 1410646149696279084, 587092196850797612, 115318278760358235 },
1306 .{ 2226851524999454362, 7717102471110805679, 7187441550995571734, 117576074943260147 },
1307 .{ 5527526061344932763, 2347100676188369132, 16976241418824030445, 119878076118278875 },
1308 .{ 6088479778147221611, 17669593130014777580, 10991124207197663546, 122225147767136307 },
1309 .{ 11107734086759692041, 3391795220306863431, 17233960908859089158, 124618172316667879 },
1310 .{ 7913172514655155198, 17726879005381242552, 641069866244011540, 127058049470587962 },
1311 .{ 12596991768458713949, 15714785522479904446, 6035972567136116512, 129545696547750811 },
1312 .{ 16901996933781815980, 4275085211437148707, 14091642539965169063, 132082048827034281 },
1313 .{ 7524574627987869240, 15661204384239316051, 2444526454225712267, 134668059898975949 },
1314 .{ 8199251625090479942, 6803282222165044067, 16064817666437851504, 137304702024293857 },
1315 .{ 4453256673338111920, 15269922543084434181, 3139961729834750852, 139992966499426682 },
1316 .{ 15841763546372731299, 3013174075437671812, 4383755396295695606, 142733864029230733 },
1317 .{ 9771896230907310329, 4900659362437687569, 12386126719044266361, 72764212553486967 },
1318 .{ 9420455527449565190, 1859606122611023693, 6555040298902684281, 74188850200884818 },
1319 .{ 5146105983135678095, 2287300449992174951, 4325371679080264751, 75641380576797959 },
1320 .{ 11019359372592553360, 8422686425957443718, 7175176077944048210, 77122349788024458 },
1321 .{ 11005742969399620716, 4132174559240043701, 9372258443096612118, 78632314633490790 },
1322 .{ 8887589641394725840, 8029899502466543662, 14582206497241572853, 80171842813591127 },
1323 .{ 360247523705545899, 12568341805293354211, 14653258284762517866, 81741513143625247 },
1324 .{ 12314272731984275834, 4740745023227177044, 6141631472368337539, 83341915771415304 },
1325 .{ 441052047733984759, 7940090120939869826, 11750200619921094248, 84973652399183278 },
1326 .{ 3436657868127012749, 9187006432149937667, 16389726097323041290, 86637336509772529 },
1327 .{ 13490220260784534044, 15339072891382896702, 8846102360835316895, 88333593597298497 },
1328 .{ 4125672032094859833, 158347675704003277, 10592598512749774447, 90063061402315272 },
1329 .{ 12189928252974395775, 2386931199439295891, 7009030566469913276, 91826390151586454 },
1330 .{ 9256479608339282969, 2844900158963599229, 11148388908923225596, 93624242802550437 },
1331 .{ 11584393507658707408, 2863659090805147914, 9873421561981063551, 95457295292572042 },
1332 .{ 13984297296943171390, 1931468383973130608, 12905719743235082319, 97326236793074198 },
1333 .{ 5837045222254987499, 10213498696735864176, 14893951506257020749, 99231769968645227 },
1334};
1335
1336// Unfortunately, the results are sometimes off by one or two. We use an additional
1337// lookup table to store those cases and adjust the result.
1338const FLOAT128_POW5_ERRORS: [156]u64 = .{
1339 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x9555596400000000,
1340 0x65a6569525565555, 0x4415551445449655, 0x5105015504144541, 0x65a69969a6965964,
1341 0x5054955969959656, 0x5105154515554145, 0x4055511051591555, 0x5500514455550115,
1342 0x0041140014145515, 0x1005440545511051, 0x0014405450411004, 0x0414440010500000,
1343 0x0044000440010040, 0x5551155000004001, 0x4554555454544114, 0x5150045544005441,
1344 0x0001111400054501, 0x6550955555554554, 0x1504159645559559, 0x4105055141454545,
1345 0x1411541410405454, 0x0415555044545555, 0x0014154115405550, 0x1540055040411445,
1346 0x0000000500000000, 0x5644000000000000, 0x1155555591596555, 0x0410440054569565,
1347 0x5145100010010005, 0x0555041405500150, 0x4141450455140450, 0x0000000144000140,
1348 0x5114004001105410, 0x4444100404005504, 0x0414014410001015, 0x5145055155555015,
1349 0x0141041444445540, 0x0000100451541414, 0x4105041104155550, 0x0500501150451145,
1350 0x1001050000004114, 0x5551504400141045, 0x5110545410151454, 0x0100001400004040,
1351 0x5040010111040000, 0x0140000150541100, 0x4400140400104110, 0x5011014405545004,
1352 0x0000000044155440, 0x0000000010000000, 0x1100401444440001, 0x0040401010055111,
1353 0x5155155551405454, 0x0444440015514411, 0x0054505054014101, 0x0451015441115511,
1354 0x1541411401140551, 0x4155104514445110, 0x4141145450145515, 0x5451445055155050,
1355 0x4400515554110054, 0x5111145104501151, 0x565a655455500501, 0x5565555555525955,
1356 0x0550511500405695, 0x4415504051054544, 0x6555595965555554, 0x0100915915555655,
1357 0x5540001510001001, 0x5450051414000544, 0x1405010555555551, 0x5555515555644155,
1358 0x5555055595496555, 0x5451045004415000, 0x5450510144040144, 0x5554155555556455,
1359 0x5051555495415555, 0x5555554555555545, 0x0000000010005455, 0x4000005000040000,
1360 0x5565555555555954, 0x5554559555555505, 0x9645545495552555, 0x4000400055955564,
1361 0x0040000000000001, 0x4004100100000000, 0x5540040440000411, 0x4565555955545644,
1362 0x1140659549651556, 0x0100000410010000, 0x5555515400004001, 0x5955545555155255,
1363 0x5151055545505556, 0x5051454510554515, 0x0501500050415554, 0x5044154005441005,
1364 0x1455445450550455, 0x0010144055144545, 0x0000401100000004, 0x1050145050000010,
1365 0x0415004554011540, 0x1000510100151150, 0x0100040400001144, 0x0000000000000000,
1366 0x0550004400000100, 0x0151145041451151, 0x0000400400005450, 0x0000100044010004,
1367 0x0100054100050040, 0x0504400005410010, 0x4011410445500105, 0x0000404000144411,
1368 0x0101504404500000, 0x0000005044400400, 0x0000000014000100, 0x0404440414000000,
1369 0x5554100410000140, 0x4555455544505555, 0x5454105055455455, 0x0115454155454015,
1370 0x4404110000045100, 0x4400001100101501, 0x6596955956966a94, 0x0040655955665965,
1371 0x5554144400100155, 0xa549495401011041, 0x5596555565955555, 0x5569965959549555,
1372 0x969565a655555456, 0x0000001000000000, 0x0000000040000140, 0x0000040100000000,
1373 0x1415454400000000, 0x5410415411454114, 0x0400040104000154, 0x0504045000000411,
1374 0x0000001000000010, 0x5554000000001040, 0x5549155551556595, 0x1455541055515555,
1375 0x0510555454554541, 0x9555555555540455, 0x6455456555556465, 0x4524565555654514,
1376 0x5554655255559545, 0x9555455441155556, 0x0000000051515555, 0x0010005040000550,
1377 0x5044044040000000, 0x1045040440010500, 0x0000400000040000, 0x0000000000000000,
1378};
1379
1380const FLOAT128_POW5_INV_SPLIT: [89][4]u64 = .{
1381 .{ 0, 0, 0, 144115188075855872 },
1382 .{ 1573859546583440065, 2691002611772552616, 6763753280790178510, 141347765182270746 },
1383 .{ 12960290449513840412, 12345512957918226762, 18057899791198622765, 138633484706040742 },
1384 .{ 7615871757716765416, 9507132263365501332, 4879801712092008245, 135971326161092377 },
1385 .{ 7869961150745287587, 5804035291554591636, 8883897266325833928, 133360288657597085 },
1386 .{ 2942118023529634767, 15128191429820565086, 10638459445243230718, 130799390525667397 },
1387 .{ 14188759758411913794, 5362791266439207815, 8068821289119264054, 128287668946279217 },
1388 .{ 7183196927902545212, 1952291723540117099, 12075928209936341512, 125824179589281448 },
1389 .{ 5672588001402349748, 17892323620748423487, 9874578446960390364, 123407996258356868 },
1390 .{ 4442590541217566325, 4558254706293456445, 10343828952663182727, 121038210542800766 },
1391 .{ 3005560928406962566, 2082271027139057888, 13961184524927245081, 118713931475986426 },
1392 .{ 13299058168408384786, 17834349496131278595, 9029906103900731664, 116434285200389047 },
1393 .{ 5414878118283973035, 13079825470227392078, 17897304791683760280, 114198414639042157 },
1394 .{ 14609755883382484834, 14991702445765844156, 3269802549772755411, 112005479173303009 },
1395 .{ 15967774957605076027, 2511532636717499923, 16221038267832563171, 109854654326805788 },
1396 .{ 9269330061621627145, 3332501053426257392, 16223281189403734630, 107745131455483836 },
1397 .{ 16739559299223642282, 1873986623300664530, 6546709159471442872, 105676117443544318 },
1398 .{ 17116435360051202055, 1359075105581853924, 2038341371621886470, 103646834405281051 },
1399 .{ 17144715798009627550, 3201623802661132408, 9757551605154622431, 101656519392613377 },
1400 .{ 17580479792687825857, 6546633380567327312, 15099972427870912398, 99704424108241124 },
1401 .{ 9726477118325522902, 14578369026754005435, 11728055595254428803, 97789814624307808 },
1402 .{ 134593949518343635, 5715151379816901985, 1660163707976377376, 95911971106466306 },
1403 .{ 5515914027713859358, 7124354893273815720, 5548463282858794077, 94070187543243255 },
1404 .{ 6188403395862945512, 5681264392632320838, 15417410852121406654, 92263771480600430 },
1405 .{ 15908890877468271457, 10398888261125597540, 4817794962769172309, 90492043761593298 },
1406 .{ 1413077535082201005, 12675058125384151580, 7731426132303759597, 88754338271028867 },
1407 .{ 1486733163972670293, 11369385300195092554, 11610016711694864110, 87050001685026843 },
1408 .{ 8788596583757589684, 3978580923851924802, 9255162428306775812, 85378393225389919 },
1409 .{ 7203518319660962120, 15044736224407683725, 2488132019818199792, 83738884418690858 },
1410 .{ 4004175967662388707, 18236988667757575407, 15613100370957482671, 82130858859985791 },
1411 .{ 18371903370586036463, 53497579022921640, 16465963977267203307, 80553711981064899 },
1412 .{ 10170778323887491315, 1999668801648976001, 10209763593579456445, 79006850823153334 },
1413 .{ 17108131712433974546, 16825784443029944237, 2078700786753338945, 77489693813976938 },
1414 .{ 17221789422665858532, 12145427517550446164, 5391414622238668005, 76001670549108934 },
1415 .{ 4859588996898795878, 1715798948121313204, 3950858167455137171, 74542221577515387 },
1416 .{ 13513469241795711526, 631367850494860526, 10517278915021816160, 73110798191218799 },
1417 .{ 11757513142672073111, 2581974932255022228, 17498959383193606459, 143413724438001539 },
1418 .{ 14524355192525042817, 5640643347559376447, 1309659274756813016, 140659771648132296 },
1419 .{ 2765095348461978538, 11021111021896007722, 3224303603779962366, 137958702611185230 },
1420 .{ 12373410389187981037, 13679193545685856195, 11644609038462631561, 135309501808182158 },
1421 .{ 12813176257562780151, 3754199046160268020, 9954691079802960722, 132711173221007413 },
1422 .{ 17557452279667723458, 3237799193992485824, 17893947919029030695, 130162739957935629 },
1423 .{ 14634200999559435155, 4123869946105211004, 6955301747350769239, 127663243886350468 },
1424 .{ 2185352760627740240, 2864813346878886844, 13049218671329690184, 125211745272516185 },
1425 .{ 6143438674322183002, 10464733336980678750, 6982925169933978309, 122807322428266620 },
1426 .{ 1099509117817174576, 10202656147550524081, 754997032816608484, 120449071364478757 },
1427 .{ 2410631293559367023, 17407273750261453804, 15307291918933463037, 118136105451200587 },
1428 .{ 12224968375134586697, 1664436604907828062, 11506086230137787358, 115867555084305488 },
1429 .{ 3495926216898000888, 18392536965197424288, 10992889188570643156, 113642567358547782 },
1430 .{ 8744506286256259680, 3966568369496879937, 18342264969761820037, 111460305746896569 },
1431 .{ 7689600520560455039, 5254331190877624630, 9628558080573245556, 109319949786027263 },
1432 .{ 11862637625618819436, 3456120362318976488, 14690471063106001082, 107220694767852583 },
1433 .{ 5697330450030126444, 12424082405392918899, 358204170751754904, 105161751436977040 },
1434 .{ 11257457505097373622, 15373192700214208870, 671619062372033814, 103142345693961148 },
1435 .{ 16850355018477166700, 1913910419361963966, 4550257919755970531, 101161718304283822 },
1436 .{ 9670835567561997011, 10584031339132130638, 3060560222974851757, 99219124612893520 },
1437 .{ 7698686577353054710, 11689292838639130817, 11806331021588878241, 97313834264240819 },
1438 .{ 12233569599615692137, 3347791226108469959, 10333904326094451110, 95445130927687169 },
1439 .{ 13049400362825383933, 17142621313007799680, 3790542585289224168, 93612312028186576 },
1440 .{ 12430457242474442072, 5625077542189557960, 14765055286236672238, 91814688482138969 },
1441 .{ 4759444137752473128, 2230562561567025078, 4954443037339580076, 90051584438315940 },
1442 .{ 7246913525170274758, 8910297835195760709, 4015904029508858381, 88322337023761438 },
1443 .{ 12854430245836432067, 8135139748065431455, 11548083631386317976, 86626296094571907 },
1444 .{ 4848827254502687803, 4789491250196085625, 3988192420450664125, 84962823991462151 },
1445 .{ 7435538409611286684, 904061756819742353, 14598026519493048444, 83331295300025028 },
1446 .{ 11042616160352530997, 8948390828345326218, 10052651191118271927, 81731096615594853 },
1447 .{ 11059348291563778943, 11696515766184685544, 3783210511290897367, 80161626312626082 },
1448 .{ 7020010856491885826, 5025093219346041680, 8960210401638911765, 78622294318500592 },
1449 .{ 17732844474490699984, 7820866704994446502, 6088373186798844243, 77112521891678506 },
1450 .{ 688278527545590501, 3045610706602776618, 8684243536999567610, 75631741404109150 },
1451 .{ 2734573255120657297, 3903146411440697663, 9470794821691856713, 74179396127820347 },
1452 .{ 15996457521023071259, 4776627823451271680, 12394856457265744744, 72754940025605801 },
1453 .{ 13492065758834518331, 7390517611012222399, 1630485387832860230, 142715675091463768 },
1454 .{ 13665021627282055864, 9897834675523659302, 17907668136755296849, 139975126841173266 },
1455 .{ 9603773719399446181, 10771916301484339398, 10672699855989487527, 137287204938390542 },
1456 .{ 3630218541553511265, 8139010004241080614, 2876479648932814543, 134650898807055963 },
1457 .{ 8318835909686377084, 9525369258927993371, 2796120270400437057, 132065217277054270 },
1458 .{ 11190003059043290163, 12424345635599592110, 12539346395388933763, 129529188211565064 },
1459 .{ 8701968833973242276, 820569587086330727, 2315591597351480110, 127041858141569228 },
1460 .{ 5115113890115690487, 16906305245394587826, 9899749468931071388, 124602291907373862 },
1461 .{ 15543535488939245974, 10945189844466391399, 3553863472349432246, 122209572307020975 },
1462 .{ 7709257252608325038, 1191832167690640880, 15077137020234258537, 119862799751447719 },
1463 .{ 7541333244210021737, 9790054727902174575, 5160944773155322014, 117561091926268545 },
1464 .{ 12297384708782857832, 1281328873123467374, 4827925254630475769, 115303583460052092 },
1465 .{ 13243237906232367265, 15873887428139547641, 3607993172301799599, 113089425598968120 },
1466 .{ 11384616453739611114, 15184114243769211033, 13148448124803481057, 110917785887682141 },
1467 .{ 17727970963596660683, 1196965221832671990, 14537830463956404138, 108787847856377790 },
1468 .{ 17241367586707330931, 8880584684128262874, 11173506540726547818, 106698810713789254 },
1469 .{ 7184427196661305643, 14332510582433188173, 14230167953789677901, 104649889046128358 },
1470};
1471
1472const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{
1473 0x1144155514145504, 0x0000541555401141, 0x0000000000000000, 0x0154454000000000,
1474 0x4114105515544440, 0x0001001111500415, 0x4041411410011000, 0x5550114515155014,
1475 0x1404100041554551, 0x0515000450404410, 0x5054544401140004, 0x5155501005555105,
1476 0x1144141000105515, 0x0541500000500000, 0x1104105540444140, 0x4000015055514110,
1477 0x0054010450004005, 0x4155515404100005, 0x5155145045155555, 0x1511555515440558,
1478 0x5558544555515555, 0x0000000000000010, 0x5004000000000050, 0x1415510100000010,
1479 0x4545555444514500, 0x5155151555555551, 0x1441540144044554, 0x5150104045544400,
1480 0x5450545401444040, 0x5554455045501400, 0x4655155555555145, 0x1000010055455055,
1481 0x1000004000055004, 0x4455405104000005, 0x4500114504150545, 0x0000000014000000,
1482 0x5450000000000000, 0x5514551511445555, 0x4111501040555451, 0x4515445500054444,
1483 0x5101500104100441, 0x1545115155545055, 0x0000000000000000, 0x1554000000100000,
1484 0x5555545595551555, 0x5555051851455955, 0x5555555555555559, 0x0000400011001555,
1485 0x0000004400040000, 0x5455511555554554, 0x5614555544115445, 0x6455156145555155,
1486 0x5455855455415455, 0x5515555144555545, 0x0114400000145155, 0x0000051000450511,
1487 0x4455154554445100, 0x4554150141544455, 0x65955555559a5965, 0x5555555854559559,
1488 0x9569654559616595, 0x1040044040005565, 0x1010010500011044, 0x1554015545154540,
1489 0x4440555401545441, 0x1014441450550105, 0x4545400410504145, 0x5015111541040151,
1490 0x5145051154000410, 0x1040001044545044, 0x4001400000151410, 0x0540000044040000,
1491 0x0510555454411544, 0x0400054054141550, 0x1001041145001100, 0x0000000140000000,
1492 0x0000000014100000, 0x1544005454000140, 0x4050055505445145, 0x0011511104504155,
1493 0x5505544415045055, 0x1155154445515554, 0x0000000000004555, 0x0000000000000000,
1494 0x5101010510400004, 0x1514045044440400, 0x5515519555515555, 0x4554545441555545,
1495 0x1551055955551515, 0x0150000011505515, 0x0044005040400000, 0x0004001004010050,
1496 0x0000051004450414, 0x0114001101001144, 0x0401000001000001, 0x4500010001000401,
1497 0x0004100000005000, 0x0105000441101100, 0x0455455550454540, 0x5404050144105505,
1498 0x4101510540555455, 0x1055541411451555, 0x5451445110115505, 0x1154110010101545,
1499 0x1145140450054055, 0x5555565415551554, 0x1550559555555555, 0x5555541545045141,
1500 0x4555455450500100, 0x5510454545554555, 0x1510140115045455, 0x1001050040111510,
1501 0x5555454555555504, 0x9954155545515554, 0x6596656555555555, 0x0140410051555559,
1502 0x0011104010001544, 0x965669659a680501, 0x5655a55955556955, 0x4015111014404514,
1503 0x1414155554505145, 0x0540040011051404, 0x1010000000015005, 0x0010054050004410,
1504 0x5041104014000100, 0x4440010500100001, 0x1155510504545554, 0x0450151545115541,
1505 0x4000100400110440, 0x1004440010514440, 0x0000115050450000, 0x0545404455541500,
1506 0x1051051555505101, 0x5505144554544144, 0x4550545555515550, 0x0015400450045445,
1507 0x4514155400554415, 0x4555055051050151, 0x1511441450001014, 0x4544554510404414,
1508 0x4115115545545450, 0x5500541555551555, 0x5550010544155015, 0x0144414045545500,
1509 0x4154050001050150, 0x5550511111000145, 0x1114504055000151, 0x5104041101451040,
1510 0x0010501401051441, 0x0010501450504401, 0x4554585440044444, 0x5155555951450455,
1511 0x0040000400105555, 0x0000000000000001,
1512};
1513
1514// zig fmt: on
1515
1516const builtin = @import("builtin");
1517
1518fn check(comptime T: type, value: T, comptime expected: []const u8) !void {
1519 const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
1520
1521 var buf: [6000]u8 = undefined;
1522 const value_bits: I = @bitCast(value);
1523 const s = try formatFloat(&buf, value, .{});
1524 try std.testing.expectEqualStrings(expected, s);
1525
1526 if (T == f80 and builtin.target.os.tag == .windows and builtin.target.cpu.arch == .x86_64) return;
1527
1528 const o = try std.fmt.parseFloat(T, s);
1529 const o_bits: I = @bitCast(o);
1530
1531 if (std.math.isNan(value)) {
1532 try std.testing.expect(std.math.isNan(o));
1533 } else {
1534 try std.testing.expectEqual(value_bits, o_bits);
1535 }
1536}
1537
1538test "format f32" {
1539 try check(f32, 0.0, "0e0");
1540 try check(f32, -0.0, "-0e0");
1541 try check(f32, 1.0, "1e0");
1542 try check(f32, -1.0, "-1e0");
1543 try check(f32, std.math.nan(f32), "nan");
1544 try check(f32, std.math.inf(f32), "inf");
1545 try check(f32, -std.math.inf(f32), "-inf");
1546 try check(f32, 1.1754944e-38, "1.1754944e-38");
1547 try check(f32, @bitCast(@as(u32, 0x7f7fffff)), "3.4028235e38");
1548 try check(f32, @bitCast(@as(u32, 1)), "1e-45");
1549 try check(f32, 3.355445E7, "3.355445e7");
1550 try check(f32, 8.999999e9, "9e9");
1551 try check(f32, 3.4366717e10, "3.436672e10");
1552 try check(f32, 3.0540412e5, "3.0540412e5");
1553 try check(f32, 8.0990312e3, "8.0990312e3");
1554 try check(f32, 2.4414062e-4, "2.4414062e-4");
1555 try check(f32, 2.4414062e-3, "2.4414062e-3");
1556 try check(f32, 4.3945312e-3, "4.3945312e-3");
1557 try check(f32, 6.3476562e-3, "6.3476562e-3");
1558 try check(f32, 4.7223665e21, "4.7223665e21");
1559 try check(f32, 8388608.0, "8.388608e6");
1560 try check(f32, 1.6777216e7, "1.6777216e7");
1561 try check(f32, 3.3554436e7, "3.3554436e7");
1562 try check(f32, 6.7131496e7, "6.7131496e7");
1563 try check(f32, 1.9310392e-38, "1.9310392e-38");
1564 try check(f32, -2.47e-43, "-2.47e-43");
1565 try check(f32, 1.993244e-38, "1.993244e-38");
1566 try check(f32, 4103.9003, "4.1039004e3");
1567 try check(f32, 5.3399997e9, "5.3399997e9");
1568 try check(f32, 6.0898e-39, "6.0898e-39");
1569 try check(f32, 0.0010310042, "1.0310042e-3");
1570 try check(f32, 2.8823261e17, "2.882326e17");
1571 try check(f32, 7.038531e-26, "7.038531e-26");
1572 try check(f32, 9.2234038e17, "9.223404e17");
1573 try check(f32, 6.7108872e7, "6.710887e7");
1574 try check(f32, 1.0e-44, "1e-44");
1575 try check(f32, 2.816025e14, "2.816025e14");
1576 try check(f32, 9.223372e18, "9.223372e18");
1577 try check(f32, 1.5846085e29, "1.5846086e29");
1578 try check(f32, 1.1811161e19, "1.1811161e19");
1579 try check(f32, 5.368709e18, "5.368709e18");
1580 try check(f32, 4.6143165e18, "4.6143166e18");
1581 try check(f32, 0.007812537, "7.812537e-3");
1582 try check(f32, 1.4e-45, "1e-45");
1583 try check(f32, 1.18697724e20, "1.18697725e20");
1584 try check(f32, 1.00014165e-36, "1.00014165e-36");
1585 try check(f32, 200.0, "2e2");
1586 try check(f32, 3.3554432e7, "3.3554432e7");
1587
1588 try check(f32, 1.0, "1e0");
1589 try check(f32, 1.2, "1.2e0");
1590 try check(f32, 1.23, "1.23e0");
1591 try check(f32, 1.234, "1.234e0");
1592 try check(f32, 1.2345, "1.2345e0");
1593 try check(f32, 1.23456, "1.23456e0");
1594 try check(f32, 1.234567, "1.234567e0");
1595 try check(f32, 1.2345678, "1.2345678e0");
1596 try check(f32, 1.23456735e-36, "1.23456735e-36");
1597}
1598
1599test "format f64" {
1600 try check(f64, 0.0, "0e0");
1601 try check(f64, -0.0, "-0e0");
1602 try check(f64, 1.0, "1e0");
1603 try check(f64, -1.0, "-1e0");
1604 try check(f64, std.math.nan(f64), "nan");
1605 try check(f64, std.math.inf(f64), "inf");
1606 try check(f64, -std.math.inf(f64), "-inf");
1607 try check(f64, 2.2250738585072014e-308, "2.2250738585072014e-308");
1608 try check(f64, @bitCast(@as(u64, 0x7fefffffffffffff)), "1.7976931348623157e308");
1609 try check(f64, @bitCast(@as(u64, 1)), "5e-324");
1610 try check(f64, 2.98023223876953125e-8, "2.9802322387695312e-8");
1611 try check(f64, -2.109808898695963e16, "-2.109808898695963e16");
1612 try check(f64, 4.940656e-318, "4.940656e-318");
1613 try check(f64, 1.18575755e-316, "1.18575755e-316");
1614 try check(f64, 2.989102097996e-312, "2.989102097996e-312");
1615 try check(f64, 9.0608011534336e15, "9.0608011534336e15");
1616 try check(f64, 4.708356024711512e18, "4.708356024711512e18");
1617 try check(f64, 9.409340012568248e18, "9.409340012568248e18");
1618 try check(f64, 1.2345678, "1.2345678e0");
1619 try check(f64, @bitCast(@as(u64, 0x4830f0cf064dd592)), "5.764607523034235e39");
1620 try check(f64, @bitCast(@as(u64, 0x4840f0cf064dd592)), "1.152921504606847e40");
1621 try check(f64, @bitCast(@as(u64, 0x4850f0cf064dd592)), "2.305843009213694e40");
1622
1623 try check(f64, 1, "1e0");
1624 try check(f64, 1.2, "1.2e0");
1625 try check(f64, 1.23, "1.23e0");
1626 try check(f64, 1.234, "1.234e0");
1627 try check(f64, 1.2345, "1.2345e0");
1628 try check(f64, 1.23456, "1.23456e0");
1629 try check(f64, 1.234567, "1.234567e0");
1630 try check(f64, 1.2345678, "1.2345678e0");
1631 try check(f64, 1.23456789, "1.23456789e0");
1632 try check(f64, 1.234567895, "1.234567895e0");
1633 try check(f64, 1.2345678901, "1.2345678901e0");
1634 try check(f64, 1.23456789012, "1.23456789012e0");
1635 try check(f64, 1.234567890123, "1.234567890123e0");
1636 try check(f64, 1.2345678901234, "1.2345678901234e0");
1637 try check(f64, 1.23456789012345, "1.23456789012345e0");
1638 try check(f64, 1.234567890123456, "1.234567890123456e0");
1639 try check(f64, 1.2345678901234567, "1.2345678901234567e0");
1640
1641 try check(f64, 4.294967294, "4.294967294e0");
1642 try check(f64, 4.294967295, "4.294967295e0");
1643 try check(f64, 4.294967296, "4.294967296e0");
1644 try check(f64, 4.294967297, "4.294967297e0");
1645 try check(f64, 4.294967298, "4.294967298e0");
1646}
1647
1648test "format f80" {
1649 try check(f80, 0.0, "0e0");
1650 try check(f80, -0.0, "-0e0");
1651 try check(f80, 1.0, "1e0");
1652 try check(f80, -1.0, "-1e0");
1653 try check(f80, std.math.nan(f80), "nan");
1654 try check(f80, std.math.inf(f80), "inf");
1655 try check(f80, -std.math.inf(f80), "-inf");
1656
1657 try check(f80, 2.2250738585072014e-308, "2.2250738585072014e-308");
1658 try check(f80, 2.98023223876953125e-8, "2.98023223876953125e-8");
1659 try check(f80, -2.109808898695963e16, "-2.109808898695963e16");
1660 try check(f80, 4.940656e-318, "4.940656e-318");
1661 try check(f80, 1.18575755e-316, "1.18575755e-316");
1662 try check(f80, 2.989102097996e-312, "2.989102097996e-312");
1663 try check(f80, 9.0608011534336e15, "9.0608011534336e15");
1664 try check(f80, 4.708356024711512e18, "4.708356024711512e18");
1665 try check(f80, 9.409340012568248e18, "9.409340012568248e18");
1666 try check(f80, 1.2345678, "1.2345678e0");
1667}
1668
1669test "format f128" {
1670 try check(f128, 0.0, "0e0");
1671 try check(f128, -0.0, "-0e0");
1672 try check(f128, 1.0, "1e0");
1673 try check(f128, -1.0, "-1e0");
1674 try check(f128, std.math.nan(f128), "nan");
1675 try check(f128, std.math.inf(f128), "inf");
1676 try check(f128, -std.math.inf(f128), "-inf");
1677
1678 try check(f128, 2.2250738585072014e-308, "2.2250738585072014e-308");
1679 try check(f128, 2.98023223876953125e-8, "2.98023223876953125e-8");
1680 try check(f128, -2.109808898695963e16, "-2.109808898695963e16");
1681 try check(f128, 4.940656e-318, "4.940656e-318");
1682 try check(f128, 1.18575755e-316, "1.18575755e-316");
1683 try check(f128, 2.989102097996e-312, "2.989102097996e-312");
1684 try check(f128, 9.0608011534336e15, "9.0608011534336e15");
1685 try check(f128, 4.708356024711512e18, "4.708356024711512e18");
1686 try check(f128, 9.409340012568248e18, "9.409340012568248e18");
1687 try check(f128, 1.2345678, "1.2345678e0");
1688}
1689
1690test "format float to decimal with zero precision" {
1691 try expectFmt("5", "{d:.0}", .{5});
1692 try expectFmt("6", "{d:.0}", .{6});
1693 try expectFmt("7", "{d:.0}", .{7});
1694 try expectFmt("8", "{d:.0}", .{8});
1695}
lib/std/fs/File.zig+772-463
......@@ -1,3 +1,20 @@
1const builtin = @import("builtin");
2const Os = std.builtin.Os;
3const native_os = builtin.os.tag;
4const is_windows = native_os == .windows;
5
6const File = @This();
7const std = @import("../std.zig");
8const Allocator = std.mem.Allocator;
9const posix = std.posix;
10const io = std.io;
11const math = std.math;
12const assert = std.debug.assert;
13const linux = std.os.linux;
14const windows = std.os.windows;
15const maxInt = std.math.maxInt;
16const Alignment = std.mem.Alignment;
17
118/// The OS-specific file descriptor or file handle.
219handle: Handle,
320
......@@ -168,6 +185,18 @@ pub const CreateFlags = struct {
168185 mode: Mode = default_mode,
169186};
170187
188pub fn stdout() File {
189 return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdOutput else posix.STDOUT_FILENO };
190}
191
192pub fn stderr() File {
193 return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdError else posix.STDERR_FILENO };
194}
195
196pub fn stdin() File {
197 return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdInput else posix.STDIN_FILENO };
198}
199
171200/// Upon success, the stream is in an uninitialized state. To continue using it,
172201/// you must use the open() function.
173202pub fn close(self: File) void {
......@@ -351,8 +380,10 @@ pub fn getPos(self: File) GetSeekPosError!u64 {
351380 return posix.lseek_CUR_get(self.handle);
352381}
353382
383pub const GetEndPosError = std.os.windows.GetFileSizeError || StatError;
384
354385/// TODO: integrate with async I/O
355pub fn getEndPos(self: File) GetSeekPosError!u64 {
386pub fn getEndPos(self: File) GetEndPosError!u64 {
356387 if (builtin.os.tag == .windows) {
357388 return windows.GetFileSizeEx(self.handle);
358389 }
......@@ -477,7 +508,6 @@ pub const Stat = struct {
477508pub const StatError = posix.FStatError;
478509
479510/// Returns `Stat` containing basic information about the `File`.
480/// Use `metadata` to retrieve more detailed information (e.g. creation time, permissions).
481511/// TODO: integrate with async I/O
482512pub fn stat(self: File) StatError!Stat {
483513 if (builtin.os.tag == .windows) {
......@@ -743,361 +773,6 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError!
743773 }
744774}
745775
746/// Cross-platform representation of file metadata.
747/// Platform-specific functionality is available through the `inner` field.
748pub const Metadata = struct {
749 /// Exposes platform-specific functionality.
750 inner: switch (builtin.os.tag) {
751 .windows => MetadataWindows,
752 .linux => MetadataLinux,
753 .wasi => MetadataWasi,
754 else => MetadataUnix,
755 },
756
757 const Self = @This();
758
759 /// Returns the size of the file
760 pub fn size(self: Self) u64 {
761 return self.inner.size();
762 }
763
764 /// Returns a `Permissions` struct, representing the permissions on the file
765 pub fn permissions(self: Self) Permissions {
766 return self.inner.permissions();
767 }
768
769 /// Returns the `Kind` of file.
770 /// On Windows, can only return: `.file`, `.directory`, `.sym_link` or `.unknown`
771 pub fn kind(self: Self) Kind {
772 return self.inner.kind();
773 }
774
775 /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
776 pub fn accessed(self: Self) i128 {
777 return self.inner.accessed();
778 }
779
780 /// Returns the time the file was modified in nanoseconds since UTC 1970-01-01
781 pub fn modified(self: Self) i128 {
782 return self.inner.modified();
783 }
784
785 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01
786 /// On Windows, this cannot return null
787 /// On Linux, this returns null if the filesystem does not support creation times
788 /// On Unices, this returns null if the filesystem or OS does not support creation times
789 /// On MacOS, this returns the ctime if the filesystem does not support creation times; this is insanity, and yet another reason to hate on Apple
790 pub fn created(self: Self) ?i128 {
791 return self.inner.created();
792 }
793};
794
795pub const MetadataUnix = struct {
796 stat: posix.Stat,
797
798 const Self = @This();
799
800 /// Returns the size of the file
801 pub fn size(self: Self) u64 {
802 return @intCast(self.stat.size);
803 }
804
805 /// Returns a `Permissions` struct, representing the permissions on the file
806 pub fn permissions(self: Self) Permissions {
807 return .{ .inner = .{ .mode = self.stat.mode } };
808 }
809
810 /// Returns the `Kind` of the file
811 pub fn kind(self: Self) Kind {
812 if (builtin.os.tag == .wasi and !builtin.link_libc) return switch (self.stat.filetype) {
813 .BLOCK_DEVICE => .block_device,
814 .CHARACTER_DEVICE => .character_device,
815 .DIRECTORY => .directory,
816 .SYMBOLIC_LINK => .sym_link,
817 .REGULAR_FILE => .file,
818 .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket,
819 else => .unknown,
820 };
821
822 const m = self.stat.mode & posix.S.IFMT;
823
824 switch (m) {
825 posix.S.IFBLK => return .block_device,
826 posix.S.IFCHR => return .character_device,
827 posix.S.IFDIR => return .directory,
828 posix.S.IFIFO => return .named_pipe,
829 posix.S.IFLNK => return .sym_link,
830 posix.S.IFREG => return .file,
831 posix.S.IFSOCK => return .unix_domain_socket,
832 else => {},
833 }
834
835 if (builtin.os.tag.isSolarish()) switch (m) {
836 posix.S.IFDOOR => return .door,
837 posix.S.IFPORT => return .event_port,
838 else => {},
839 };
840
841 return .unknown;
842 }
843
844 /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
845 pub fn accessed(self: Self) i128 {
846 const atime = self.stat.atime();
847 return @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec;
848 }
849
850 /// Returns the last time the file was modified in nanoseconds since UTC 1970-01-01
851 pub fn modified(self: Self) i128 {
852 const mtime = self.stat.mtime();
853 return @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec;
854 }
855
856 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01.
857 /// Returns null if this is not supported by the OS or filesystem
858 pub fn created(self: Self) ?i128 {
859 if (!@hasDecl(@TypeOf(self.stat), "birthtime")) return null;
860 const birthtime = self.stat.birthtime();
861
862 // If the filesystem doesn't support this the value *should* be:
863 // On FreeBSD: nsec = 0, sec = -1
864 // On NetBSD and OpenBSD: nsec = 0, sec = 0
865 // On MacOS, it is set to ctime -- we cannot detect this!!
866 switch (builtin.os.tag) {
867 .freebsd => if (birthtime.sec == -1 and birthtime.nsec == 0) return null,
868 .netbsd, .openbsd => if (birthtime.sec == 0 and birthtime.nsec == 0) return null,
869 .macos => {},
870 else => @compileError("Creation time detection not implemented for OS"),
871 }
872
873 return @as(i128, birthtime.sec) * std.time.ns_per_s + birthtime.nsec;
874 }
875};
876
877/// `MetadataUnix`, but using Linux's `statx` syscall.
878pub const MetadataLinux = struct {
879 statx: std.os.linux.Statx,
880
881 const Self = @This();
882
883 /// Returns the size of the file
884 pub fn size(self: Self) u64 {
885 return self.statx.size;
886 }
887
888 /// Returns a `Permissions` struct, representing the permissions on the file
889 pub fn permissions(self: Self) Permissions {
890 return Permissions{ .inner = PermissionsUnix{ .mode = self.statx.mode } };
891 }
892
893 /// Returns the `Kind` of the file
894 pub fn kind(self: Self) Kind {
895 const m = self.statx.mode & posix.S.IFMT;
896
897 switch (m) {
898 posix.S.IFBLK => return .block_device,
899 posix.S.IFCHR => return .character_device,
900 posix.S.IFDIR => return .directory,
901 posix.S.IFIFO => return .named_pipe,
902 posix.S.IFLNK => return .sym_link,
903 posix.S.IFREG => return .file,
904 posix.S.IFSOCK => return .unix_domain_socket,
905 else => {},
906 }
907
908 return .unknown;
909 }
910
911 /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
912 pub fn accessed(self: Self) i128 {
913 return @as(i128, self.statx.atime.sec) * std.time.ns_per_s + self.statx.atime.nsec;
914 }
915
916 /// Returns the last time the file was modified in nanoseconds since UTC 1970-01-01
917 pub fn modified(self: Self) i128 {
918 return @as(i128, self.statx.mtime.sec) * std.time.ns_per_s + self.statx.mtime.nsec;
919 }
920
921 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01.
922 /// Returns null if this is not supported by the filesystem, or on kernels before than version 4.11
923 pub fn created(self: Self) ?i128 {
924 if (self.statx.mask & std.os.linux.STATX_BTIME == 0) return null;
925 return @as(i128, self.statx.btime.sec) * std.time.ns_per_s + self.statx.btime.nsec;
926 }
927};
928
929pub const MetadataWasi = struct {
930 stat: std.os.wasi.filestat_t,
931
932 pub fn size(self: @This()) u64 {
933 return self.stat.size;
934 }
935
936 pub fn permissions(self: @This()) Permissions {
937 return .{ .inner = .{ .mode = self.stat.mode } };
938 }
939
940 pub fn kind(self: @This()) Kind {
941 return switch (self.stat.filetype) {
942 .BLOCK_DEVICE => .block_device,
943 .CHARACTER_DEVICE => .character_device,
944 .DIRECTORY => .directory,
945 .SYMBOLIC_LINK => .sym_link,
946 .REGULAR_FILE => .file,
947 .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket,
948 else => .unknown,
949 };
950 }
951
952 pub fn accessed(self: @This()) i128 {
953 return self.stat.atim;
954 }
955
956 pub fn modified(self: @This()) i128 {
957 return self.stat.mtim;
958 }
959
960 pub fn created(self: @This()) ?i128 {
961 return self.stat.ctim;
962 }
963};
964
965pub const MetadataWindows = struct {
966 attributes: windows.DWORD,
967 reparse_tag: windows.DWORD,
968 _size: u64,
969 access_time: i128,
970 modified_time: i128,
971 creation_time: i128,
972
973 const Self = @This();
974
975 /// Returns the size of the file
976 pub fn size(self: Self) u64 {
977 return self._size;
978 }
979
980 /// Returns a `Permissions` struct, representing the permissions on the file
981 pub fn permissions(self: Self) Permissions {
982 return .{ .inner = .{ .attributes = self.attributes } };
983 }
984
985 /// Returns the `Kind` of the file.
986 /// Can only return: `.file`, `.directory`, `.sym_link` or `.unknown`
987 pub fn kind(self: Self) Kind {
988 if (self.attributes & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) {
989 if (self.reparse_tag & windows.reparse_tag_name_surrogate_bit != 0) {
990 return .sym_link;
991 }
992 } else if (self.attributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) {
993 return .directory;
994 } else {
995 return .file;
996 }
997 return .unknown;
998 }
999
1000 /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
1001 pub fn accessed(self: Self) i128 {
1002 return self.access_time;
1003 }
1004
1005 /// Returns the time the file was modified in nanoseconds since UTC 1970-01-01
1006 pub fn modified(self: Self) i128 {
1007 return self.modified_time;
1008 }
1009
1010 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01.
1011 /// This never returns null, only returning an optional for compatibility with other OSes
1012 pub fn created(self: Self) ?i128 {
1013 return self.creation_time;
1014 }
1015};
1016
1017pub const MetadataError = posix.FStatError;
1018
1019pub fn metadata(self: File) MetadataError!Metadata {
1020 return .{
1021 .inner = switch (builtin.os.tag) {
1022 .windows => blk: {
1023 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
1024 var info: windows.FILE_ALL_INFORMATION = undefined;
1025
1026 const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);
1027 switch (rc) {
1028 .SUCCESS => {},
1029 // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer
1030 // size provided. This is treated as success because the type of variable-length information that this would be relevant for
1031 // (name, volume name, etc) we don't care about.
1032 .BUFFER_OVERFLOW => {},
1033 .INVALID_PARAMETER => unreachable,
1034 .ACCESS_DENIED => return error.AccessDenied,
1035 else => return windows.unexpectedStatus(rc),
1036 }
1037
1038 const reparse_tag: windows.DWORD = reparse_blk: {
1039 if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) {
1040 var tag_info: windows.FILE_ATTRIBUTE_TAG_INFO = undefined;
1041 const tag_rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &tag_info, @sizeOf(windows.FILE_ATTRIBUTE_TAG_INFO), .FileAttributeTagInformation);
1042 switch (tag_rc) {
1043 .SUCCESS => {},
1044 // INFO_LENGTH_MISMATCH and ACCESS_DENIED are the only documented possible errors
1045 // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/d295752f-ce89-4b98-8553-266d37c84f0e
1046 .INFO_LENGTH_MISMATCH => unreachable,
1047 .ACCESS_DENIED => return error.AccessDenied,
1048 else => return windows.unexpectedStatus(rc),
1049 }
1050 break :reparse_blk tag_info.ReparseTag;
1051 }
1052 break :reparse_blk 0;
1053 };
1054
1055 break :blk .{
1056 .attributes = info.BasicInformation.FileAttributes,
1057 .reparse_tag = reparse_tag,
1058 ._size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)),
1059 .access_time = windows.fromSysTime(info.BasicInformation.LastAccessTime),
1060 .modified_time = windows.fromSysTime(info.BasicInformation.LastWriteTime),
1061 .creation_time = windows.fromSysTime(info.BasicInformation.CreationTime),
1062 };
1063 },
1064 .linux => blk: {
1065 var stx = std.mem.zeroes(linux.Statx);
1066
1067 // We are gathering information for Metadata, which is meant to contain all the
1068 // native OS information about the file, so use all known flags.
1069 const rc = linux.statx(
1070 self.handle,
1071 "",
1072 linux.AT.EMPTY_PATH,
1073 linux.STATX_BASIC_STATS | linux.STATX_BTIME,
1074 &stx,
1075 );
1076
1077 switch (linux.E.init(rc)) {
1078 .SUCCESS => {},
1079 .ACCES => unreachable,
1080 .BADF => unreachable,
1081 .FAULT => unreachable,
1082 .INVAL => unreachable,
1083 .LOOP => unreachable,
1084 .NAMETOOLONG => unreachable,
1085 .NOENT => unreachable,
1086 .NOMEM => return error.SystemResources,
1087 .NOTDIR => unreachable,
1088 else => |err| return posix.unexpectedErrno(err),
1089 }
1090
1091 break :blk .{
1092 .statx = stx,
1093 };
1094 },
1095 .wasi => .{ .stat = try std.os.fstat_wasi(self.handle) },
1096 else => .{ .stat = try posix.fstat(self.handle) },
1097 },
1098 };
1099}
1100
1101776pub const UpdateTimesError = posix.FutimensError || windows.SetFileTimeError;
1102777
1103778/// The underlying file system may have a different granularity than nanoseconds,
......@@ -1130,19 +805,12 @@ pub fn updateTimes(
1130805 try posix.futimens(self.handle, &times);
1131806}
1132807
1133/// Reads all the bytes from the current position to the end of the file.
1134/// On success, caller owns returned buffer.
1135/// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
808/// Deprecated in favor of `Reader`.
1136809pub fn readToEndAlloc(self: File, allocator: Allocator, max_bytes: usize) ![]u8 {
1137810 return self.readToEndAllocOptions(allocator, max_bytes, null, .of(u8), null);
1138811}
1139812
1140/// Reads all the bytes from the current position to the end of the file.
1141/// On success, caller owns returned buffer.
1142/// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
1143/// If `size_hint` is specified the initial buffer size is calculated using
1144/// that value, otherwise an arbitrary value is used instead.
1145/// Allows specifying alignment and a sentinel value.
813/// Deprecated in favor of `Reader`.
1146814pub fn readToEndAllocOptions(
1147815 self: File,
1148816 allocator: Allocator,
......@@ -1161,7 +829,7 @@ pub fn readToEndAllocOptions(
1161829 var array_list = try std.ArrayListAligned(u8, alignment).initCapacity(allocator, initial_cap);
1162830 defer array_list.deinit();
1163831
1164 self.reader().readAllArrayListAligned(alignment, &array_list, max_bytes) catch |err| switch (err) {
832 self.deprecatedReader().readAllArrayListAligned(alignment, &array_list, max_bytes) catch |err| switch (err) {
1165833 error.StreamTooLong => return error.FileTooBig,
1166834 else => |e| return e,
1167835 };
......@@ -1184,8 +852,7 @@ pub fn read(self: File, buffer: []u8) ReadError!usize {
1184852 return posix.read(self.handle, buffer);
1185853}
1186854
1187/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
1188/// means the file reached the end. Reaching the end of a file is not an error condition.
855/// Deprecated in favor of `Reader`.
1189856pub fn readAll(self: File, buffer: []u8) ReadError!usize {
1190857 var index: usize = 0;
1191858 while (index != buffer.len) {
......@@ -1206,10 +873,7 @@ pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
1206873 return posix.pread(self.handle, buffer, offset);
1207874}
1208875
1209/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
1210/// means the file reached the end. Reaching the end of a file is not an error condition.
1211/// On Windows, this function currently does alter the file pointer.
1212/// https://github.com/ziglang/zig/issues/12783
876/// Deprecated in favor of `Reader`.
1213877pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
1214878 var index: usize = 0;
1215879 while (index != buffer.len) {
......@@ -1223,8 +887,7 @@ pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
1223887/// See https://github.com/ziglang/zig/issues/7699
1224888pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
1225889 if (is_windows) {
1226 // TODO improve this to use ReadFileScatter
1227 if (iovecs.len == 0) return @as(usize, 0);
890 if (iovecs.len == 0) return 0;
1228891 const first = iovecs[0];
1229892 return windows.ReadFile(self.handle, first.base[0..first.len], null);
1230893 }
......@@ -1232,19 +895,7 @@ pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
1232895 return posix.readv(self.handle, iovecs);
1233896}
1234897
1235/// Returns the number of bytes read. If the number read is smaller than the total bytes
1236/// from all the buffers, it means the file reached the end. Reaching the end of a file
1237/// is not an error condition.
1238///
1239/// The `iovecs` parameter is mutable because:
1240/// * This function needs to mutate the fields in order to handle partial
1241/// reads from the underlying OS layer.
1242/// * The OS layer expects pointer addresses to be inside the application's address space
1243/// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer
1244/// addresses when the length is zero. So this function modifies the base fields
1245/// when the length is zero.
1246///
1247/// Related open issue: https://github.com/ziglang/zig/issues/7699
898/// Deprecated in favor of `Reader`.
1248899pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {
1249900 if (iovecs.len == 0) return 0;
1250901
......@@ -1279,8 +930,7 @@ pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {
1279930/// https://github.com/ziglang/zig/issues/12783
1280931pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!usize {
1281932 if (is_windows) {
1282 // TODO improve this to use ReadFileScatter
1283 if (iovecs.len == 0) return @as(usize, 0);
933 if (iovecs.len == 0) return 0;
1284934 const first = iovecs[0];
1285935 return windows.ReadFile(self.handle, first.base[0..first.len], offset);
1286936 }
......@@ -1288,14 +938,7 @@ pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!u
1288938 return posix.preadv(self.handle, iovecs, offset);
1289939}
1290940
1291/// Returns the number of bytes read. If the number read is smaller than the total bytes
1292/// from all the buffers, it means the file reached the end. Reaching the end of a file
1293/// is not an error condition.
1294/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
1295/// order to handle partial reads from the underlying OS layer.
1296/// See https://github.com/ziglang/zig/issues/7699
1297/// On Windows, this function currently does alter the file pointer.
1298/// https://github.com/ziglang/zig/issues/12783
941/// Deprecated in favor of `Reader`.
1299942pub fn preadvAll(self: File, iovecs: []posix.iovec, offset: u64) PReadError!usize {
1300943 if (iovecs.len == 0) return 0;
1301944
......@@ -1328,6 +971,7 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize {
1328971 return posix.write(self.handle, bytes);
1329972}
1330973
974/// Deprecated in favor of `Writer`.
1331975pub fn writeAll(self: File, bytes: []const u8) WriteError!void {
1332976 var index: usize = 0;
1333977 while (index < bytes.len) {
......@@ -1345,8 +989,7 @@ pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
1345989 return posix.pwrite(self.handle, bytes, offset);
1346990}
1347991
1348/// On Windows, this function currently does alter the file pointer.
1349/// https://github.com/ziglang/zig/issues/12783
992/// Deprecated in favor of `Writer`.
1350993pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {
1351994 var index: usize = 0;
1352995 while (index < bytes.len) {
......@@ -1355,11 +998,10 @@ pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {
1355998}
1356999
13571000/// See https://github.com/ziglang/zig/issues/7699
1358/// See equivalent function: `std.net.Stream.writev`.
13591001pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
13601002 if (is_windows) {
13611003 // TODO improve this to use WriteFileScatter
1362 if (iovecs.len == 0) return @as(usize, 0);
1004 if (iovecs.len == 0) return 0;
13631005 const first = iovecs[0];
13641006 return windows.WriteFile(self.handle, first.base[0..first.len], null);
13651007 }
......@@ -1367,15 +1009,7 @@ pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
13671009 return posix.writev(self.handle, iovecs);
13681010}
13691011
1370/// The `iovecs` parameter is mutable because:
1371/// * This function needs to mutate the fields in order to handle partial
1372/// writes from the underlying OS layer.
1373/// * The OS layer expects pointer addresses to be inside the application's address space
1374/// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer
1375/// addresses when the length is zero. So this function modifies the base fields
1376/// when the length is zero.
1377/// See https://github.com/ziglang/zig/issues/7699
1378/// See equivalent function: `std.net.Stream.writevAll`.
1012/// Deprecated in favor of `Writer`.
13791013pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {
13801014 if (iovecs.len == 0) return;
13811015
......@@ -1405,8 +1039,7 @@ pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {
14051039/// https://github.com/ziglang/zig/issues/12783
14061040pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!usize {
14071041 if (is_windows) {
1408 // TODO improve this to use WriteFileScatter
1409 if (iovecs.len == 0) return @as(usize, 0);
1042 if (iovecs.len == 0) return 0;
14101043 const first = iovecs[0];
14111044 return windows.WriteFile(self.handle, first.base[0..first.len], offset);
14121045 }
......@@ -1414,14 +1047,9 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError
14141047 return posix.pwritev(self.handle, iovecs, offset);
14151048}
14161049
1417/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
1418/// order to handle partial writes from the underlying OS layer.
1419/// See https://github.com/ziglang/zig/issues/7699
1420/// On Windows, this function currently does alter the file pointer.
1421/// https://github.com/ziglang/zig/issues/12783
1050/// Deprecated in favor of `Writer`.
14221051pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!void {
14231052 if (iovecs.len == 0) return;
1424
14251053 var i: usize = 0;
14261054 var off: u64 = 0;
14271055 while (true) {
......@@ -1439,14 +1067,14 @@ pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteEr
14391067
14401068pub const CopyRangeError = posix.CopyFileRangeError;
14411069
1070/// Deprecated in favor of `Writer`.
14421071pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
14431072 const adjusted_len = math.cast(usize, len) orelse maxInt(usize);
14441073 const result = try posix.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0);
14451074 return result;
14461075}
14471076
1448/// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it
1449/// means the in file reached the end. Reaching the end of a file is not an error condition.
1077/// Deprecated in favor of `Writer`.
14501078pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
14511079 var total_bytes_copied: u64 = 0;
14521080 var in_off = in_offset;
......@@ -1461,24 +1089,18 @@ pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u
14611089 return total_bytes_copied;
14621090}
14631091
1092/// Deprecated in favor of `Writer`.
14641093pub const WriteFileOptions = struct {
14651094 in_offset: u64 = 0,
1466
1467 /// `null` means the entire file. `0` means no bytes from the file.
1468 /// When this is `null`, trailers must be sent in a separate writev() call
1469 /// due to a flaw in the BSD sendfile API. Other operating systems, such as
1470 /// Linux, already do this anyway due to API limitations.
1471 /// If the size of the source file is known, passing the size here will save one syscall.
14721095 in_len: ?u64 = null,
1473
14741096 headers_and_trailers: []posix.iovec_const = &[0]posix.iovec_const{},
1475
1476 /// The trailer count is inferred from `headers_and_trailers.len - header_count`
14771097 header_count: usize = 0,
14781098};
14791099
1100/// Deprecated in favor of `Writer`.
14801101pub const WriteFileError = ReadError || error{EndOfStream} || WriteError;
14811102
1103/// Deprecated in favor of `Writer`.
14821104pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
14831105 return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {
14841106 error.Unseekable,
......@@ -1488,35 +1110,27 @@ pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFile
14881110 error.NetworkUnreachable,
14891111 error.NetworkSubsystemFailed,
14901112 => return self.writeFileAllUnseekable(in_file, args),
1491
14921113 else => |e| return e,
14931114 };
14941115}
14951116
1496/// Does not try seeking in either of the File parameters.
1497/// See `writeFileAll` as an alternative to calling this.
1117/// Deprecated in favor of `Writer`.
14981118pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
14991119 const headers = args.headers_and_trailers[0..args.header_count];
15001120 const trailers = args.headers_and_trailers[args.header_count..];
1501
15021121 try self.writevAll(headers);
1503
1504 try in_file.reader().skipBytes(args.in_offset, .{ .buf_size = 4096 });
1505
1122 try in_file.deprecatedReader().skipBytes(args.in_offset, .{ .buf_size = 4096 });
15061123 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
15071124 if (args.in_len) |len| {
1508 var stream = std.io.limitedReader(in_file.reader(), len);
1509 try fifo.pump(stream.reader(), self.writer());
1125 var stream = std.io.limitedReader(in_file.deprecatedReader(), len);
1126 try fifo.pump(stream.reader(), self.deprecatedWriter());
15101127 } else {
1511 try fifo.pump(in_file.reader(), self.writer());
1128 try fifo.pump(in_file.deprecatedReader(), self.deprecatedWriter());
15121129 }
1513
15141130 try self.writevAll(trailers);
15151131}
15161132
1517/// Low level function which can fail for OS-specific reasons.
1518/// See `writeFileAll` as an alternative to calling this.
1519/// TODO integrate with async I/O
1133/// Deprecated in favor of `Writer`.
15201134fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix.SendFileError!void {
15211135 const count = blk: {
15221136 if (args.in_len) |l| {
......@@ -1581,18 +1195,23 @@ fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix
15811195 }
15821196}
15831197
1584pub const Reader = io.GenericReader(File, ReadError, read);
1198/// Deprecated in favor of `Reader`.
1199pub const DeprecatedReader = io.GenericReader(File, ReadError, read);
15851200
1586pub fn reader(file: File) Reader {
1201/// Deprecated in favor of `Reader`.
1202pub fn deprecatedReader(file: File) DeprecatedReader {
15871203 return .{ .context = file };
15881204}
15891205
1590pub const Writer = io.GenericWriter(File, WriteError, write);
1206/// Deprecated in favor of `Writer`.
1207pub const DeprecatedWriter = io.GenericWriter(File, WriteError, write);
15911208
1592pub fn writer(file: File) Writer {
1209/// Deprecated in favor of `Writer`.
1210pub fn deprecatedWriter(file: File) DeprecatedWriter {
15931211 return .{ .context = file };
15941212}
15951213
1214/// Deprecated in favor of `Reader` and `Writer`.
15961215pub const SeekableStream = io.SeekableStream(
15971216 File,
15981217 SeekError,
......@@ -1603,10 +1222,715 @@ pub const SeekableStream = io.SeekableStream(
16031222 getEndPos,
16041223);
16051224
1225/// Deprecated in favor of `Reader` and `Writer`.
16061226pub fn seekableStream(file: File) SeekableStream {
16071227 return .{ .context = file };
16081228}
16091229
1230/// Memoizes key information about a file handle such as:
1231/// * The size from calling stat, or the error that occurred therein.
1232/// * The current seek position.
1233/// * The error that occurred when trying to seek.
1234/// * Whether reading should be done positionally or streaming.
1235/// * Whether reading should be done via fd-to-fd syscalls (e.g. `sendfile`)
1236/// versus plain variants (e.g. `read`).
1237///
1238/// Fulfills the `std.io.Reader` interface.
1239pub const Reader = struct {
1240 file: File,
1241 err: ?ReadError = null,
1242 mode: Reader.Mode = .positional,
1243 pos: u64 = 0,
1244 size: ?u64 = null,
1245 size_err: ?GetEndPosError = null,
1246 seek_err: ?Reader.SeekError = null,
1247 interface: std.io.Reader,
1248
1249 pub const SeekError = File.SeekError || error{
1250 /// Seeking fell back to reading, and reached the end before the requested seek position.
1251 /// `pos` remains at the end of the file.
1252 EndOfStream,
1253 /// Seeking fell back to reading, which failed.
1254 ReadFailed,
1255 };
1256
1257 pub const Mode = enum {
1258 streaming,
1259 positional,
1260 /// Avoid syscalls other than `read` and `readv`.
1261 streaming_reading,
1262 /// Avoid syscalls other than `pread` and `preadv`.
1263 positional_reading,
1264 /// Indicates reading cannot continue because of a seek failure.
1265 failure,
1266
1267 pub fn toStreaming(m: @This()) @This() {
1268 return switch (m) {
1269 .positional, .streaming => .streaming,
1270 .positional_reading, .streaming_reading => .streaming_reading,
1271 .failure => .failure,
1272 };
1273 }
1274
1275 pub fn toReading(m: @This()) @This() {
1276 return switch (m) {
1277 .positional, .positional_reading => .positional_reading,
1278 .streaming, .streaming_reading => .streaming_reading,
1279 .failure => .failure,
1280 };
1281 }
1282 };
1283
1284 pub fn initInterface(buffer: []u8) std.io.Reader {
1285 return .{
1286 .vtable = &.{
1287 .stream = Reader.stream,
1288 .discard = Reader.discard,
1289 },
1290 .buffer = buffer,
1291 .seek = 0,
1292 .end = 0,
1293 };
1294 }
1295
1296 pub fn init(file: File, buffer: []u8) Reader {
1297 return .{
1298 .file = file,
1299 .interface = initInterface(buffer),
1300 };
1301 }
1302
1303 pub fn initSize(file: File, buffer: []u8, size: ?u64) Reader {
1304 return .{
1305 .file = file,
1306 .interface = initInterface(buffer),
1307 .size = size,
1308 };
1309 }
1310
1311 pub fn initMode(file: File, buffer: []u8, init_mode: Reader.Mode) Reader {
1312 return .{
1313 .file = file,
1314 .interface = initInterface(buffer),
1315 .mode = init_mode,
1316 };
1317 }
1318
1319 pub fn getSize(r: *Reader) GetEndPosError!u64 {
1320 return r.size orelse {
1321 if (r.size_err) |err| return err;
1322 if (r.file.getEndPos()) |size| {
1323 r.size = size;
1324 return size;
1325 } else |err| {
1326 r.size_err = err;
1327 return err;
1328 }
1329 };
1330 }
1331
1332 pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
1333 switch (r.mode) {
1334 .positional, .positional_reading => {
1335 // TODO: make += operator allow any integer types
1336 r.pos = @intCast(@as(i64, @intCast(r.pos)) + offset);
1337 },
1338 .streaming, .streaming_reading => {
1339 const seek_err = r.seek_err orelse e: {
1340 if (posix.lseek_CUR(r.file.handle, offset)) |_| {
1341 // TODO: make += operator allow any integer types
1342 r.pos = @intCast(@as(i64, @intCast(r.pos)) + offset);
1343 return;
1344 } else |err| {
1345 r.seek_err = err;
1346 break :e err;
1347 }
1348 };
1349 var remaining = std.math.cast(u64, offset) orelse return seek_err;
1350 while (remaining > 0) {
1351 const n = discard(&r.interface, .limited(remaining)) catch |err| {
1352 r.seek_err = err;
1353 return err;
1354 };
1355 r.pos += n;
1356 remaining -= n;
1357 }
1358 },
1359 .failure => return r.seek_err.?,
1360 }
1361 }
1362
1363 pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
1364 switch (r.mode) {
1365 .positional, .positional_reading => {
1366 r.pos = offset;
1367 },
1368 .streaming, .streaming_reading => {
1369 if (offset >= r.pos) return Reader.seekBy(r, offset - r.pos);
1370 if (r.seek_err) |err| return err;
1371 posix.lseek_SET(r.file.handle, offset) catch |err| {
1372 r.seek_err = err;
1373 return err;
1374 };
1375 r.pos = offset;
1376 },
1377 .failure => return r.seek_err.?,
1378 }
1379 }
1380
1381 /// Number of slices to store on the stack, when trying to send as many byte
1382 /// vectors through the underlying read calls as possible.
1383 const max_buffers_len = 16;
1384
1385 fn stream(io_reader: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
1386 const r: *Reader = @fieldParentPtr("interface", io_reader);
1387 switch (r.mode) {
1388 .positional, .streaming => return w.sendFile(r, limit) catch |write_err| switch (write_err) {
1389 error.Unimplemented => {
1390 r.mode = r.mode.toReading();
1391 return 0;
1392 },
1393 else => |e| return e,
1394 },
1395 .positional_reading => {
1396 if (is_windows) {
1397 // Unfortunately, `ReadFileScatter` cannot be used since it
1398 // requires page alignment.
1399 const dest = limit.slice(try w.writableSliceGreedy(1));
1400 const n = try readPositional(r, dest);
1401 w.advance(n);
1402 return n;
1403 }
1404 var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
1405 const dest = try w.writableVectorPosix(&iovecs_buffer, limit);
1406 assert(dest[0].len > 0);
1407 const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
1408 error.Unseekable => {
1409 r.mode = r.mode.toStreaming();
1410 if (r.pos != 0) r.seekBy(@intCast(r.pos)) catch {
1411 r.mode = .failure;
1412 return error.ReadFailed;
1413 };
1414 return 0;
1415 },
1416 else => |e| {
1417 r.err = e;
1418 return error.ReadFailed;
1419 },
1420 };
1421 if (n == 0) {
1422 r.size = r.pos;
1423 return error.EndOfStream;
1424 }
1425 r.pos += n;
1426 return n;
1427 },
1428 .streaming_reading => {
1429 if (is_windows) {
1430 // Unfortunately, `ReadFileScatter` cannot be used since it
1431 // requires page alignment.
1432 const dest = limit.slice(try w.writableSliceGreedy(1));
1433 const n = try readStreaming(r, dest);
1434 w.advance(n);
1435 return n;
1436 }
1437 var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
1438 const dest = try w.writableVectorPosix(&iovecs_buffer, limit);
1439 assert(dest[0].len > 0);
1440 const n = posix.readv(r.file.handle, dest) catch |err| {
1441 r.err = err;
1442 return error.ReadFailed;
1443 };
1444 if (n == 0) {
1445 r.size = r.pos;
1446 return error.EndOfStream;
1447 }
1448 r.pos += n;
1449 return n;
1450 },
1451 .failure => return error.ReadFailed,
1452 }
1453 }
1454
1455 fn discard(io_reader: *std.io.Reader, limit: std.io.Limit) std.io.Reader.Error!usize {
1456 const r: *Reader = @fieldParentPtr("interface", io_reader);
1457 const file = r.file;
1458 const pos = r.pos;
1459 switch (r.mode) {
1460 .positional, .positional_reading => {
1461 const size = r.size orelse {
1462 if (file.getEndPos()) |size| {
1463 r.size = size;
1464 } else |err| {
1465 r.size_err = err;
1466 r.mode = r.mode.toStreaming();
1467 }
1468 return 0;
1469 };
1470 const delta = @min(@intFromEnum(limit), size - pos);
1471 r.pos = pos + delta;
1472 return delta;
1473 },
1474 .streaming, .streaming_reading => {
1475 // Unfortunately we can't seek forward without knowing the
1476 // size because the seek syscalls provided to us will not
1477 // return the true end position if a seek would exceed the
1478 // end.
1479 fallback: {
1480 if (r.size_err == null and r.seek_err == null) break :fallback;
1481 var trash_buffer: [128]u8 = undefined;
1482 const trash = &trash_buffer;
1483 if (is_windows) {
1484 const n = windows.ReadFile(file.handle, trash, null) catch |err| {
1485 r.err = err;
1486 return error.ReadFailed;
1487 };
1488 if (n == 0) {
1489 r.size = pos;
1490 return error.EndOfStream;
1491 }
1492 r.pos = pos + n;
1493 return n;
1494 }
1495 var iovecs: [max_buffers_len]std.posix.iovec = undefined;
1496 var iovecs_i: usize = 0;
1497 var remaining = @intFromEnum(limit);
1498 while (remaining > 0 and iovecs_i < iovecs.len) {
1499 iovecs[iovecs_i] = .{ .base = trash, .len = @min(trash.len, remaining) };
1500 remaining -= iovecs[iovecs_i].len;
1501 iovecs_i += 1;
1502 }
1503 const n = posix.readv(file.handle, iovecs[0..iovecs_i]) catch |err| {
1504 r.err = err;
1505 return error.ReadFailed;
1506 };
1507 if (n == 0) {
1508 r.size = pos;
1509 return error.EndOfStream;
1510 }
1511 r.pos = pos + n;
1512 return n;
1513 }
1514 const size = r.size orelse {
1515 if (file.getEndPos()) |size| {
1516 r.size = size;
1517 } else |err| {
1518 r.size_err = err;
1519 }
1520 return 0;
1521 };
1522 const n = @min(size - pos, std.math.maxInt(i64), @intFromEnum(limit));
1523 file.seekBy(n) catch |err| {
1524 r.seek_err = err;
1525 return 0;
1526 };
1527 r.pos = pos + n;
1528 return n;
1529 },
1530 .failure => return error.ReadFailed,
1531 }
1532 }
1533
1534 pub fn readPositional(r: *Reader, dest: []u8) std.io.Reader.Error!usize {
1535 const n = r.file.pread(dest, r.pos) catch |err| switch (err) {
1536 error.Unseekable => {
1537 r.mode = r.mode.toStreaming();
1538 if (r.pos != 0) r.seekBy(@intCast(r.pos)) catch {
1539 r.mode = .failure;
1540 return error.ReadFailed;
1541 };
1542 return 0;
1543 },
1544 else => |e| {
1545 r.err = e;
1546 return error.ReadFailed;
1547 },
1548 };
1549 if (n == 0) {
1550 r.size = r.pos;
1551 return error.EndOfStream;
1552 }
1553 r.pos += n;
1554 return n;
1555 }
1556
1557 pub fn readStreaming(r: *Reader, dest: []u8) std.io.Reader.Error!usize {
1558 const n = r.file.read(dest) catch |err| {
1559 r.err = err;
1560 return error.ReadFailed;
1561 };
1562 if (n == 0) {
1563 r.size = r.pos;
1564 return error.EndOfStream;
1565 }
1566 r.pos += n;
1567 return n;
1568 }
1569
1570 pub fn read(r: *Reader, dest: []u8) std.io.Reader.Error!usize {
1571 switch (r.mode) {
1572 .positional, .positional_reading => return readPositional(r, dest),
1573 .streaming, .streaming_reading => return readStreaming(r, dest),
1574 .failure => return error.ReadFailed,
1575 }
1576 }
1577
1578 pub fn atEnd(r: *Reader) bool {
1579 // Even if stat fails, size is set when end is encountered.
1580 const size = r.size orelse return false;
1581 return size - r.pos == 0;
1582 }
1583};
1584
1585pub const Writer = struct {
1586 file: File,
1587 err: ?WriteError = null,
1588 mode: Writer.Mode = .positional,
1589 pos: u64 = 0,
1590 sendfile_err: ?SendfileError = null,
1591 copy_file_range_err: ?CopyFileRangeError = null,
1592 fcopyfile_err: ?FcopyfileError = null,
1593 seek_err: ?SeekError = null,
1594 interface: std.io.Writer,
1595
1596 pub const Mode = Reader.Mode;
1597
1598 pub const SendfileError = error{
1599 UnsupportedOperation,
1600 SystemResources,
1601 InputOutput,
1602 BrokenPipe,
1603 WouldBlock,
1604 Unexpected,
1605 };
1606
1607 pub const CopyFileRangeError = std.os.freebsd.CopyFileRangeError || std.os.linux.wrapped.CopyFileRangeError;
1608
1609 pub const FcopyfileError = error{
1610 OperationNotSupported,
1611 OutOfMemory,
1612 Unexpected,
1613 };
1614
1615 /// Number of slices to store on the stack, when trying to send as many byte
1616 /// vectors through the underlying write calls as possible.
1617 const max_buffers_len = 16;
1618
1619 pub fn init(file: File, buffer: []u8) Writer {
1620 return initMode(file, buffer, .positional);
1621 }
1622
1623 pub fn initMode(file: File, buffer: []u8, init_mode: Writer.Mode) Writer {
1624 return .{
1625 .file = file,
1626 .interface = initInterface(buffer),
1627 .mode = init_mode,
1628 };
1629 }
1630
1631 pub fn initInterface(buffer: []u8) std.io.Writer {
1632 return .{
1633 .vtable = &.{
1634 .drain = drain,
1635 .sendFile = sendFile,
1636 },
1637 .buffer = buffer,
1638 };
1639 }
1640
1641 pub fn moveToReader(w: *Writer) Reader {
1642 defer w.* = undefined;
1643 return .{
1644 .file = w.file,
1645 .mode = w.mode,
1646 .pos = w.pos,
1647 .seek_err = w.seek_err,
1648 };
1649 }
1650
1651 pub fn drain(io_writer: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
1652 const w: *Writer = @fieldParentPtr("interface", io_writer);
1653 const handle = w.file.handle;
1654 const buffered = io_writer.buffered();
1655 var splat_buffer: [256]u8 = undefined;
1656 if (is_windows) {
1657 var i: usize = 0;
1658 while (i < buffered.len) {
1659 const n = windows.WriteFile(handle, buffered[i..], null) catch |err| {
1660 w.err = err;
1661 w.pos += i;
1662 _ = io_writer.consume(i);
1663 return error.WriteFailed;
1664 };
1665 i += n;
1666 if (data.len > 0 and buffered.len - i < n) {
1667 w.pos += i;
1668 return io_writer.consume(i);
1669 }
1670 }
1671 if (i != 0 or data.len == 0 or (data.len == 1 and splat == 0)) {
1672 w.pos += i;
1673 return io_writer.consume(i);
1674 }
1675 const n = windows.WriteFile(handle, data[0], null) catch |err| {
1676 w.err = err;
1677 return 0;
1678 };
1679 w.pos += n;
1680 return n;
1681 }
1682 if (data.len == 0) {
1683 var i: usize = 0;
1684 while (i < buffered.len) {
1685 i += std.posix.write(handle, buffered) catch |err| {
1686 w.err = err;
1687 w.pos += i;
1688 _ = io_writer.consume(i);
1689 return error.WriteFailed;
1690 };
1691 }
1692 w.pos += i;
1693 return io_writer.consumeAll();
1694 }
1695 var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
1696 var len: usize = 0;
1697 if (buffered.len > 0) {
1698 iovecs[len] = .{ .base = buffered.ptr, .len = buffered.len };
1699 len += 1;
1700 }
1701 for (data) |d| {
1702 if (d.len == 0) continue;
1703 if (iovecs.len - len == 0) break;
1704 iovecs[len] = .{ .base = d.ptr, .len = d.len };
1705 len += 1;
1706 }
1707 switch (splat) {
1708 0 => if (data[data.len - 1].len != 0) {
1709 len -= 1;
1710 },
1711 1 => {},
1712 else => switch (data[data.len - 1].len) {
1713 0 => {},
1714 1 => {
1715 const memset_len = @min(splat_buffer.len, splat);
1716 const buf = splat_buffer[0..memset_len];
1717 @memset(buf, data[data.len - 1][0]);
1718 iovecs[len - 1] = .{ .base = buf.ptr, .len = buf.len };
1719 var remaining_splat = splat - buf.len;
1720 while (remaining_splat > splat_buffer.len and len < iovecs.len) {
1721 iovecs[len] = .{ .base = &splat_buffer, .len = splat_buffer.len };
1722 remaining_splat -= splat_buffer.len;
1723 len += 1;
1724 }
1725 if (remaining_splat > 0 and len < iovecs.len) {
1726 iovecs[len] = .{ .base = &splat_buffer, .len = remaining_splat };
1727 len += 1;
1728 }
1729 return std.posix.writev(handle, iovecs[0..len]) catch |err| {
1730 w.err = err;
1731 return error.WriteFailed;
1732 };
1733 },
1734 else => for (0..splat - 1) |_| {
1735 if (iovecs.len - len == 0) break;
1736 iovecs[len] = .{ .base = data[data.len - 1].ptr, .len = data[data.len - 1].len };
1737 len += 1;
1738 },
1739 },
1740 }
1741 const n = std.posix.writev(handle, iovecs[0..len]) catch |err| {
1742 w.err = err;
1743 return error.WriteFailed;
1744 };
1745 w.pos += n;
1746 return io_writer.consume(n);
1747 }
1748
1749 pub fn sendFile(
1750 io_writer: *std.io.Writer,
1751 file_reader: *Reader,
1752 limit: std.io.Limit,
1753 ) std.io.Writer.FileError!usize {
1754 const w: *Writer = @fieldParentPtr("interface", io_writer);
1755 const out_fd = w.file.handle;
1756 const in_fd = file_reader.file.handle;
1757 // TODO try using copy_file_range on FreeBSD
1758 // TODO try using sendfile on macOS
1759 // TODO try using sendfile on FreeBSD
1760 if (native_os == .linux and w.mode == .streaming) sf: {
1761 // Try using sendfile on Linux.
1762 if (w.sendfile_err != null) break :sf;
1763 // Linux sendfile does not support headers.
1764 const buffered = limit.slice(file_reader.interface.buffer);
1765 if (io_writer.end != 0 or buffered.len != 0) return drain(io_writer, &.{buffered}, 1);
1766 const max_count = 0x7ffff000; // Avoid EINVAL.
1767 var off: std.os.linux.off_t = undefined;
1768 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {
1769 .positional => o: {
1770 const size = file_reader.size orelse {
1771 if (file_reader.file.getEndPos()) |size| {
1772 file_reader.size = size;
1773 } else |err| {
1774 file_reader.size_err = err;
1775 file_reader.mode = .streaming;
1776 }
1777 return 0;
1778 };
1779 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed;
1780 break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) };
1781 },
1782 .streaming => .{ null, limit.minInt(max_count) },
1783 .streaming_reading, .positional_reading => break :sf,
1784 .failure => return error.ReadFailed,
1785 };
1786 const n = std.os.linux.wrapped.sendfile(out_fd, in_fd, off_ptr, count) catch |err| switch (err) {
1787 error.Unseekable => {
1788 file_reader.mode = file_reader.mode.toStreaming();
1789 if (file_reader.pos != 0) file_reader.seekBy(@intCast(file_reader.pos)) catch {
1790 file_reader.mode = .failure;
1791 return error.ReadFailed;
1792 };
1793 return 0;
1794 },
1795 else => |e| {
1796 w.sendfile_err = e;
1797 return 0;
1798 },
1799 };
1800 if (n == 0) {
1801 file_reader.size = file_reader.pos;
1802 return error.EndOfStream;
1803 }
1804 file_reader.pos += n;
1805 w.pos += n;
1806 return n;
1807 }
1808 const copy_file_range_fn = switch (native_os) {
1809 .freebsd => std.os.freebsd.copy_file_range,
1810 .linux => if (std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })) std.os.linux.wrapped.copy_file_range else null,
1811 else => null,
1812 };
1813 if (copy_file_range_fn) |copy_file_range| cfr: {
1814 if (w.copy_file_range_err != null) break :cfr;
1815 const buffered = limit.slice(file_reader.interface.buffer);
1816 if (io_writer.end != 0 or buffered.len != 0) return drain(io_writer, &.{buffered}, 1);
1817 var off_in: i64 = undefined;
1818 var off_out: i64 = undefined;
1819 const off_in_ptr: ?*i64 = switch (file_reader.mode) {
1820 .positional_reading, .streaming_reading => return error.Unimplemented,
1821 .positional => p: {
1822 off_in = file_reader.pos;
1823 break :p &off_in;
1824 },
1825 .streaming => null,
1826 .failure => return error.WriteFailed,
1827 };
1828 const off_out_ptr: ?*i64 = switch (w.mode) {
1829 .positional_reading, .streaming_reading => return error.Unimplemented,
1830 .positional => p: {
1831 off_out = w.pos;
1832 break :p &off_out;
1833 },
1834 .streaming => null,
1835 .failure => return error.WriteFailed,
1836 };
1837 const n = copy_file_range(in_fd, off_in_ptr, out_fd, off_out_ptr, @intFromEnum(limit), 0) catch |err| {
1838 w.copy_file_range_err = err;
1839 return 0;
1840 };
1841 if (n == 0) {
1842 file_reader.size = file_reader.pos;
1843 return error.EndOfStream;
1844 }
1845 file_reader.pos += n;
1846 w.pos += n;
1847 return n;
1848 }
1849
1850 if (builtin.os.tag.isDarwin()) fcf: {
1851 if (w.fcopyfile_err != null) break :fcf;
1852 if (file_reader.pos != 0) break :fcf;
1853 if (w.pos != 0) break :fcf;
1854 if (limit != .unlimited) break :fcf;
1855 const rc = std.c.fcopyfile(in_fd, out_fd, null, .{ .DATA = true });
1856 switch (posix.errno(rc)) {
1857 .SUCCESS => {},
1858 .INVAL => if (builtin.mode == .Debug) @panic("invalid API usage") else {
1859 w.fcopyfile_err = error.Unexpected;
1860 return 0;
1861 },
1862 .NOMEM => {
1863 w.fcopyfile_err = error.OutOfMemory;
1864 return 0;
1865 },
1866 .OPNOTSUPP => {
1867 w.fcopyfile_err = error.OperationNotSupported;
1868 return 0;
1869 },
1870 else => |err| {
1871 w.fcopyfile_err = posix.unexpectedErrno(err);
1872 return 0;
1873 },
1874 }
1875 const n = if (file_reader.size) |size| size else @panic("TODO figure out how much copied");
1876 file_reader.pos = n;
1877 w.pos = n;
1878 return n;
1879 }
1880
1881 return error.Unimplemented;
1882 }
1883
1884 pub fn seekTo(w: *Writer, offset: u64) SeekError!void {
1885 if (w.seek_err) |err| return err;
1886 switch (w.mode) {
1887 .positional, .positional_reading => {
1888 w.pos = offset;
1889 },
1890 .streaming, .streaming_reading => {
1891 posix.lseek_SET(w.file.handle, offset) catch |err| {
1892 w.seek_err = err;
1893 return err;
1894 };
1895 },
1896 }
1897 }
1898};
1899
1900/// Defaults to positional reading; falls back to streaming.
1901///
1902/// Positional is more threadsafe, since the global seek position is not
1903/// affected.
1904pub fn reader(file: File, buffer: []u8) Reader {
1905 return .init(file, buffer);
1906}
1907
1908/// Positional is more threadsafe, since the global seek position is not
1909/// affected, but when such syscalls are not available, preemptively choosing
1910/// `Reader.Mode.streaming` will skip a failed syscall.
1911pub fn readerStreaming(file: File) Reader {
1912 return .{
1913 .file = file,
1914 .mode = .streaming,
1915 .seek_err = error.Unseekable,
1916 };
1917}
1918
1919/// Defaults to positional reading; falls back to streaming.
1920///
1921/// Positional is more threadsafe, since the global seek position is not
1922/// affected.
1923pub fn writer(file: File, buffer: []u8) Writer {
1924 return .init(file, buffer);
1925}
1926
1927/// Positional is more threadsafe, since the global seek position is not
1928/// affected, but when such syscalls are not available, preemptively choosing
1929/// `Writer.Mode.streaming` will skip a failed syscall.
1930pub fn writerStreaming(file: File, buffer: []u8) Writer {
1931 return .initMode(file, buffer, .streaming);
1932}
1933
16101934const range_off: windows.LARGE_INTEGER = 0;
16111935const range_len: windows.LARGE_INTEGER = 1;
16121936
......@@ -1769,18 +2093,3 @@ pub fn downgradeLock(file: File) LockError!void {
17692093 };
17702094 }
17712095}
1772
1773const File = @This();
1774const std = @import("../std.zig");
1775const builtin = @import("builtin");
1776const Allocator = std.mem.Allocator;
1777const posix = std.posix;
1778const io = std.io;
1779const math = std.math;
1780const assert = std.debug.assert;
1781const linux = std.os.linux;
1782const windows = std.os.windows;
1783const Os = std.builtin.Os;
1784const maxInt = std.math.maxInt;
1785const is_windows = builtin.os.tag == .windows;
1786const Alignment = std.mem.Alignment;
lib/std/fs/path.zig+2-5
......@@ -146,14 +146,11 @@ pub fn joinZ(allocator: Allocator, paths: []const []const u8) ![:0]u8 {
146146 return out[0 .. out.len - 1 :0];
147147}
148148
149pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter(formatJoin) {
149pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter([]const []const u8, formatJoin) {
150150 return .{ .data = paths };
151151}
152152
153fn formatJoin(paths: []const []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void {
154 _ = fmt;
155 _ = options;
156
153fn formatJoin(paths: []const []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
157154 const first_path_idx = for (paths, 0..) |p, idx| {
158155 if (p.len != 0) break idx;
159156 } else return;
lib/std/fs/test.zig+2-109
......@@ -1798,11 +1798,11 @@ test "walker" {
17981798 var num_walked: usize = 0;
17991799 while (try walker.next()) |entry| {
18001800 testing.expect(expected_basenames.has(entry.basename)) catch |err| {
1801 std.debug.print("found unexpected basename: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.basename)});
1801 std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)});
18021802 return err;
18031803 };
18041804 testing.expect(expected_paths.has(entry.path)) catch |err| {
1805 std.debug.print("found unexpected path: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.path)});
1805 std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});
18061806 return err;
18071807 };
18081808 // make sure that the entry.dir is the containing dir
......@@ -1953,113 +1953,6 @@ test "chown" {
19531953 try dir.chown(null, null);
19541954}
19551955
1956test "File.Metadata" {
1957 var tmp = tmpDir(.{});
1958 defer tmp.cleanup();
1959
1960 const file = try tmp.dir.createFile("test_file", .{ .read = true });
1961 defer file.close();
1962
1963 const metadata = try file.metadata();
1964 try testing.expectEqual(File.Kind.file, metadata.kind());
1965 try testing.expectEqual(@as(u64, 0), metadata.size());
1966 _ = metadata.accessed();
1967 _ = metadata.modified();
1968 _ = metadata.created();
1969}
1970
1971test "File.Permissions" {
1972 if (native_os == .wasi)
1973 return error.SkipZigTest;
1974
1975 var tmp = tmpDir(.{});
1976 defer tmp.cleanup();
1977
1978 const file = try tmp.dir.createFile("test_file", .{ .read = true });
1979 defer file.close();
1980
1981 const metadata = try file.metadata();
1982 var permissions = metadata.permissions();
1983
1984 try testing.expect(!permissions.readOnly());
1985 permissions.setReadOnly(true);
1986 try testing.expect(permissions.readOnly());
1987
1988 try file.setPermissions(permissions);
1989 const new_permissions = (try file.metadata()).permissions();
1990 try testing.expect(new_permissions.readOnly());
1991
1992 // Must be set to non-read-only to delete
1993 permissions.setReadOnly(false);
1994 try file.setPermissions(permissions);
1995}
1996
1997test "File.PermissionsUnix" {
1998 if (native_os == .windows or native_os == .wasi)
1999 return error.SkipZigTest;
2000
2001 var tmp = tmpDir(.{});
2002 defer tmp.cleanup();
2003
2004 const file = try tmp.dir.createFile("test_file", .{ .mode = 0o666, .read = true });
2005 defer file.close();
2006
2007 const metadata = try file.metadata();
2008 var permissions = metadata.permissions();
2009
2010 permissions.setReadOnly(true);
2011 try testing.expect(permissions.readOnly());
2012 try testing.expect(!permissions.inner.unixHas(.user, .write));
2013 permissions.inner.unixSet(.user, .{ .write = true });
2014 try testing.expect(!permissions.readOnly());
2015 try testing.expect(permissions.inner.unixHas(.user, .write));
2016 try testing.expect(permissions.inner.mode & 0o400 != 0);
2017
2018 permissions.setReadOnly(true);
2019 try file.setPermissions(permissions);
2020 permissions = (try file.metadata()).permissions();
2021 try testing.expect(permissions.readOnly());
2022
2023 // Must be set to non-read-only to delete
2024 permissions.setReadOnly(false);
2025 try file.setPermissions(permissions);
2026
2027 const permissions_unix = File.PermissionsUnix.unixNew(0o754);
2028 try testing.expect(permissions_unix.unixHas(.user, .execute));
2029 try testing.expect(!permissions_unix.unixHas(.other, .execute));
2030}
2031
2032test "delete a read-only file on windows" {
2033 if (native_os != .windows)
2034 return error.SkipZigTest;
2035
2036 var tmp = testing.tmpDir(.{});
2037 defer tmp.cleanup();
2038
2039 const file = try tmp.dir.createFile("test_file", .{ .read = true });
2040 defer file.close();
2041 // Create a file and make it read-only
2042 const metadata = try file.metadata();
2043 var permissions = metadata.permissions();
2044 permissions.setReadOnly(true);
2045 try file.setPermissions(permissions);
2046
2047 // If the OS and filesystem support it, POSIX_SEMANTICS and IGNORE_READONLY_ATTRIBUTE
2048 // is used meaning that the deletion of a read-only file will succeed.
2049 // Otherwise, this delete will fail and the read-only flag must be unset before it's
2050 // able to be deleted.
2051 const delete_result = tmp.dir.deleteFile("test_file");
2052 if (delete_result) {
2053 try testing.expectError(error.FileNotFound, tmp.dir.deleteFile("test_file"));
2054 } else |err| {
2055 try testing.expectEqual(@as(anyerror, error.AccessDenied), err);
2056 // Now make the file not read-only
2057 permissions.setReadOnly(false);
2058 try file.setPermissions(permissions);
2059 try tmp.dir.deleteFile("test_file");
2060 }
2061}
2062
20631956test "delete a setAsCwd directory on Windows" {
20641957 if (native_os != .windows) return error.SkipZigTest;
20651958
lib/std/hash/benchmark.zig+1-1
......@@ -346,7 +346,7 @@ fn mode(comptime x: comptime_int) comptime_int {
346346}
347347
348348pub fn main() !void {
349 const stdout = std.fs.File.stdout().writer();
349 const stdout = std.fs.File.stdout().deprecatedWriter();
350350
351351 var buffer: [1024]u8 = undefined;
352352 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
lib/std/heap/debug_allocator.zig+10-10
......@@ -436,7 +436,7 @@ pub fn DebugAllocator(comptime config: Config) type {
436436 const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);
437437 const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
438438 const addr = page_addr + slot_index * size_class;
439 log.err("memory address 0x{x} leaked: {}", .{ addr, stack_trace });
439 log.err("memory address 0x{x} leaked: {f}", .{ addr, stack_trace });
440440 leaks = true;
441441 }
442442 }
......@@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type {
463463 while (it.next()) |large_alloc| {
464464 if (config.retain_metadata and large_alloc.freed) continue;
465465 const stack_trace = large_alloc.getStackTrace(.alloc);
466 log.err("memory address 0x{x} leaked: {}", .{
466 log.err("memory address 0x{x} leaked: {f}", .{
467467 @intFromPtr(large_alloc.bytes.ptr), stack_trace,
468468 });
469469 leaks = true;
......@@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type {
522522 .index = 0,
523523 };
524524 std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);
525 log.err("Double free detected. Allocation: {} First free: {} Second free: {}", .{
525 log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{
526526 alloc_stack_trace, free_stack_trace, second_free_stack_trace,
527527 });
528528 }
......@@ -568,7 +568,7 @@ pub fn DebugAllocator(comptime config: Config) type {
568568 .index = 0,
569569 };
570570 std.debug.captureStackTrace(ret_addr, &free_stack_trace);
571 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
571 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
572572 entry.value_ptr.bytes.len,
573573 old_mem.len,
574574 entry.value_ptr.getStackTrace(.alloc),
......@@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type {
678678 .index = 0,
679679 };
680680 std.debug.captureStackTrace(ret_addr, &free_stack_trace);
681 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
681 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
682682 entry.value_ptr.bytes.len,
683683 old_mem.len,
684684 entry.value_ptr.getStackTrace(.alloc),
......@@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type {
907907 };
908908 std.debug.captureStackTrace(return_address, &free_stack_trace);
909909 if (old_memory.len != requested_size) {
910 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
910 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
911911 requested_size,
912912 old_memory.len,
913913 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
......@@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type {
915915 });
916916 }
917917 if (alignment != slot_alignment) {
918 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {} Free: {}", .{
918 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
919919 slot_alignment.toByteUnits(),
920920 alignment.toByteUnits(),
921921 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
......@@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type {
10061006 };
10071007 std.debug.captureStackTrace(return_address, &free_stack_trace);
10081008 if (memory.len != requested_size) {
1009 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
1009 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
10101010 requested_size,
10111011 memory.len,
10121012 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
......@@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type {
10141014 });
10151015 }
10161016 if (alignment != slot_alignment) {
1017 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {} Free: {}", .{
1017 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
10181018 slot_alignment.toByteUnits(),
10191019 alignment.toByteUnits(),
10201020 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
......@@ -1054,7 +1054,7 @@ const TraceKind = enum {
10541054 free,
10551055};
10561056
1057const test_config = Config{};
1057const test_config: Config = .{};
10581058
10591059test "small allocations - free in same order" {
10601060 var gpa = DebugAllocator(test_config){};
lib/std/http.zig+13-8
......@@ -1,3 +1,7 @@
1const builtin = @import("builtin");
2const std = @import("std.zig");
3const assert = std.debug.assert;
4
15pub const Client = @import("http/Client.zig");
26pub const Server = @import("http/Server.zig");
37pub const protocol = @import("http/protocol.zig");
......@@ -38,8 +42,9 @@ pub const Method = enum(u64) {
3842 return x;
3943 }
4044
41 pub fn write(self: Method, w: anytype) !void {
42 const bytes = std.mem.asBytes(&@intFromEnum(self));
45 pub fn format(self: Method, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
46 comptime assert(f.len == 0);
47 const bytes: []const u8 = @ptrCast(&@intFromEnum(self));
4348 const str = std.mem.sliceTo(bytes, 0);
4449 try w.writeAll(str);
4550 }
......@@ -77,7 +82,9 @@ pub const Method = enum(u64) {
7782 };
7883 }
7984
80 /// An HTTP method is idempotent if an identical request can be made once or several times in a row with the same effect while leaving the server in the same state.
85 /// An HTTP method is idempotent if an identical request can be made once
86 /// or several times in a row with the same effect while leaving the server
87 /// in the same state.
8188 ///
8289 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
8390 ///
......@@ -90,7 +97,8 @@ pub const Method = enum(u64) {
9097 };
9198 }
9299
93 /// A cacheable response is an HTTP response that can be cached, that is stored to be retrieved and used later, saving a new request to the server.
100 /// A cacheable response can be stored to be retrieved and used later,
101 /// saving a new request to the server.
94102 ///
95103 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable
96104 ///
......@@ -282,10 +290,10 @@ pub const Status = enum(u10) {
282290 }
283291};
284292
293/// compression is intentionally omitted here since it is handled in `ContentEncoding`.
285294pub const TransferEncoding = enum {
286295 chunked,
287296 none,
288 // compression is intentionally omitted here, as std.http.Client stores it as content-encoding
289297};
290298
291299pub const ContentEncoding = enum {
......@@ -308,9 +316,6 @@ pub const Header = struct {
308316 value: []const u8,
309317};
310318
311const builtin = @import("builtin");
312const std = @import("std.zig");
313
314319test {
315320 if (builtin.os.tag != .wasi) {
316321 _ = Client;
lib/std/http/Client.zig+17-10
......@@ -823,21 +823,28 @@ pub const Request = struct {
823823 return error.UnsupportedTransferEncoding;
824824
825825 const connection = req.connection.?;
826 const w = connection.writer();
826 var connection_writer_adapter = connection.writer().adaptToNewApi();
827 const w = &connection_writer_adapter.new_interface;
828 sendAdapted(req, connection, w) catch |err| switch (err) {
829 error.WriteFailed => return connection_writer_adapter.err.?,
830 else => |e| return e,
831 };
832 }
827833
828 try req.method.write(w);
834 fn sendAdapted(req: *Request, connection: *Connection, w: *std.io.Writer) !void {
835 try req.method.format(w, "");
829836 try w.writeByte(' ');
830837
831838 if (req.method == .CONNECT) {
832 try req.uri.writeToStream(.{ .authority = true }, w);
839 try req.uri.writeToStream(w, .{ .authority = true });
833840 } else {
834 try req.uri.writeToStream(.{
841 try req.uri.writeToStream(w, .{
835842 .scheme = connection.proxied,
836843 .authentication = connection.proxied,
837844 .authority = connection.proxied,
838845 .path = true,
839846 .query = true,
840 }, w);
847 });
841848 }
842849 try w.writeByte(' ');
843850 try w.writeAll(@tagName(req.version));
......@@ -845,7 +852,7 @@ pub const Request = struct {
845852
846853 if (try emitOverridableHeader("host: ", req.headers.host, w)) {
847854 try w.writeAll("host: ");
848 try req.uri.writeToStream(.{ .authority = true }, w);
855 try req.uri.writeToStream(w, .{ .authority = true });
849856 try w.writeAll("\r\n");
850857 }
851858
......@@ -1284,10 +1291,10 @@ pub const basic_authorization = struct {
12841291
12851292 pub fn valueLengthFromUri(uri: Uri) usize {
12861293 var stream = std.io.countingWriter(std.io.null_writer);
1287 try stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty});
1294 try stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty});
12881295 const user_len = stream.bytes_written;
12891296 stream.bytes_written = 0;
1290 try stream.writer().print("{password}", .{uri.password orelse Uri.Component.empty});
1297 try stream.writer().print("{fpassword}", .{uri.password orelse Uri.Component.empty});
12911298 const password_len = stream.bytes_written;
12921299 return valueLength(@intCast(user_len), @intCast(password_len));
12931300 }
......@@ -1295,10 +1302,10 @@ pub const basic_authorization = struct {
12951302 pub fn value(uri: Uri, out: []u8) []u8 {
12961303 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
12971304 var stream = std.io.fixedBufferStream(&buf);
1298 stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch
1305 stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty}) catch
12991306 unreachable;
13001307 assert(stream.pos <= max_user_len);
1301 stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch
1308 stream.writer().print(":{fpassword}", .{uri.password orelse Uri.Component.empty}) catch
13021309 unreachable;
13031310
13041311 @memcpy(out[0..prefix.len], prefix);
lib/std/http/test.zig+2-4
......@@ -385,10 +385,8 @@ test "general client/server API coverage" {
385385 fn handleRequest(request: *http.Server.Request, listen_port: u16) !void {
386386 const log = std.log.scoped(.server);
387387
388 log.info("{} {s} {s}", .{
389 request.head.method,
390 @tagName(request.head.version),
391 request.head.target,
388 log.info("{f} {s} {s}", .{
389 request.head.method, @tagName(request.head.version), request.head.target,
392390 });
393391
394392 const gpa = std.testing.allocator;
lib/std/io.zig+27-1
......@@ -364,6 +364,32 @@ pub fn GenericWriter(
364364 const ptr: *const Context = @alignCast(@ptrCast(context));
365365 return writeFn(ptr.*, bytes);
366366 }
367
368 /// Helper for bridging to the new `Writer` API while upgrading.
369 pub fn adaptToNewApi(self: *const Self) Adapter {
370 return .{
371 .derp_writer = self.*,
372 .new_interface = .{
373 .buffer = &.{},
374 .vtable = &.{ .drain = Adapter.drain },
375 },
376 };
377 }
378
379 pub const Adapter = struct {
380 derp_writer: Self,
381 new_interface: Writer,
382 err: ?Error = null,
383
384 fn drain(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
385 _ = splat;
386 const a: *@This() = @fieldParentPtr("new_interface", w);
387 return a.derp_writer.write(data[0]) catch |err| {
388 a.err = err;
389 return error.WriteFailed;
390 };
391 }
392 };
367393 };
368394}
369395
......@@ -419,7 +445,7 @@ pub const tty = @import("io/tty.zig");
419445/// A Writer that doesn't write to anything.
420446pub const null_writer: NullWriter = .{ .context = {} };
421447
422pub const NullWriter = Writer(void, error{}, dummyWrite);
448pub const NullWriter = GenericWriter(void, error{}, dummyWrite);
423449fn dummyWrite(context: void, data: []const u8) error{}!usize {
424450 _ = context;
425451 return data.len;
lib/std/io/DeprecatedWriter.zig+27-1
......@@ -21,7 +21,7 @@ pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {
2121}
2222
2323pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {
24 return std.fmt.format(self, format, args);
24 return std.fmt.deprecatedFormat(self, format, args);
2525}
2626
2727pub fn writeByte(self: Self, byte: u8) anyerror!void {
......@@ -81,3 +81,29 @@ pub fn writeFile(self: Self, file: std.fs.File) anyerror!void {
8181 if (n < buf.len) return;
8282 }
8383}
84
85/// Helper for bridging to the new `Writer` API while upgrading.
86pub fn adaptToNewApi(self: *const Self) Adapter {
87 return .{
88 .derp_writer = self.*,
89 .new_interface = .{
90 .buffer = &.{},
91 .vtable = &.{ .drain = Adapter.drain },
92 },
93 };
94}
95
96pub const Adapter = struct {
97 derp_writer: Self,
98 new_interface: std.io.Writer,
99 err: ?Error = null,
100
101 fn drain(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
102 _ = splat;
103 const a: *@This() = @fieldParentPtr("new_interface", w);
104 return a.derp_writer.write(data[0]) catch |err| {
105 a.err = err;
106 return error.WriteFailed;
107 };
108 }
109};
lib/std/io/Reader.zig+30-18
......@@ -26,7 +26,8 @@ pub const VTable = struct {
2626 /// Returns the number of bytes written, which will be at minimum `0` and
2727 /// at most `limit`. The number returned, including zero, does not indicate
2828 /// end of stream. `limit` is guaranteed to be at least as large as the
29 /// buffer capacity of `w`.
29 /// buffer capacity of `w`, a value whose minimum size is determined by the
30 /// stream implementation.
3031 ///
3132 /// The reader's internal logical seek position moves forward in accordance
3233 /// with the number of bytes returned from this function.
......@@ -1243,10 +1244,10 @@ test peekArray {
12431244
12441245test discardAll {
12451246 var r: Reader = .fixed("foobar");
1246 try r.discard(3);
1247 try r.discardAll(3);
12471248 try testing.expectEqualStrings("bar", try r.take(3));
1248 try r.discard(0);
1249 try testing.expectError(error.EndOfStream, r.discard(1));
1249 try r.discardAll(0);
1250 try testing.expectError(error.EndOfStream, r.discardAll(1));
12501251}
12511252
12521253test discardRemaining {
......@@ -1355,9 +1356,11 @@ test readVec {
13551356
13561357test "expected error.EndOfStream" {
13571358 // Unit test inspired by https://github.com/ziglang/zig/issues/17733
1358 var r: std.io.Reader = .fixed("");
1359 try std.testing.expectError(error.EndOfStream, r.readEnum(enum(u8) { a, b }, .little));
1360 try std.testing.expectError(error.EndOfStream, r.isBytes("foo"));
1359 var buffer: [3]u8 = undefined;
1360 var r: std.io.Reader = .fixed(&buffer);
1361 r.end = 0; // capacity 3, but empty
1362 try std.testing.expectError(error.EndOfStream, r.takeEnum(enum(u8) { a, b }, .little));
1363 try std.testing.expectError(error.EndOfStream, r.take(3));
13611364}
13621365
13631366fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
......@@ -1389,21 +1392,30 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
13891392test "readAlloc when the backing reader provides one byte at a time" {
13901393 const OneByteReader = struct {
13911394 str: []const u8,
1392 curr: usize,
1393
1394 fn read(self: *@This(), dest: []u8) usize {
1395 if (self.str.len <= self.curr or dest.len == 0)
1396 return 0;
1397
1398 dest[0] = self.str[self.curr];
1399 self.curr += 1;
1395 i: usize,
1396 reader: Reader,
1397
1398 fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1399 assert(@intFromEnum(limit) >= 1);
1400 const self: *@This() = @fieldParentPtr("reader", r);
1401 if (self.str.len - self.i == 0) return error.EndOfStream;
1402 try w.writeByte(self.str[self.i]);
1403 self.i += 1;
14001404 return 1;
14011405 }
14021406 };
1403
14041407 const str = "This is a test";
1405 var one_byte_stream: OneByteReader = .init(str);
1406 const res = try one_byte_stream.reader().streamReadAlloc(std.testing.allocator, str.len + 1);
1408 var one_byte_stream: OneByteReader = .{
1409 .str = str,
1410 .i = 0,
1411 .reader = .{
1412 .buffer = &.{},
1413 .vtable = &.{ .stream = OneByteReader.stream },
1414 .seek = 0,
1415 .end = 0,
1416 },
1417 };
1418 const res = try one_byte_stream.reader.allocRemaining(std.testing.allocator, .unlimited);
14071419 defer std.testing.allocator.free(res);
14081420 try std.testing.expectEqualStrings(str, res);
14091421}
lib/std/io/Writer.zig+128-133
......@@ -37,6 +37,10 @@ pub const VTable = struct {
3737 /// The last element of `data` is repeated as necessary so that it is
3838 /// written `splat` number of times, which may be zero.
3939 ///
40 /// This function may not be called if the data to be written could have
41 /// been stored in `buffer` instead, including when the amount of data to
42 /// be written is zero and the buffer capacity is zero.
43 ///
4044 /// Number of bytes consumed from `data` is returned, excluding bytes from
4145 /// `buffer`.
4246 ///
......@@ -800,18 +804,13 @@ pub fn printValue(
800804) Error!void {
801805 const T = @TypeOf(value);
802806
803 if (comptime std.mem.eql(u8, fmt, "*")) {
804 return w.printAddress(value);
805 }
807 if (comptime std.mem.eql(u8, fmt, "*")) return w.printAddress(value);
808 if (fmt.len > 0 and fmt[0] == 'f') return value.format(w, fmt[1..]);
806809
807810 const is_any = comptime std.mem.eql(u8, fmt, ANY);
808 if (!is_any and std.meta.hasMethod(T, "format")) {
809 if (fmt.len > 0 and fmt[0] == 'f') {
810 return value.format(w, fmt[1..]);
811 } else if (fmt.len == 0) {
812 // after 0.15.0 is tagged, delete the hasMethod condition and this compile error
813 @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
814 }
811 if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) {
812 // after 0.15.0 is tagged, delete this compile error and its condition
813 @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
815814 }
816815
817816 switch (@typeInfo(T)) {
......@@ -952,9 +951,8 @@ pub fn printValue(
952951 },
953952 .pointer => |ptr_info| switch (ptr_info.size) {
954953 .one => switch (@typeInfo(ptr_info.child)) {
955 .array, .@"enum", .@"union", .@"struct" => {
956 return w.printValue(fmt, options, value.*, max_depth);
957 },
954 .array => |array_info| return w.printValue(fmt, options, @as([]const array_info.child, value), max_depth),
955 .@"enum", .@"union", .@"struct" => return w.printValue(fmt, options, value.*, max_depth),
958956 else => {
959957 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
960958 try w.writeVecAll(&buffers);
......@@ -1120,7 +1118,12 @@ pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error
11201118
11211119pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {
11221120 var buf: [4]u8 = undefined;
1123 const len = try std.unicode.utf8Encode(c, &buf);
1121 const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) {
1122 error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: {
1123 buf[0..3].* = std.unicode.replacement_character_utf8;
1124 break :l 3;
1125 },
1126 };
11241127 return w.alignBufferOptions(buf[0..len], options);
11251128}
11261129
......@@ -1553,13 +1556,7 @@ test "formatValue max_depth" {
15531556 x: f32,
15541557 y: f32,
15551558
1556 pub fn format(
1557 self: SelfType,
1558 comptime fmt: []const u8,
1559 options: std.fmt.Options,
1560 w: *Writer,
1561 ) Error!void {
1562 _ = options;
1559 pub fn format(self: SelfType, w: *Writer, comptime fmt: []const u8) Error!void {
15631560 if (fmt.len == 0) {
15641561 return w.print("({d:.3},{d:.3})", .{ self.x, self.y });
15651562 } else {
......@@ -1600,131 +1597,131 @@ test "formatValue max_depth" {
16001597 try w.printValue("", .{}, inst, 0);
16011598 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered());
16021599
1603 w.reset();
1600 w = .fixed(&buf);
16041601 try w.printValue("", .{}, inst, 1);
16051602 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
16061603
1607 w.reset();
1604 w = .fixed(&buf);
16081605 try w.printValue("", .{}, inst, 2);
16091606 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
16101607
1611 w.reset();
1608 w = .fixed(&buf);
16121609 try w.printValue("", .{}, inst, 3);
16131610 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
16141611
16151612 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
1616 w.reset();
1613 w = .fixed(&buf);
16171614 try w.printValue("", .{}, vec, 0);
16181615 try testing.expectEqualStrings("{ ... }", w.buffered());
16191616
1620 w.reset();
1617 w = .fixed(&buf);
16211618 try w.printValue("", .{}, vec, 1);
16221619 try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());
16231620}
16241621
16251622test printDuration {
1626 testDurationCase("0ns", 0);
1627 testDurationCase("1ns", 1);
1628 testDurationCase("999ns", std.time.ns_per_us - 1);
1629 testDurationCase("1us", std.time.ns_per_us);
1630 testDurationCase("1.45us", 1450);
1631 testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
1632 testDurationCase("14.5us", 14500);
1633 testDurationCase("145us", 145000);
1634 testDurationCase("999.999us", std.time.ns_per_ms - 1);
1635 testDurationCase("1ms", std.time.ns_per_ms + 1);
1636 testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
1637 testDurationCase("1.11ms", 1110000);
1638 testDurationCase("1.111ms", 1111000);
1639 testDurationCase("1.111ms", 1111100);
1640 testDurationCase("999.999ms", std.time.ns_per_s - 1);
1641 testDurationCase("1s", std.time.ns_per_s);
1642 testDurationCase("59.999s", std.time.ns_per_min - 1);
1643 testDurationCase("1m", std.time.ns_per_min);
1644 testDurationCase("1h", std.time.ns_per_hour);
1645 testDurationCase("1d", std.time.ns_per_day);
1646 testDurationCase("1w", std.time.ns_per_week);
1647 testDurationCase("1y", 365 * std.time.ns_per_day);
1648 testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
1649 testDurationCase("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1650 testDurationCase("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1651 testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1652 testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1653 testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1654 testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1655 testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
1656
1657 testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1658 testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1659 testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
1623 try testDurationCase("0ns", 0);
1624 try testDurationCase("1ns", 1);
1625 try testDurationCase("999ns", std.time.ns_per_us - 1);
1626 try testDurationCase("1us", std.time.ns_per_us);
1627 try testDurationCase("1.45us", 1450);
1628 try testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
1629 try testDurationCase("14.5us", 14500);
1630 try testDurationCase("145us", 145000);
1631 try testDurationCase("999.999us", std.time.ns_per_ms - 1);
1632 try testDurationCase("1ms", std.time.ns_per_ms + 1);
1633 try testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
1634 try testDurationCase("1.11ms", 1110000);
1635 try testDurationCase("1.111ms", 1111000);
1636 try testDurationCase("1.111ms", 1111100);
1637 try testDurationCase("999.999ms", std.time.ns_per_s - 1);
1638 try testDurationCase("1s", std.time.ns_per_s);
1639 try testDurationCase("59.999s", std.time.ns_per_min - 1);
1640 try testDurationCase("1m", std.time.ns_per_min);
1641 try testDurationCase("1h", std.time.ns_per_hour);
1642 try testDurationCase("1d", std.time.ns_per_day);
1643 try testDurationCase("1w", std.time.ns_per_week);
1644 try testDurationCase("1y", 365 * std.time.ns_per_day);
1645 try testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
1646 try testDurationCase("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1647 try testDurationCase("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1648 try testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1649 try testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1650 try testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1651 try testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1652 try testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
1653
1654 try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1655 try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1656 try testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
16601657}
16611658
16621659test printDurationSigned {
1663 testDurationCaseSigned("0ns", 0);
1664 testDurationCaseSigned("1ns", 1);
1665 testDurationCaseSigned("-1ns", -(1));
1666 testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
1667 testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
1668 testDurationCaseSigned("1us", std.time.ns_per_us);
1669 testDurationCaseSigned("-1us", -(std.time.ns_per_us));
1670 testDurationCaseSigned("1.45us", 1450);
1671 testDurationCaseSigned("-1.45us", -(1450));
1672 testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
1673 testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
1674 testDurationCaseSigned("14.5us", 14500);
1675 testDurationCaseSigned("-14.5us", -(14500));
1676 testDurationCaseSigned("145us", 145000);
1677 testDurationCaseSigned("-145us", -(145000));
1678 testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
1679 testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
1680 testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
1681 testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
1682 testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
1683 testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
1684 testDurationCaseSigned("1.11ms", 1110000);
1685 testDurationCaseSigned("-1.11ms", -(1110000));
1686 testDurationCaseSigned("1.111ms", 1111000);
1687 testDurationCaseSigned("-1.111ms", -(1111000));
1688 testDurationCaseSigned("1.111ms", 1111100);
1689 testDurationCaseSigned("-1.111ms", -(1111100));
1690 testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
1691 testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
1692 testDurationCaseSigned("1s", std.time.ns_per_s);
1693 testDurationCaseSigned("-1s", -(std.time.ns_per_s));
1694 testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
1695 testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
1696 testDurationCaseSigned("1m", std.time.ns_per_min);
1697 testDurationCaseSigned("-1m", -(std.time.ns_per_min));
1698 testDurationCaseSigned("1h", std.time.ns_per_hour);
1699 testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
1700 testDurationCaseSigned("1d", std.time.ns_per_day);
1701 testDurationCaseSigned("-1d", -(std.time.ns_per_day));
1702 testDurationCaseSigned("1w", std.time.ns_per_week);
1703 testDurationCaseSigned("-1w", -(std.time.ns_per_week));
1704 testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
1705 testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
1706 testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
1707 testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
1708 testDurationCaseSigned("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1709 testDurationCaseSigned("-1y1h1.001s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms));
1710 testDurationCaseSigned("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1711 testDurationCaseSigned("-1y1h1s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us));
1712 testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1713 testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
1714 testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1715 testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
1716 testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1717 testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
1718 testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1719 testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
1720 testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
1721 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
1722 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
1723
1724 testing.expectFmt("=======0ns", "{s:=>10}", .{0});
1725 testing.expectFmt("1ns=======", "{s:=<10}", .{1});
1726 testing.expectFmt("-1ns======", "{s:=<10}", .{-(1)});
1727 testing.expectFmt(" -999ns ", "{s:^10}", .{-(std.time.ns_per_us - 1)});
1660 try testDurationCaseSigned("0ns", 0);
1661 try testDurationCaseSigned("1ns", 1);
1662 try testDurationCaseSigned("-1ns", -(1));
1663 try testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
1664 try testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
1665 try testDurationCaseSigned("1us", std.time.ns_per_us);
1666 try testDurationCaseSigned("-1us", -(std.time.ns_per_us));
1667 try testDurationCaseSigned("1.45us", 1450);
1668 try testDurationCaseSigned("-1.45us", -(1450));
1669 try testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
1670 try testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
1671 try testDurationCaseSigned("14.5us", 14500);
1672 try testDurationCaseSigned("-14.5us", -(14500));
1673 try testDurationCaseSigned("145us", 145000);
1674 try testDurationCaseSigned("-145us", -(145000));
1675 try testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
1676 try testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
1677 try testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
1678 try testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
1679 try testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
1680 try testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
1681 try testDurationCaseSigned("1.11ms", 1110000);
1682 try testDurationCaseSigned("-1.11ms", -(1110000));
1683 try testDurationCaseSigned("1.111ms", 1111000);
1684 try testDurationCaseSigned("-1.111ms", -(1111000));
1685 try testDurationCaseSigned("1.111ms", 1111100);
1686 try testDurationCaseSigned("-1.111ms", -(1111100));
1687 try testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
1688 try testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
1689 try testDurationCaseSigned("1s", std.time.ns_per_s);
1690 try testDurationCaseSigned("-1s", -(std.time.ns_per_s));
1691 try testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
1692 try testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
1693 try testDurationCaseSigned("1m", std.time.ns_per_min);
1694 try testDurationCaseSigned("-1m", -(std.time.ns_per_min));
1695 try testDurationCaseSigned("1h", std.time.ns_per_hour);
1696 try testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
1697 try testDurationCaseSigned("1d", std.time.ns_per_day);
1698 try testDurationCaseSigned("-1d", -(std.time.ns_per_day));
1699 try testDurationCaseSigned("1w", std.time.ns_per_week);
1700 try testDurationCaseSigned("-1w", -(std.time.ns_per_week));
1701 try testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
1702 try testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
1703 try testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
1704 try testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
1705 try testDurationCaseSigned("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
1706 try testDurationCaseSigned("-1y1h1.001s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms));
1707 try testDurationCaseSigned("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
1708 try testDurationCaseSigned("-1y1h1s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us));
1709 try testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1710 try testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
1711 try testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1712 try testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
1713 try testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1714 try testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
1715 try testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1716 try testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
1717 try testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
1718 try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
1719 try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
1720
1721 try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1722 try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1723 try testing.expectFmt("-1ns======", "{D:=<10}", .{-(1)});
1724 try testing.expectFmt(" -999ns ", "{D:^10}", .{-(std.time.ns_per_us - 1)});
17281725}
17291726
17301727fn testDurationCase(expected: []const u8, input: u64) !void {
......@@ -1762,7 +1759,7 @@ test printIntOptions {
17621759test "printInt with comptime_int" {
17631760 var buf: [20]u8 = undefined;
17641761 var w: Writer = .fixed(&buf);
1765 try w.printInt(@as(comptime_int, 123456789123456789), "", .{});
1762 try w.printInt("", .{}, @as(comptime_int, 123456789123456789));
17661763 try std.testing.expectEqualStrings("123456789123456789", w.buffered());
17671764}
17681765
......@@ -1777,7 +1774,7 @@ test "printFloat with comptime_float" {
17771774fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
17781775 var buffer: [100]u8 = undefined;
17791776 var w: Writer = .fixed(&buffer);
1780 w.printIntOptions(value, base, case, options);
1777 try w.printIntOptions(value, base, case, options);
17811778 try testing.expectEqualStrings(expected, w.buffered());
17821779}
17831780
......@@ -1832,17 +1829,15 @@ test "fixed output" {
18321829 try w.writeAll("world");
18331830 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
18341831
1835 try testing.expectError(error.WriteStreamEnd, w.writeAll("!"));
1832 try testing.expectError(error.WriteFailed, w.writeAll("!"));
18361833 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
18371834
1838 w.reset();
1835 w = .fixed(&buffer);
1836
18391837 try testing.expect(w.buffered().len == 0);
18401838
1841 try testing.expectError(error.WriteStreamEnd, w.writeAll("Hello world!"));
1839 try testing.expectError(error.WriteFailed, w.writeAll("Hello world!"));
18421840 try testing.expect(std.mem.eql(u8, w.buffered(), "Hello worl"));
1843
1844 try w.seekTo((try w.getEndPos()) + 1);
1845 try testing.expectError(error.WriteStreamEnd, w.writeAll("H"));
18461841}
18471842
18481843pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
lib/std/io/buffered_atomic_file.zig+1-1
......@@ -33,7 +33,7 @@ pub const BufferedAtomicFile = struct {
3333 self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options);
3434 errdefer self.atomic_file.deinit();
3535
36 self.file_writer = self.atomic_file.file.writer();
36 self.file_writer = self.atomic_file.file.deprecatedWriter();
3737 self.buffered_writer = .{ .unbuffered_writer = self.file_writer };
3838 return self;
3939 }
lib/std/io/test.zig+4-4
......@@ -24,7 +24,7 @@ test "write a file, read it, then delete it" {
2424 var file = try tmp.dir.createFile(tmp_file_name, .{});
2525 defer file.close();
2626
27 var buf_stream = io.bufferedWriter(file.writer());
27 var buf_stream = io.bufferedWriter(file.deprecatedWriter());
2828 const st = buf_stream.writer();
2929 try st.print("begin", .{});
3030 try st.writeAll(data[0..]);
......@@ -45,7 +45,7 @@ test "write a file, read it, then delete it" {
4545 const expected_file_size: u64 = "begin".len + data.len + "end".len;
4646 try expectEqual(expected_file_size, file_size);
4747
48 var buf_stream = io.bufferedReader(file.reader());
48 var buf_stream = io.bufferedReader(file.deprecatedReader());
4949 const st = buf_stream.reader();
5050 const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024);
5151 defer std.testing.allocator.free(contents);
......@@ -66,7 +66,7 @@ test "BitStreams with File Stream" {
6666 var file = try tmp.dir.createFile(tmp_file_name, .{});
6767 defer file.close();
6868
69 var bit_stream = io.bitWriter(native_endian, file.writer());
69 var bit_stream = io.bitWriter(native_endian, file.deprecatedWriter());
7070
7171 try bit_stream.writeBits(@as(u2, 1), 1);
7272 try bit_stream.writeBits(@as(u5, 2), 2);
......@@ -80,7 +80,7 @@ test "BitStreams with File Stream" {
8080 var file = try tmp.dir.openFile(tmp_file_name, .{});
8181 defer file.close();
8282
83 var bit_stream = io.bitReader(native_endian, file.reader());
83 var bit_stream = io.bitReader(native_endian, file.deprecatedReader());
8484
8585 var out_bits: u16 = undefined;
8686
lib/std/json/dynamic.zig+1-1
......@@ -56,7 +56,7 @@ pub const Value = union(enum) {
5656 std.debug.lockStdErr();
5757 defer std.debug.unlockStdErr();
5858
59 const stderr = std.fs.File.stderr().writer();
59 const stderr = std.fs.File.stderr().deprecatedWriter();
6060 stringify(self, .{}, stderr) catch return;
6161 }
6262
lib/std/json/fmt.zig+4-9
......@@ -1,4 +1,5 @@
1const std = @import("std");
1const std = @import("../std.zig");
2const assert = std.debug.assert;
23
34const stringify = @import("stringify.zig").stringify;
45const StringifyOptions = @import("stringify.zig").StringifyOptions;
......@@ -14,14 +15,8 @@ pub fn Formatter(comptime T: type) type {
1415 value: T,
1516 options: StringifyOptions,
1617
17 pub fn format(
18 self: @This(),
19 comptime fmt_spec: []const u8,
20 options: std.fmt.FormatOptions,
21 writer: anytype,
22 ) !void {
23 _ = fmt_spec;
24 _ = options;
18 pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
19 comptime assert(f.len == 0);
2520 try stringify(self.value, self.options, writer);
2621 }
2722 };
lib/std/json/stringify.zig+6-3
......@@ -689,7 +689,8 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
689689 // then it may be represented as a six-character sequence: a reverse solidus, followed
690690 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
691691 try out_stream.writeAll("\\u");
692 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
692 //try w.printInt("x", .{ .width = 4, .fill = '0' }, codepoint);
693 try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{codepoint});
693694 } else {
694695 assert(codepoint <= 0x10FFFF);
695696 // To escape an extended character that is not in the Basic Multilingual Plane,
......@@ -697,9 +698,11 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
697698 const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;
698699 const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;
699700 try out_stream.writeAll("\\u");
700 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
701 //try w.printInt("x", .{ .width = 4, .fill = '0' }, high);
702 try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{high});
701703 try out_stream.writeAll("\\u");
702 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
704 //try w.printInt("x", .{ .width = 4, .fill = '0' }, low);
705 try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{low});
703706 }
704707}
705708
lib/std/log.zig+2-2
......@@ -47,7 +47,7 @@
4747//! // Print the message to stderr, silently ignoring any errors
4848//! std.debug.lockStdErr();
4949//! defer std.debug.unlockStdErr();
50//! const stderr = std.fs.File.stderr().writer();
50//! const stderr = std.fs.File.stderr().deprecatedWriter();
5151//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
5252//! }
5353//!
......@@ -148,7 +148,7 @@ pub fn defaultLog(
148148) void {
149149 const level_txt = comptime message_level.asText();
150150 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
151 const stderr = std.fs.File.stderr().writer();
151 const stderr = std.fs.File.stderr().deprecatedWriter();
152152 var bw = std.io.bufferedWriter(stderr);
153153 const writer = bw.writer();
154154
lib/std/math/big/int.zig+5-16
......@@ -2322,13 +2322,7 @@ pub const Const = struct {
23222322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
23232323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
23242324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2325 pub fn format(
2326 self: Const,
2327 comptime fmt: []const u8,
2328 options: std.fmt.FormatOptions,
2329 out_stream: anytype,
2330 ) !void {
2331 _ = options;
2325 pub fn format(self: Const, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
23322326 comptime var base = 10;
23332327 comptime var case: std.fmt.Case = .lower;
23342328
......@@ -2350,7 +2344,7 @@ pub const Const = struct {
23502344
23512345 const available_len = 64;
23522346 if (self.limbs.len > available_len)
2353 return out_stream.writeAll("(BigInt)");
2347 return w.writeAll("(BigInt)");
23542348
23552349 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;
23562350
......@@ -2360,7 +2354,7 @@ pub const Const = struct {
23602354 };
23612355 var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;
23622356 const len = self.toString(&buf, base, case, &limbs);
2363 return out_stream.writeAll(buf[0..len]);
2357 return w.writeAll(buf[0..len]);
23642358 }
23652359
23662360 /// Converts self to a string in the requested base.
......@@ -2934,13 +2928,8 @@ pub const Managed = struct {
29342928 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
29352929 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
29362930 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2937 pub fn format(
2938 self: Managed,
2939 comptime fmt: []const u8,
2940 options: std.fmt.FormatOptions,
2941 out_stream: anytype,
2942 ) !void {
2943 return self.toConst().format(fmt, options, out_stream);
2931 pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
2932 return self.toConst().format(w, f);
29442933 }
29452934
29462935 /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==
lib/std/math/big/int_test.zig+4-4
......@@ -3813,10 +3813,10 @@ test "(BigInt) positive" {
38133813 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
38143814 try b.sub(&a, &c);
38153815
3816 const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});
3816 const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0);
38173817 defer testing.allocator.free(a_fmt);
38183818
3819 const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});
3819 const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0);
38203820 defer testing.allocator.free(b_fmt);
38213821
38223822 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
......@@ -3838,10 +3838,10 @@ test "(BigInt) negative" {
38383838 a.negate();
38393839 try b.add(&a, &c);
38403840
3841 const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});
3841 const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0);
38423842 defer testing.allocator.free(a_fmt);
38433843
3844 const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});
3844 const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0);
38453845 defer testing.allocator.free(b_fmt);
38463846
38473847 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
lib/std/multi_array_list.zig+1
......@@ -991,6 +991,7 @@ test "0 sized struct" {
991991test "struct with many fields" {
992992 const ManyFields = struct {
993993 fn Type(count: comptime_int) type {
994 @setEvalBranchQuota(50000);
994995 var fields: [count]std.builtin.Type.StructField = undefined;
995996 for (0..count) |i| {
996997 fields[i] = .{
lib/std/net.zig+22-48
......@@ -161,22 +161,14 @@ pub const Address = extern union {
161161 }
162162 }
163163
164 pub fn format(
165 self: Address,
166 comptime fmt: []const u8,
167 options: std.fmt.FormatOptions,
168 out_stream: anytype,
169 ) !void {
170 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
164 pub fn format(self: Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
165 comptime assert(fmt.len == 0);
171166 switch (self.any.family) {
172 posix.AF.INET => try self.in.format(fmt, options, out_stream),
173 posix.AF.INET6 => try self.in6.format(fmt, options, out_stream),
167 posix.AF.INET => try self.in.format(w, fmt),
168 posix.AF.INET6 => try self.in6.format(w, fmt),
174169 posix.AF.UNIX => {
175 if (!has_unix_sockets) {
176 unreachable;
177 }
178
179 try std.fmt.format(out_stream, "{s}", .{std.mem.sliceTo(&self.un.path, 0)});
170 if (!has_unix_sockets) unreachable;
171 try w.writeAll(std.mem.sliceTo(&self.un.path, 0));
180172 },
181173 else => unreachable,
182174 }
......@@ -349,22 +341,10 @@ pub const Ip4Address = extern struct {
349341 self.sa.port = mem.nativeToBig(u16, port);
350342 }
351343
352 pub fn format(
353 self: Ip4Address,
354 comptime fmt: []const u8,
355 options: std.fmt.FormatOptions,
356 out_stream: anytype,
357 ) !void {
358 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
359 _ = options;
360 const bytes = @as(*const [4]u8, @ptrCast(&self.sa.addr));
361 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
362 bytes[0],
363 bytes[1],
364 bytes[2],
365 bytes[3],
366 self.getPort(),
367 });
344 pub fn format(self: Ip4Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
345 comptime assert(fmt.len == 0);
346 const bytes: *const [4]u8 = @ptrCast(&self.sa.addr);
347 try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() });
368348 }
369349
370350 pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {
......@@ -653,17 +633,11 @@ pub const Ip6Address = extern struct {
653633 self.sa.port = mem.nativeToBig(u16, port);
654634 }
655635
656 pub fn format(
657 self: Ip6Address,
658 comptime fmt: []const u8,
659 options: std.fmt.FormatOptions,
660 out_stream: anytype,
661 ) !void {
662 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
663 _ = options;
636 pub fn format(self: Ip6Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
637 comptime assert(fmt.len == 0);
664638 const port = mem.bigToNative(u16, self.sa.port);
665639 if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
666 try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
640 try w.print("[::ffff:{d}.{d}.{d}.{d}]:{d}", .{
667641 self.sa.addr[12],
668642 self.sa.addr[13],
669643 self.sa.addr[14],
......@@ -711,14 +685,14 @@ pub const Ip6Address = extern struct {
711685 longest_len = 0;
712686 }
713687
714 try out_stream.writeAll("[");
688 try w.writeAll("[");
715689 var i: usize = 0;
716690 var abbrv = false;
717691 while (i < native_endian_parts.len) : (i += 1) {
718692 if (i == longest_start) {
719693 // Emit "::" for the longest zero run
720694 if (!abbrv) {
721 try out_stream.writeAll(if (i == 0) "::" else ":");
695 try w.writeAll(if (i == 0) "::" else ":");
722696 abbrv = true;
723697 }
724698 i += longest_len - 1; // Skip the compressed range
......@@ -727,12 +701,12 @@ pub const Ip6Address = extern struct {
727701 if (abbrv) {
728702 abbrv = false;
729703 }
730 try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
704 try w.print("{x}", .{native_endian_parts[i]});
731705 if (i != native_endian_parts.len - 1) {
732 try out_stream.writeAll(":");
706 try w.writeAll(":");
733707 }
734708 }
735 try std.fmt.format(out_stream, "]:{}", .{port});
709 try w.print("]:{}", .{port});
736710 }
737711
738712 pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {
......@@ -894,7 +868,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
894868 const name_c = try allocator.dupeZ(u8, name);
895869 defer allocator.free(name_c);
896870
897 const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port});
871 const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0);
898872 defer allocator.free(port_c);
899873
900874 const ws2_32 = windows.ws2_32;
......@@ -966,7 +940,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
966940 const name_c = try allocator.dupeZ(u8, name);
967941 defer allocator.free(name_c);
968942
969 const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port});
943 const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0);
970944 defer allocator.free(port_c);
971945
972946 const hints: posix.addrinfo = .{
......@@ -1356,7 +1330,7 @@ fn linuxLookupNameFromHosts(
13561330 };
13571331 defer file.close();
13581332
1359 var buffered_reader = std.io.bufferedReader(file.reader());
1333 var buffered_reader = std.io.bufferedReader(file.deprecatedReader());
13601334 const reader = buffered_reader.reader();
13611335 var line_buf: [512]u8 = undefined;
13621336 while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
......@@ -1557,7 +1531,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
15571531 };
15581532 defer file.close();
15591533
1560 var buf_reader = std.io.bufferedReader(file.reader());
1534 var buf_reader = std.io.bufferedReader(file.deprecatedReader());
15611535 const stream = buf_reader.reader();
15621536 var line_buf: [512]u8 = undefined;
15631537 while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
lib/std/net/test.zig+7-20
......@@ -7,18 +7,12 @@ const testing = std.testing;
77test "parse and render IP addresses at comptime" {
88 if (builtin.os.tag == .wasi) return error.SkipZigTest;
99 comptime {
10 var ipAddrBuffer: [16]u8 = undefined;
11 // Parses IPv6 at comptime
1210 const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
13 var ipv6 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv6addr}) catch unreachable;
14 try std.testing.expect(std.mem.eql(u8, "::1", ipv6[1 .. ipv6.len - 3]));
11 try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr});
1512
16 // Parses IPv4 at comptime
1713 const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;
18 var ipv4 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv4addr}) catch unreachable;
19 try std.testing.expect(std.mem.eql(u8, "127.0.0.1", ipv4[0 .. ipv4.len - 2]));
14 try std.testing.expectFmt("127.0.0.1:0", "{f}", .{ipv4addr});
2015
21 // Returns error for invalid IP addresses at comptime
2216 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0));
2317 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("127.01.0.1", 0));
2418 try testing.expectError(error.InvalidIPAddressFormat, net.Address.resolveIp("::123.123.123.123", 0));
......@@ -28,13 +22,8 @@ test "parse and render IP addresses at comptime" {
2822
2923test "format IPv6 address with no zero runs" {
3024 if (builtin.os.tag == .wasi) return error.SkipZigTest;
31
3225 const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);
33
34 var buffer: [50]u8 = undefined;
35 const result = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
36
37 try std.testing.expectEqualStrings("[2001:db8:1:2:3:4:5:6]:0", result);
26 try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr});
3827}
3928
4029test "parse IPv6 addresses and check compressed form" {
......@@ -111,12 +100,12 @@ test "parse and render IPv6 addresses" {
111100 };
112101 for (ips, 0..) |ip, i| {
113102 const addr = net.Address.parseIp6(ip, 0) catch unreachable;
114 var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
103 var newIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr}) catch unreachable;
115104 try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
116105
117106 if (builtin.os.tag == .linux) {
118107 const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;
119 var newResolvedIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr_via_resolve}) catch unreachable;
108 var newResolvedIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr_via_resolve}) catch unreachable;
120109 try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));
121110 }
122111 }
......@@ -159,7 +148,7 @@ test "parse and render IPv4 addresses" {
159148 "127.0.0.1",
160149 }) |ip| {
161150 const addr = net.Address.parseIp4(ip, 0) catch unreachable;
162 var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
151 var newIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr}) catch unreachable;
163152 try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
164153 }
165154
......@@ -175,10 +164,8 @@ test "parse and render UNIX addresses" {
175164 if (builtin.os.tag == .wasi) return error.SkipZigTest;
176165 if (!net.has_unix_sockets) return error.SkipZigTest;
177166
178 var buffer: [14]u8 = undefined;
179167 const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;
180 const fmt_addr = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
181 try std.testing.expectEqualSlices(u8, "/tmp/testpath", fmt_addr);
168 try std.testing.expectFmt("/tmp/testpath", "{f}", .{addr});
182169
183170 const too_long = [_]u8{'a'} ** 200;
184171 try testing.expectError(error.NameTooLong, net.Address.initUnix(too_long[0..]));
lib/std/os.zig+1
......@@ -31,6 +31,7 @@ pub const uefi = @import("os/uefi.zig");
3131pub const wasi = @import("os/wasi.zig");
3232pub const emscripten = @import("os/emscripten.zig");
3333pub const windows = @import("os/windows.zig");
34pub const freebsd = @import("os/freebsd.zig");
3435
3536test {
3637 _ = linux;
lib/std/os/freebsd.zig created+49
......@@ -0,0 +1,49 @@
1const std = @import("../std.zig");
2const fd_t = std.c.fd_t;
3const off_t = std.c.off_t;
4const unexpectedErrno = std.posix.unexpectedErrno;
5const errno = std.posix.errno;
6
7pub const CopyFileRangeError = error{
8 /// If infd is not open for reading or outfd is not open for writing, or
9 /// opened for writing with O_APPEND, or if infd and outfd refer to the
10 /// same file.
11 BadFileFlags,
12 /// If the copy exceeds the process's file size limit or the maximum
13 /// file size for the file system outfd re- sides on.
14 FileTooBig,
15 /// A signal interrupted the system call before it could be completed.
16 /// This may happen for files on some NFS mounts. When this happens,
17 /// the values pointed to by inoffp and outoffp are reset to the
18 /// initial values for the system call.
19 Interrupted,
20 /// One of:
21 /// * infd and outfd refer to the same file and the byte ranges overlap.
22 /// * The flags argument is not zero.
23 /// * Either infd or outfd refers to a file object that is not a regular file.
24 InvalidArguments,
25 /// An I/O error occurred while reading/writing the files.
26 InputOutput,
27 /// Corrupted data was detected while reading from a file system.
28 CorruptedData,
29 /// Either infd or outfd refers to a directory.
30 IsDir,
31 /// File system that stores outfd is full.
32 NoSpaceLeft,
33};
34
35pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize {
36 const rc = std.c.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
37 switch (errno(rc)) {
38 .SUCCESS => return @intCast(rc),
39 .BADF => return error.BadFileFlags,
40 .FBIG => return error.FileTooBig,
41 .INTR => return error.Interrupted,
42 .INVAL => return error.InvalidArguments,
43 .IO => return error.InputOutput,
44 .INTEGRITY => return error.CorruptedData,
45 .ISDIR => return error.IsDir,
46 .NOSPC => return error.NoSpaceLeft,
47 else => |err| return unexpectedErrno(err),
48 }
49}
lib/std/os/linux.zig+129-1
......@@ -9420,4 +9420,132 @@ pub const msghdr_const = extern struct {
94209420 control: ?*const anyopaque,
94219421 controllen: usize,
94229422 flags: u32,
9423};
\ No newline at end of file
9423};
9424
9425/// The syscalls, but with Zig error sets, going through libc if linking libc,
9426/// and with some footguns eliminated.
9427pub const wrapped = struct {
9428 pub const lfs64_abi = builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid());
9429 const system = if (builtin.link_libc) std.c else std.os.linux;
9430
9431 pub const SendfileError = std.posix.UnexpectedError || error{
9432 /// `out_fd` is an unconnected socket, or out_fd closed its read end.
9433 BrokenPipe,
9434 /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd.
9435 UnsupportedOperation,
9436 /// Nonblocking I/O has been selected but the write would block.
9437 WouldBlock,
9438 /// Unspecified error while reading from in_fd.
9439 InputOutput,
9440 /// Insufficient kernel memory to read from in_fd.
9441 SystemResources,
9442 /// `offset` is not `null` but the input file is not seekable.
9443 Unseekable,
9444 };
9445
9446 pub fn sendfile(
9447 out_fd: fd_t,
9448 in_fd: fd_t,
9449 in_offset: ?*off_t,
9450 in_len: usize,
9451 ) SendfileError!usize {
9452 const adjusted_len = @min(in_len, 0x7ffff000); // Prevents EOVERFLOW.
9453 const sendfileSymbol = if (lfs64_abi) system.sendfile64 else system.sendfile;
9454 const rc = sendfileSymbol(out_fd, in_fd, in_offset, adjusted_len);
9455 switch (errno(rc)) {
9456 .SUCCESS => return @intCast(rc),
9457 .BADF => return invalidApiUsage(), // Always a race condition.
9458 .FAULT => return invalidApiUsage(), // Segmentation fault.
9459 .OVERFLOW => return unexpectedErrno(.OVERFLOW), // We avoid passing too large of a `count`.
9460 .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
9461 .INVAL => return error.UnsupportedOperation,
9462 .AGAIN => return error.WouldBlock,
9463 .IO => return error.InputOutput,
9464 .PIPE => return error.BrokenPipe,
9465 .NOMEM => return error.SystemResources,
9466 .NXIO => return error.Unseekable,
9467 .SPIPE => return error.Unseekable,
9468 else => |err| return unexpectedErrno(err),
9469 }
9470 }
9471
9472 pub const CopyFileRangeError = std.posix.UnexpectedError || error{
9473 /// One of:
9474 /// * One or more file descriptors are not valid.
9475 /// * fd_in is not open for reading; or fd_out is not open for writing.
9476 /// * The O_APPEND flag is set for the open file description referred
9477 /// to by the file descriptor fd_out.
9478 BadFileFlags,
9479 /// One of:
9480 /// * An attempt was made to write at a position past the maximum file
9481 /// offset the kernel supports.
9482 /// * An attempt was made to write a range that exceeds the allowed
9483 /// maximum file size. The maximum file size differs between
9484 /// filesystem implementations and can be different from the maximum
9485 /// allowed file offset.
9486 /// * An attempt was made to write beyond the process's file size
9487 /// resource limit. This may also result in the process receiving a
9488 /// SIGXFSZ signal.
9489 FileTooBig,
9490 /// One of:
9491 /// * either fd_in or fd_out is not a regular file
9492 /// * flags argument is not zero
9493 /// * fd_in and fd_out refer to the same file and the source and target ranges overlap.
9494 InvalidArguments,
9495 /// A low-level I/O error occurred while copying.
9496 InputOutput,
9497 /// Either fd_in or fd_out refers to a directory.
9498 IsDir,
9499 OutOfMemory,
9500 /// There is not enough space on the target filesystem to complete the copy.
9501 NoSpaceLeft,
9502 /// (since Linux 5.19) the filesystem does not support this operation.
9503 OperationNotSupported,
9504 /// The requested source or destination range is too large to represent
9505 /// in the specified data types.
9506 Overflow,
9507 /// fd_out refers to an immutable file.
9508 PermissionDenied,
9509 /// Either fd_in or fd_out refers to an active swap file.
9510 SwapFile,
9511 /// The files referred to by fd_in and fd_out are not on the same
9512 /// filesystem, and the source and target filesystems are not of the
9513 /// same type, or do not support cross-filesystem copy.
9514 NotSameFileSystem,
9515 };
9516
9517 pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize {
9518 const rc = system.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
9519 switch (errno(rc)) {
9520 .SUCCESS => return @intCast(rc),
9521 .BADF => return error.BadFileFlags,
9522 .FBIG => return error.FileTooBig,
9523 .INVAL => return error.InvalidArguments,
9524 .IO => return error.InputOutput,
9525 .ISDIR => return error.IsDir,
9526 .NOMEM => return error.OutOfMemory,
9527 .NOSPC => return error.NoSpaceLeft,
9528 .OPNOTSUPP => return error.OperationNotSupported,
9529 .OVERFLOW => return error.Overflow,
9530 .PERM => return error.PermissionDenied,
9531 .TXTBSY => return error.SwapFile,
9532 .XDEV => return error.NotSameFileSystem,
9533 else => |err| return unexpectedErrno(err),
9534 }
9535 }
9536
9537 const unexpectedErrno = std.posix.unexpectedErrno;
9538
9539 fn invalidApiUsage() error{Unexpected} {
9540 if (builtin.mode == .Debug) @panic("invalid API usage");
9541 return error.Unexpected;
9542 }
9543
9544 fn errno(rc: anytype) E {
9545 if (builtin.link_libc) {
9546 return if (rc == -1) @enumFromInt(std.c._errno().*) else .SUCCESS;
9547 } else {
9548 return errnoFromSyscall(rc);
9549 }
9550 }
9551};
lib/std/os/uefi.zig+16-25
......@@ -1,4 +1,5 @@
11const std = @import("../std.zig");
2const assert = std.debug.assert;
23
34/// A protocol is an interface identified by a GUID.
45pub const protocol = @import("uefi/protocol.zig");
......@@ -59,31 +60,21 @@ pub const Guid = extern struct {
5960 node: [6]u8,
6061
6162 /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
62 pub fn format(
63 self: @This(),
64 comptime f: []const u8,
65 options: std.fmt.FormatOptions,
66 writer: anytype,
67 ) !void {
68 _ = options;
69 if (f.len == 0) {
70 const fmt = std.fmt.fmtSliceHexLower;
71
72 const time_low = @byteSwap(self.time_low);
73 const time_mid = @byteSwap(self.time_mid);
74 const time_high_and_version = @byteSwap(self.time_high_and_version);
75
76 return std.fmt.format(writer, "{:0>8}-{:0>4}-{:0>4}-{:0>2}{:0>2}-{:0>12}", .{
77 fmt(std.mem.asBytes(&time_low)),
78 fmt(std.mem.asBytes(&time_mid)),
79 fmt(std.mem.asBytes(&time_high_and_version)),
80 fmt(std.mem.asBytes(&self.clock_seq_high_and_reserved)),
81 fmt(std.mem.asBytes(&self.clock_seq_low)),
82 fmt(std.mem.asBytes(&self.node)),
83 });
84 } else {
85 std.fmt.invalidFmtError(f, self);
86 }
63 pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
64 comptime assert(f.len == 0);
65
66 const time_low = @byteSwap(self.time_low);
67 const time_mid = @byteSwap(self.time_mid);
68 const time_high_and_version = @byteSwap(self.time_high_and_version);
69
70 return std.fmt.format(writer, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
71 std.mem.asBytes(&time_low),
72 std.mem.asBytes(&time_mid),
73 std.mem.asBytes(&time_high_and_version),
74 std.mem.asBytes(&self.clock_seq_high_and_reserved),
75 std.mem.asBytes(&self.clock_seq_low),
76 std.mem.asBytes(&self.node),
77 });
8778 }
8879
8980 pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {
lib/std/os/uefi/protocol/file.zig-24
......@@ -79,30 +79,6 @@ pub const File = extern struct {
7979 VolumeFull,
8080 };
8181
82 pub const SeekableStream = io.SeekableStream(
83 *File,
84 SeekError,
85 SeekError,
86 setPosition,
87 seekBy,
88 getPosition,
89 getEndPos,
90 );
91 pub const Reader = io.GenericReader(*File, ReadError, read);
92 pub const Writer = io.GenericWriter(*File, WriteError, write);
93
94 pub fn seekableStream(self: *File) SeekableStream {
95 return .{ .context = self };
96 }
97
98 pub fn reader(self: *File) Reader {
99 return .{ .context = self };
100 }
101
102 pub fn writer(self: *File) Writer {
103 return .{ .context = self };
104 }
105
10682 pub fn open(
10783 self: *const File,
10884 file_name: [*:0]const u16,
lib/std/os/windows.zig-34
......@@ -1690,40 +1690,6 @@ pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
16901690 return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
16911691}
16921692
1693pub fn sendmsg(
1694 s: ws2_32.SOCKET,
1695 msg: *ws2_32.WSAMSG_const,
1696 flags: u32,
1697) i32 {
1698 var bytes_send: DWORD = undefined;
1699 if (ws2_32.WSASendMsg(s, msg, flags, &bytes_send, null, null) == ws2_32.SOCKET_ERROR) {
1700 return ws2_32.SOCKET_ERROR;
1701 } else {
1702 return @as(i32, @as(u31, @intCast(bytes_send)));
1703 }
1704}
1705
1706pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
1707 var buffer = ws2_32.WSABUF{ .len = @as(u31, @truncate(len)), .buf = @constCast(buf) };
1708 var bytes_send: DWORD = undefined;
1709 if (ws2_32.WSASendTo(s, @as([*]ws2_32.WSABUF, @ptrCast(&buffer)), 1, &bytes_send, flags, to, @as(i32, @intCast(to_len)), null, null) == ws2_32.SOCKET_ERROR) {
1710 return ws2_32.SOCKET_ERROR;
1711 } else {
1712 return @as(i32, @as(u31, @intCast(bytes_send)));
1713 }
1714}
1715
1716pub fn recvfrom(s: ws2_32.SOCKET, buf: [*]u8, len: usize, flags: u32, from: ?*ws2_32.sockaddr, from_len: ?*ws2_32.socklen_t) i32 {
1717 var buffer = ws2_32.WSABUF{ .len = @as(u31, @truncate(len)), .buf = buf };
1718 var bytes_received: DWORD = undefined;
1719 var flags_inout = flags;
1720 if (ws2_32.WSARecvFrom(s, @as([*]ws2_32.WSABUF, @ptrCast(&buffer)), 1, &bytes_received, &flags_inout, from, @as(?*i32, @ptrCast(from_len)), null, null) == ws2_32.SOCKET_ERROR) {
1721 return ws2_32.SOCKET_ERROR;
1722 } else {
1723 return @as(i32, @as(u31, @intCast(bytes_received)));
1724 }
1725}
1726
17271693pub fn poll(fds: [*]ws2_32.pollfd, n: c_ulong, timeout: i32) i32 {
17281694 return ws2_32.WSAPoll(fds, n, timeout);
17291695}
lib/std/os/windows/ws2_32.zig+1-9
......@@ -1829,7 +1829,7 @@ pub extern "ws2_32" fn sendto(
18291829 buf: [*]const u8,
18301830 len: i32,
18311831 flags: i32,
1832 to: *const sockaddr,
1832 to: ?*const sockaddr,
18331833 tolen: i32,
18341834) callconv(.winapi) i32;
18351835
......@@ -2116,14 +2116,6 @@ pub extern "ws2_32" fn WSASendMsg(
21162116 lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
21172117) callconv(.winapi) i32;
21182118
2119pub extern "ws2_32" fn WSARecvMsg(
2120 s: SOCKET,
2121 lpMsg: *WSAMSG,
2122 lpdwNumberOfBytesRecv: ?*u32,
2123 lpOverlapped: ?*OVERLAPPED,
2124 lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
2125) callconv(.winapi) i32;
2126
21272119pub extern "ws2_32" fn WSASendDisconnect(
21282120 s: SOCKET,
21292121 lpOutboundDisconnectData: ?*WSABUF,
lib/std/posix.zig+1-1
......@@ -651,7 +651,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
651651 }
652652
653653 const file: fs.File = .{ .handle = fd };
654 const stream = file.reader();
654 const stream = file.deprecatedReader();
655655 stream.readNoEof(buf) catch return error.Unexpected;
656656}
657657
lib/std/posix/test.zig+1-1
......@@ -667,7 +667,7 @@ test "mmap" {
667667 const file = try tmp.dir.createFile(test_out_file, .{});
668668 defer file.close();
669669
670 const stream = file.writer();
670 const stream = file.deprecatedWriter();
671671
672672 var i: u32 = 0;
673673 while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
lib/std/process.zig+7-7
......@@ -1553,7 +1553,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
15531553 const file = try std.fs.openFileAbsolute("/etc/passwd", .{});
15541554 defer file.close();
15551555
1556 const reader = file.reader();
1556 const reader = file.deprecatedReader();
15571557
15581558 const State = enum {
15591559 Start,
......@@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap(
18951895 var i: usize = 0;
18961896
18971897 if (zig_progress_action == .add) {
1898 envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});
1898 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
18991899 i += 1;
19001900 }
19011901
......@@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap(
19061906 .add => unreachable,
19071907 .delete => continue,
19081908 .edit => {
1909 envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={d}", .{
1909 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={d}", .{
19101910 pair.key_ptr.*, options.zig_progress_fd.?,
1911 });
1911 }, 0);
19121912 i += 1;
19131913 continue;
19141914 },
19151915 .nothing => {},
19161916 };
19171917
1918 envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* });
1918 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* }, 0);
19191919 i += 1;
19201920 }
19211921 }
......@@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting(
19651965 var existing_index: usize = 0;
19661966
19671967 if (zig_progress_action == .add) {
1968 envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});
1968 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
19691969 i += 1;
19701970 }
19711971
......@@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting(
19741974 .add => unreachable,
19751975 .delete => continue,
19761976 .edit => {
1977 envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});
1977 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
19781978 i += 1;
19791979 continue;
19801980 },
lib/std/process/Child.zig+2-2
......@@ -1004,12 +1004,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
10041004
10051005fn writeIntFd(fd: i32, value: ErrInt) !void {
10061006 const file: File = .{ .handle = fd };
1007 file.writer().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
1007 file.deprecatedWriter().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
10081008}
10091009
10101010fn readIntFd(fd: i32) !ErrInt {
10111011 const file: File = .{ .handle = fd };
1012 return @intCast(file.reader().readInt(u64, .little) catch return error.SystemResources);
1012 return @intCast(file.deprecatedReader().readInt(u64, .little) catch return error.SystemResources);
10131013}
10141014
10151015const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
lib/std/testing.zig+15-6
......@@ -105,7 +105,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
105105 .error_set,
106106 => {
107107 if (actual != expected) {
108 print("expected {}, found {}\n", .{ expected, actual });
108 print("expected {any}, found {any}\n", .{ expected, actual });
109109 return error.TestExpectedEqual;
110110 }
111111 },
......@@ -267,9 +267,13 @@ test "expectEqual null" {
267267
268268/// This function is intended to be used only in tests. When the formatted result of the template
269269/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how
270/// they are not equal, then returns an error. It depends on `expectEqualStrings()` for printing
270/// they are not equal, then returns an error. It depends on `expectEqualStrings` for printing
271271/// diagnostics.
272272pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
273 if (@inComptime()) {
274 var buffer: [std.fmt.count(template, args)]u8 = undefined;
275 return expectEqualStrings(expected, try std.fmt.bufPrint(&buffer, template, args));
276 }
273277 const actual = try std.fmt.allocPrint(allocator, template, args);
274278 defer allocator.free(actual);
275279 return expectEqualStrings(expected, actual);
......@@ -415,7 +419,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
415419 print("... truncated ...\n", .{});
416420 }
417421 }
418 differ.write(stderr.writer()) catch {};
422 differ.write(stderr.deprecatedWriter()) catch {};
419423 if (expected_truncated) {
420424 const end_offset = window_start + expected_window.len;
421425 const num_missing_items = expected.len - (window_start + expected_window.len);
......@@ -437,7 +441,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
437441 print("... truncated ...\n", .{});
438442 }
439443 }
440 differ.write(stderr.writer()) catch {};
444 differ.write(stderr.deprecatedWriter()) catch {};
441445 if (actual_truncated) {
442446 const end_offset = window_start + actual_window.len;
443447 const num_missing_items = actual.len - (window_start + actual_window.len);
......@@ -637,6 +641,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir {
637641
638642pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
639643 if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| {
644 if (@inComptime()) {
645 @compileError(std.fmt.comptimePrint("\nexpected:\n{s}\nfound:\n{s}\ndifference starts at index {d}", .{
646 expected, actual, diff_index,
647 }));
648 }
640649 print("\n====== expected this output: =========\n", .{});
641650 printWithVisibleNewlines(expected);
642651 print("\n======== instead found this: =========\n", .{});
......@@ -1108,7 +1117,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
11081117 const arg_i_str = comptime str: {
11091118 var str_buf: [100]u8 = undefined;
11101119 const args_i = i + 1;
1111 const str_len = std.fmt.formatIntBuf(&str_buf, args_i, 10, .lower, .{});
1120 const str_len = std.fmt.printInt(&str_buf, args_i, 10, .lower, .{});
11121121 break :str str_buf[0..str_len];
11131122 };
11141123 @field(args, arg_i_str) = @field(extra_args, field.name);
......@@ -1138,7 +1147,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
11381147 error.OutOfMemory => {
11391148 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
11401149 print(
1141 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {}",
1150 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}",
11421151 .{
11431152 fail_index,
11441153 needed_alloc_count,
lib/std/unicode.zig+23-36
......@@ -9,6 +9,7 @@ const native_endian = builtin.cpu.arch.endian();
99///
1010/// See also: https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character
1111pub const replacement_character: u21 = 0xFFFD;
12pub const replacement_character_utf8: [3]u8 = utf8EncodeComptime(replacement_character);
1213
1314/// Returns how many bytes the UTF-8 representation would require
1415/// for the given codepoint.
......@@ -802,14 +803,7 @@ fn testDecode(bytes: []const u8) !u21 {
802803/// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD)
803804/// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of
804805/// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder
805fn formatUtf8(
806 utf8: []const u8,
807 comptime fmt: []const u8,
808 options: std.fmt.FormatOptions,
809 writer: anytype,
810) !void {
811 _ = fmt;
812 _ = options;
806fn formatUtf8(utf8: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
813807 var buf: [300]u8 = undefined; // just an arbitrary size
814808 var u8len: usize = 0;
815809
......@@ -898,27 +892,27 @@ fn formatUtf8(
898892/// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD)
899893/// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of
900894/// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder
901pub fn fmtUtf8(utf8: []const u8) std.fmt.Formatter(formatUtf8) {
895pub fn fmtUtf8(utf8: []const u8) std.fmt.Formatter([]const u8, formatUtf8) {
902896 return .{ .data = utf8 };
903897}
904898
905899test fmtUtf8 {
906900 const expectFmt = testing.expectFmt;
907 try expectFmt("", "{}", .{fmtUtf8("")});
908 try expectFmt("foo", "{}", .{fmtUtf8("foo")});
909 try expectFmt("𐐷", "{}", .{fmtUtf8("𐐷")});
901 try expectFmt("", "{f}", .{fmtUtf8("")});
902 try expectFmt("foo", "{f}", .{fmtUtf8("foo")});
903 try expectFmt("𐐷", "{f}", .{fmtUtf8("𐐷")});
910904
911905 // Table 3-8. U+FFFD for Non-Shortest Form Sequences
912 try expectFmt("��������A", "{}", .{fmtUtf8("\xC0\xAF\xE0\x80\xBF\xF0\x81\x82A")});
906 try expectFmt("��������A", "{f}", .{fmtUtf8("\xC0\xAF\xE0\x80\xBF\xF0\x81\x82A")});
913907
914908 // Table 3-9. U+FFFD for Ill-Formed Sequences for Surrogates
915 try expectFmt("��������A", "{}", .{fmtUtf8("\xED\xA0\x80\xED\xBF\xBF\xED\xAFA")});
909 try expectFmt("��������A", "{f}", .{fmtUtf8("\xED\xA0\x80\xED\xBF\xBF\xED\xAFA")});
916910
917911 // Table 3-10. U+FFFD for Other Ill-Formed Sequences
918 try expectFmt("�����A��B", "{}", .{fmtUtf8("\xF4\x91\x92\x93\xFFA\x80\xBFB")});
912 try expectFmt("�����A��B", "{f}", .{fmtUtf8("\xF4\x91\x92\x93\xFFA\x80\xBFB")});
919913
920914 // Table 3-11. U+FFFD for Truncated Sequences
921 try expectFmt("����A", "{}", .{fmtUtf8("\xE1\x80\xE2\xF0\x91\x92\xF1\xBFA")});
915 try expectFmt("����A", "{f}", .{fmtUtf8("\xE1\x80\xE2\xF0\x91\x92\xF1\xBFA")});
922916}
923917
924918fn utf16LeToUtf8ArrayListImpl(
......@@ -1477,14 +1471,7 @@ test calcWtf16LeLen {
14771471
14781472/// Print the given `utf16le` string, encoded as UTF-8 bytes.
14791473/// Unpaired surrogates are replaced by the replacement character (U+FFFD).
1480fn formatUtf16Le(
1481 utf16le: []const u16,
1482 comptime fmt: []const u8,
1483 options: std.fmt.FormatOptions,
1484 writer: anytype,
1485) !void {
1486 _ = fmt;
1487 _ = options;
1474fn formatUtf16Le(utf16le: []const u16, writer: *std.io.Writer) std.io.Writer.Error!void {
14881475 var buf: [300]u8 = undefined; // just an arbitrary size
14891476 var it = Utf16LeIterator.init(utf16le);
14901477 var u8len: usize = 0;
......@@ -1505,23 +1492,23 @@ pub const fmtUtf16le = @compileError("deprecated; renamed to fmtUtf16Le");
15051492/// Return a Formatter for a (potentially ill-formed) UTF-16 LE string,
15061493/// which will be converted to UTF-8 during formatting.
15071494/// Unpaired surrogates are replaced by the replacement character (U+FFFD).
1508pub fn fmtUtf16Le(utf16le: []const u16) std.fmt.Formatter(formatUtf16Le) {
1495pub fn fmtUtf16Le(utf16le: []const u16) std.fmt.Formatter([]const u16, formatUtf16Le) {
15091496 return .{ .data = utf16le };
15101497}
15111498
15121499test fmtUtf16Le {
15131500 const expectFmt = testing.expectFmt;
1514 try expectFmt("", "{}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral(""))});
1515 try expectFmt("", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral(""))});
1516 try expectFmt("foo", "{}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral("foo"))});
1517 try expectFmt("foo", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("foo"))});
1518 try expectFmt("𐐷", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("𐐷"))});
1519 try expectFmt("퟿", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xd7", native_endian)})});
1520 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xd8", native_endian)})});
1521 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdb", native_endian)})});
1522 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xdc", native_endian)})});
1523 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdf", native_endian)})});
1524 try expectFmt("", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xe0", native_endian)})});
1501 try expectFmt("", "{f}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral(""))});
1502 try expectFmt("", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral(""))});
1503 try expectFmt("foo", "{f}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral("foo"))});
1504 try expectFmt("foo", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("foo"))});
1505 try expectFmt("𐐷", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("𐐷"))});
1506 try expectFmt("퟿", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xd7", native_endian)})});
1507 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xd8", native_endian)})});
1508 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdb", native_endian)})});
1509 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xdc", native_endian)})});
1510 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdf", native_endian)})});
1511 try expectFmt("", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xe0", native_endian)})});
15251512}
15261513
15271514fn testUtf8ToUtf16LeStringLiteral(utf8ToUtf16LeStringLiteral_: anytype) !void {
lib/std/unicode/throughput_test.zig+1-1
......@@ -39,7 +39,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
3939}
4040
4141pub fn main() !void {
42 const stdout = std.fs.File.stdout().writer();
42 const stdout = std.fs.File.stdout().deprecatedWriter();
4343
4444 try stdout.print("short ASCII strings\n", .{});
4545 {
lib/std/zig.zig+106-119
......@@ -363,149 +363,136 @@ const Allocator = std.mem.Allocator;
363363
364364/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.
365365///
366/// - An empty `{}` format specifier escapes invalid identifiers, identifiers that shadow primitives
367/// and the reserved `_` identifier.
368/// - Add `p` to the specifier to render identifiers that shadow primitives unescaped.
369/// - Add `_` to the specifier to render the reserved `_` identifier unescaped.
370/// - `p` and `_` can be combined, e.g. `{p_}`.
366/// See also `fmtIdFlags`.
367pub fn fmtId(bytes: []const u8) std.fmt.Formatter(FormatId, FormatId.render) {
368 return .{ .data = .{ .bytes = bytes, .flags = .{} } };
369}
370
371/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.
371372///
372pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) {
373 return .{ .data = bytes };
373/// See also `fmtId`.
374pub fn fmtIdFlags(bytes: []const u8, flags: FormatId.Flags) std.fmt.Formatter(FormatId, FormatId.render) {
375 return .{ .data = .{ .bytes = bytes, .flags = flags } };
376}
377
378pub fn fmtIdPU(bytes: []const u8) std.fmt.Formatter(FormatId, FormatId.render) {
379 return .{ .data = .{ .bytes = bytes, .flags = .{ .allow_primitive = true, .allow_underscore = true } } };
380}
381
382pub fn fmtIdP(bytes: []const u8) std.fmt.Formatter(FormatId, FormatId.render) {
383 return .{ .data = .{ .bytes = bytes, .flags = .{ .allow_primitive = true } } };
374384}
375385
376386test fmtId {
377387 const expectFmt = std.testing.expectFmt;
378 try expectFmt("@\"while\"", "{}", .{fmtId("while")});
379 try expectFmt("@\"while\"", "{p}", .{fmtId("while")});
380 try expectFmt("@\"while\"", "{_}", .{fmtId("while")});
381 try expectFmt("@\"while\"", "{p_}", .{fmtId("while")});
382 try expectFmt("@\"while\"", "{_p}", .{fmtId("while")});
383
384 try expectFmt("hello", "{}", .{fmtId("hello")});
385 try expectFmt("hello", "{p}", .{fmtId("hello")});
386 try expectFmt("hello", "{_}", .{fmtId("hello")});
387 try expectFmt("hello", "{p_}", .{fmtId("hello")});
388 try expectFmt("hello", "{_p}", .{fmtId("hello")});
389
390 try expectFmt("@\"type\"", "{}", .{fmtId("type")});
391 try expectFmt("type", "{p}", .{fmtId("type")});
392 try expectFmt("@\"type\"", "{_}", .{fmtId("type")});
393 try expectFmt("type", "{p_}", .{fmtId("type")});
394 try expectFmt("type", "{_p}", .{fmtId("type")});
395
396 try expectFmt("@\"_\"", "{}", .{fmtId("_")});
397 try expectFmt("@\"_\"", "{p}", .{fmtId("_")});
398 try expectFmt("_", "{_}", .{fmtId("_")});
399 try expectFmt("_", "{p_}", .{fmtId("_")});
400 try expectFmt("_", "{_p}", .{fmtId("_")});
401
402 try expectFmt("@\"i123\"", "{}", .{fmtId("i123")});
403 try expectFmt("i123", "{p}", .{fmtId("i123")});
404 try expectFmt("@\"4four\"", "{}", .{fmtId("4four")});
405 try expectFmt("_underscore", "{}", .{fmtId("_underscore")});
406 try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")});
407 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
388 try expectFmt("@\"while\"", "{f}", .{fmtId("while")});
389 try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_primitive = true })});
390 try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_underscore = true })});
391 try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_primitive = true, .allow_underscore = true })});
392
393 try expectFmt("hello", "{f}", .{fmtId("hello")});
394 try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_primitive = true })});
395 try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_underscore = true })});
396 try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_primitive = true, .allow_underscore = true })});
397
398 try expectFmt("@\"type\"", "{f}", .{fmtId("type")});
399 try expectFmt("type", "{f}", .{fmtIdFlags("type", .{ .allow_primitive = true })});
400 try expectFmt("@\"type\"", "{f}", .{fmtIdFlags("type", .{ .allow_underscore = true })});
401 try expectFmt("type", "{f}", .{fmtIdFlags("type", .{ .allow_primitive = true, .allow_underscore = true })});
402
403 try expectFmt("@\"_\"", "{f}", .{fmtId("_")});
404 try expectFmt("@\"_\"", "{f}", .{fmtIdFlags("_", .{ .allow_primitive = true })});
405 try expectFmt("_", "{f}", .{fmtIdFlags("_", .{ .allow_underscore = true })});
406 try expectFmt("_", "{f}", .{fmtIdFlags("_", .{ .allow_primitive = true, .allow_underscore = true })});
407
408 try expectFmt("@\"i123\"", "{f}", .{fmtId("i123")});
409 try expectFmt("i123", "{f}", .{fmtIdFlags("i123", .{ .allow_primitive = true })});
410 try expectFmt("@\"4four\"", "{f}", .{fmtId("4four")});
411 try expectFmt("_underscore", "{f}", .{fmtId("_underscore")});
412 try expectFmt("@\"11\\\"23\"", "{f}", .{fmtId("11\"23")});
413 try expectFmt("@\"11\\x0f23\"", "{f}", .{fmtId("11\x0F23")});
408414
409415 // These are technically not currently legal in Zig.
410 try expectFmt("@\"\"", "{}", .{fmtId("")});
411 try expectFmt("@\"\\x00\"", "{}", .{fmtId("\x00")});
416 try expectFmt("@\"\"", "{f}", .{fmtId("")});
417 try expectFmt("@\"\\x00\"", "{f}", .{fmtId("\x00")});
412418}
413419
414/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
415fn formatId(
420pub const FormatId = struct {
416421 bytes: []const u8,
417 comptime fmt: []const u8,
418 options: std.fmt.FormatOptions,
419 writer: anytype,
420) !void {
421 const allow_primitive, const allow_underscore = comptime parse_fmt: {
422 var allow_primitive = false;
423 var allow_underscore = false;
424 for (fmt) |char| {
425 switch (char) {
426 'p' => if (!allow_primitive) {
427 allow_primitive = true;
428 continue;
429 },
430 '_' => if (!allow_underscore) {
431 allow_underscore = true;
432 continue;
433 },
434 else => {},
435 }
436 @compileError("expected {}, {p}, {_}, {p_} or {_p}, found {" ++ fmt ++ "}");
437 }
438 break :parse_fmt .{ allow_primitive, allow_underscore };
422 flags: Flags,
423 pub const Flags = struct {
424 allow_primitive: bool = false,
425 allow_underscore: bool = false,
439426 };
440427
441 if (isValidId(bytes) and
442 (allow_primitive or !std.zig.isPrimitive(bytes)) and
443 (allow_underscore or !isUnderscore(bytes)))
444 {
445 return writer.writeAll(bytes);
428 /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
429 fn render(ctx: FormatId, writer: *std.io.Writer) std.io.Writer.Error!void {
430 const bytes = ctx.bytes;
431 if (isValidId(bytes) and
432 (ctx.flags.allow_primitive or !std.zig.isPrimitive(bytes)) and
433 (ctx.flags.allow_underscore or !isUnderscore(bytes)))
434 {
435 return writer.writeAll(bytes);
436 }
437 try writer.writeAll("@\"");
438 try stringEscape(bytes, writer);
439 try writer.writeByte('"');
446440 }
447 try writer.writeAll("@\"");
448 try stringEscape(bytes, "", options, writer);
449 try writer.writeByte('"');
441};
442
443/// Return a formatter for escaping a double quoted Zig string.
444pub fn fmtString(bytes: []const u8) std.fmt.Formatter([]const u8, stringEscape) {
445 return .{ .data = bytes };
450446}
451447
452/// Return a Formatter for Zig Escapes of a double quoted string.
453/// The format specifier must be one of:
454/// * `{}` treats contents as a double-quoted string.
455/// * `{'}` treats contents as a single-quoted string.
456pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(stringEscape) {
448/// Return a formatter for escaping a single quoted Zig string.
449pub fn fmtChar(bytes: []const u8) std.fmt.Formatter([]const u8, charEscape) {
457450 return .{ .data = bytes };
458451}
459452
460test fmtEscapes {
461 const expectFmt = std.testing.expectFmt;
462 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
463 try expectFmt(
464 \\" \\ hi \x07 \x11 " derp \'"
465 , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
466 try expectFmt(
453test fmtString {
454 try std.testing.expectFmt("\\x0f", "{f}", .{fmtString("\x0f")});
455 try std.testing.expectFmt(
467456 \\" \\ hi \x07 \x11 \" derp '"
468 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
457 , "\"{f}\"", .{fmtString(" \\ hi \x07 \x11 \" derp '")});
469458}
470459
471/// Print the string as escaped contents of a double quoted or single-quoted string.
472/// Format `{}` treats contents as a double-quoted string.
473/// Format `{'}` treats contents as a single-quoted string.
474pub fn stringEscape(
475 bytes: []const u8,
476 comptime f: []const u8,
477 options: std.fmt.FormatOptions,
478 writer: anytype,
479) !void {
480 _ = options;
460test fmtChar {
461 try std.testing.expectFmt(
462 \\" \\ hi \x07 \x11 " derp \'"
463 , "\"{f}\"", .{fmtChar(" \\ hi \x07 \x11 \" derp '")});
464}
465
466/// Print the string as escaped contents of a double quoted string.
467pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
481468 for (bytes) |byte| switch (byte) {
482 '\n' => try writer.writeAll("\\n"),
483 '\r' => try writer.writeAll("\\r"),
484 '\t' => try writer.writeAll("\\t"),
485 '\\' => try writer.writeAll("\\\\"),
486 '"' => {
487 if (f.len == 1 and f[0] == '\'') {
488 try writer.writeByte('"');
489 } else if (f.len == 0) {
490 try writer.writeAll("\\\"");
491 } else {
492 @compileError("expected {} or {'}, found {" ++ f ++ "}");
493 }
494 },
495 '\'' => {
496 if (f.len == 1 and f[0] == '\'') {
497 try writer.writeAll("\\'");
498 } else if (f.len == 0) {
499 try writer.writeByte('\'');
500 } else {
501 @compileError("expected {} or {'}, found {" ++ f ++ "}");
502 }
469 '\n' => try w.writeAll("\\n"),
470 '\r' => try w.writeAll("\\r"),
471 '\t' => try w.writeAll("\\t"),
472 '\\' => try w.writeAll("\\\\"),
473 '"' => try w.writeAll("\\\""),
474 '\'' => try w.writeByte('\''),
475 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
476 else => {
477 try w.writeAll("\\x");
478 try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });
503479 },
504 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),
505 // Use hex escapes for rest any unprintable characters.
480 };
481}
482
483/// Print the string as escaped contents of a single-quoted string.
484pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
485 for (bytes) |byte| switch (byte) {
486 '\n' => try w.writeAll("\\n"),
487 '\r' => try w.writeAll("\\r"),
488 '\t' => try w.writeAll("\\t"),
489 '\\' => try w.writeAll("\\\\"),
490 '"' => try w.writeByte('"'),
491 '\'' => try w.writeAll("\\'"),
492 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
506493 else => {
507 try writer.writeAll("\\x");
508 try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, writer);
494 try w.writeAll("\\x");
495 try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });
509496 },
510497 };
511498}
lib/std/zig/Ast.zig+2-2
......@@ -565,14 +565,14 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
565565
566566 .invalid_byte => {
567567 const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];
568 return stream.print("{s} contains invalid byte: '{'}'", .{
568 return stream.print("{s} contains invalid byte: '{f}'", .{
569569 switch (tok_slice[0]) {
570570 '\'' => "character literal",
571571 '"', '\\' => "string literal",
572572 '/' => "comment",
573573 else => unreachable,
574574 },
575 std.zig.fmtEscapes(tok_slice[parse_error.extra.offset..][0..1]),
575 std.zig.fmtChar(tok_slice[parse_error.extra.offset..][0..1]),
576576 });
577577 },
578578
lib/std/zig/ErrorBundle.zig+1-1
......@@ -165,7 +165,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {
165165 std.debug.lockStdErr();
166166 defer std.debug.unlockStdErr();
167167 const stderr: std.fs.File = .stderr();
168 return renderToWriter(eb, options, stderr.writer()) catch return;
168 return renderToWriter(eb, options, stderr.deprecatedWriter()) catch return;
169169}
170170
171171pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void {
lib/std/zig/ZonGen.zig+1-7
......@@ -756,13 +756,7 @@ fn lowerStrLitError(
756756 raw_string: []const u8,
757757 offset: u32,
758758) Allocator.Error!void {
759 return ZonGen.addErrorTokOff(
760 zg,
761 token,
762 @intCast(offset + err.offset()),
763 "{}",
764 .{err.fmt(raw_string)},
765 );
759 return ZonGen.addErrorTokOff(zg, token, @intCast(offset + err.offset()), "{f}", .{err.fmt(raw_string)});
766760}
767761
768762fn lowerNumberError(zg: *ZonGen, err: std.zig.number_literal.Error, token: Ast.TokenIndex, bytes: []const u8) Allocator.Error!void {
lib/std/zig/llvm/Builder.zig+435-597
......@@ -1,3 +1,14 @@
1const std = @import("../../std.zig");
2const Allocator = std.mem.Allocator;
3const assert = std.debug.assert;
4const bitcode_writer = @import("bitcode_writer.zig");
5const Builder = @This();
6const builtin = @import("builtin");
7const DW = std.dwarf;
8const ir = @import("ir.zig");
9const log = std.log.scoped(.llvm);
10const Writer = std.io.Writer;
11
112gpa: Allocator,
213strip: bool,
314
......@@ -90,31 +101,25 @@ pub const String = enum(u32) {
90101 const FormatData = struct {
91102 string: String,
92103 builder: *const Builder,
104 quote_behavior: ?QuoteBehavior,
93105 };
94 fn format(
95 data: FormatData,
96 comptime fmt_str: []const u8,
97 _: std.fmt.FormatOptions,
98 writer: anytype,
99 ) @TypeOf(writer).Error!void {
100 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
101 @compileError("invalid format string: '" ++ fmt_str ++ "'");
106 fn format(data: FormatData, w: *Writer) Writer.Error!void {
102107 assert(data.string != .none);
103108 const string_slice = data.string.slice(data.builder) orelse
104 return writer.print("{d}", .{@intFromEnum(data.string)});
105 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
106 return writer.writeAll(string_slice);
107 try printEscapedString(
108 string_slice,
109 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
110 .always_quote
111 else
112 .quote_unless_valid_identifier,
113 writer,
114 );
109 return w.print("{d}", .{@intFromEnum(data.string)});
110 const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice);
111 return printEscapedString(string_slice, quote_behavior, w);
115112 }
116 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {
117 return .{ .data = .{ .string = self, .builder = builder } };
113 pub fn fmt(
114 self: String,
115 builder: *const Builder,
116 quote_behavior: ?QuoteBehavior,
117 ) std.fmt.Formatter(FormatData, format) {
118 return .{ .data = .{
119 .string = self,
120 .builder = builder,
121 .quote_behavior = quote_behavior,
122 } };
118123 }
119124
120125 fn fromIndex(index: ?usize) String {
......@@ -228,7 +233,7 @@ pub const Type = enum(u32) {
228233 _,
229234
230235 pub const ptr_amdgpu_constant =
231 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
236 @field(Type, std.fmt.comptimePrint("ptr{f }", .{AddrSpace.amdgpu.constant}));
232237
233238 pub const Tag = enum(u4) {
234239 simple,
......@@ -653,18 +658,16 @@ pub const Type = enum(u32) {
653658 const FormatData = struct {
654659 type: Type,
655660 builder: *const Builder,
661 mode: Mode,
662
663 const Mode = enum { default, m, lt, gt, percent };
656664 };
657 fn format(
658 data: FormatData,
659 comptime fmt_str: []const u8,
660 fmt_opts: std.fmt.FormatOptions,
661 writer: anytype,
662 ) @TypeOf(writer).Error!void {
665 fn format(data: FormatData, w: *Writer) Writer.Error!void {
663666 assert(data.type != .none);
664 if (comptime std.mem.eql(u8, fmt_str, "m")) {
667 if (data.mode == .m) {
665668 const item = data.builder.type_items.items[@intFromEnum(data.type)];
666669 switch (item.tag) {
667 .simple => try writer.writeAll(switch (@as(Simple, @enumFromInt(item.data))) {
670 .simple => try w.writeAll(switch (@as(Simple, @enumFromInt(item.data))) {
668671 .void => "isVoid",
669672 .half => "f16",
670673 .bfloat => "bf16",
......@@ -681,29 +684,29 @@ pub const Type = enum(u32) {
681684 .function, .vararg_function => |kind| {
682685 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
683686 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
684 try writer.print("f_{m}", .{extra.data.ret.fmt(data.builder)});
685 for (params) |param| try writer.print("{m}", .{param.fmt(data.builder)});
687 try w.print("f_{fm}", .{extra.data.ret.fmt(data.builder)});
688 for (params) |param| try w.print("{fm}", .{param.fmt(data.builder)});
686689 switch (kind) {
687690 .function => {},
688 .vararg_function => try writer.writeAll("vararg"),
691 .vararg_function => try w.writeAll("vararg"),
689692 else => unreachable,
690693 }
691 try writer.writeByte('f');
694 try w.writeByte('f');
692695 },
693 .integer => try writer.print("i{d}", .{item.data}),
694 .pointer => try writer.print("p{d}", .{item.data}),
696 .integer => try w.print("i{d}", .{item.data}),
697 .pointer => try w.print("p{d}", .{item.data}),
695698 .target => {
696699 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
697700 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
698701 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
699 try writer.print("t{s}", .{extra.data.name.slice(data.builder).?});
700 for (types) |ty| try writer.print("_{m}", .{ty.fmt(data.builder)});
701 for (ints) |int| try writer.print("_{d}", .{int});
702 try writer.writeByte('t');
702 try w.print("t{s}", .{extra.data.name.slice(data.builder).?});
703 for (types) |ty| try w.print("_{fm}", .{ty.fmt(data.builder)});
704 for (ints) |int| try w.print("_{d}", .{int});
705 try w.writeByte('t');
703706 },
704707 .vector, .scalable_vector => |kind| {
705708 const extra = data.builder.typeExtraData(Type.Vector, item.data);
706 try writer.print("{s}v{d}{m}", .{
709 try w.print("{s}v{d}{fm}", .{
707710 switch (kind) {
708711 .vector => "",
709712 .scalable_vector => "nx",
......@@ -719,65 +722,65 @@ pub const Type = enum(u32) {
719722 .array => Type.Array,
720723 else => unreachable,
721724 }, item.data);
722 try writer.print("a{d}{m}", .{ extra.length(), extra.child.fmt(data.builder) });
725 try w.print("a{d}{fm}", .{ extra.length(), extra.child.fmt(data.builder) });
723726 },
724727 .structure, .packed_structure => {
725728 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
726729 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
727 try writer.writeAll("sl_");
728 for (fields) |field| try writer.print("{m}", .{field.fmt(data.builder)});
729 try writer.writeByte('s');
730 try w.writeAll("sl_");
731 for (fields) |field| try w.print("{fm}", .{field.fmt(data.builder)});
732 try w.writeByte('s');
730733 },
731734 .named_structure => {
732735 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
733 try writer.writeAll("s_");
734 if (extra.id.slice(data.builder)) |id| try writer.writeAll(id);
736 try w.writeAll("s_");
737 if (extra.id.slice(data.builder)) |id| try w.writeAll(id);
735738 },
736739 }
737740 return;
738741 }
739 if (std.enums.tagName(Type, data.type)) |name| return writer.writeAll(name);
742 if (std.enums.tagName(Type, data.type)) |name| return w.writeAll(name);
740743 const item = data.builder.type_items.items[@intFromEnum(data.type)];
741744 switch (item.tag) {
742745 .simple => unreachable,
743746 .function, .vararg_function => |kind| {
744747 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
745748 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
746 if (!comptime std.mem.eql(u8, fmt_str, ">"))
747 try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)});
748 if (!comptime std.mem.eql(u8, fmt_str, "<")) {
749 try writer.writeByte('(');
749 if (data.mode != .gt)
750 try w.print("{f%} ", .{extra.data.ret.fmt(data.builder)});
751 if (data.mode != .lt) {
752 try w.writeByte('(');
750753 for (params, 0..) |param, index| {
751 if (index > 0) try writer.writeAll(", ");
752 try writer.print("{%}", .{param.fmt(data.builder)});
754 if (index > 0) try w.writeAll(", ");
755 try w.print("{f%}", .{param.fmt(data.builder)});
753756 }
754757 switch (kind) {
755758 .function => {},
756759 .vararg_function => {
757 if (params.len > 0) try writer.writeAll(", ");
758 try writer.writeAll("...");
760 if (params.len > 0) try w.writeAll(", ");
761 try w.writeAll("...");
759762 },
760763 else => unreachable,
761764 }
762 try writer.writeByte(')');
765 try w.writeByte(')');
763766 }
764767 },
765 .integer => try writer.print("i{d}", .{item.data}),
766 .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}),
768 .integer => try w.print("i{d}", .{item.data}),
769 .pointer => try w.print("ptr{f }", .{@as(AddrSpace, @enumFromInt(item.data))}),
767770 .target => {
768771 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
769772 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
770773 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
771 try writer.print(
772 \\target({"}
774 try w.print(
775 \\target({f"}
773776 , .{extra.data.name.fmt(data.builder)});
774 for (types) |ty| try writer.print(", {%}", .{ty.fmt(data.builder)});
775 for (ints) |int| try writer.print(", {d}", .{int});
776 try writer.writeByte(')');
777 for (types) |ty| try w.print(", {f%}", .{ty.fmt(data.builder)});
778 for (ints) |int| try w.print(", {d}", .{int});
779 try w.writeByte(')');
777780 },
778781 .vector, .scalable_vector => |kind| {
779782 const extra = data.builder.typeExtraData(Type.Vector, item.data);
780 try writer.print("<{s}{d} x {%}>", .{
783 try w.print("<{s}{d} x {f%}>", .{
781784 switch (kind) {
782785 .vector => "",
783786 .scalable_vector => "vscale x ",
......@@ -793,44 +796,45 @@ pub const Type = enum(u32) {
793796 .array => Type.Array,
794797 else => unreachable,
795798 }, item.data);
796 try writer.print("[{d} x {%}]", .{ extra.length(), extra.child.fmt(data.builder) });
799 try w.print("[{d} x {f%}]", .{ extra.length(), extra.child.fmt(data.builder) });
797800 },
798801 .structure, .packed_structure => |kind| {
799802 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
800803 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
801804 switch (kind) {
802805 .structure => {},
803 .packed_structure => try writer.writeByte('<'),
806 .packed_structure => try w.writeByte('<'),
804807 else => unreachable,
805808 }
806 try writer.writeAll("{ ");
809 try w.writeAll("{ ");
807810 for (fields, 0..) |field, index| {
808 if (index > 0) try writer.writeAll(", ");
809 try writer.print("{%}", .{field.fmt(data.builder)});
811 if (index > 0) try w.writeAll(", ");
812 try w.print("{f%}", .{field.fmt(data.builder)});
810813 }
811 try writer.writeAll(" }");
814 try w.writeAll(" }");
812815 switch (kind) {
813816 .structure => {},
814 .packed_structure => try writer.writeByte('>'),
817 .packed_structure => try w.writeByte('>'),
815818 else => unreachable,
816819 }
817820 },
818821 .named_structure => {
819822 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
820 if (comptime std.mem.eql(u8, fmt_str, "%")) try writer.print("%{}", .{
823 if (data.mode == .percent) try w.print("%{f}", .{
821824 extra.id.fmt(data.builder),
822825 }) else switch (extra.body) {
823 .none => try writer.writeAll("opaque"),
826 .none => try w.writeAll("opaque"),
824827 else => try format(.{
825828 .type = extra.body,
826829 .builder = data.builder,
827 }, fmt_str, fmt_opts, writer),
830 .mode = data.mode,
831 }, w),
828832 }
829833 },
830834 }
831835 }
832 pub fn fmt(self: Type, builder: *const Builder) std.fmt.Formatter(format) {
833 return .{ .data = .{ .type = self, .builder = builder } };
836 pub fn fmt(self: Type, builder: *const Builder, mode: FormatData.Mode) std.fmt.Formatter(FormatData, format) {
837 return .{ .data = .{ .type = self, .builder = builder, .mode = mode } };
834838 }
835839
836840 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);
......@@ -1138,15 +1142,10 @@ pub const Attribute = union(Kind) {
11381142 const FormatData = struct {
11391143 attribute_index: Index,
11401144 builder: *const Builder,
1145 mode: Mode,
1146 const Mode = enum { default, quote, pound };
11411147 };
1142 fn format(
1143 data: FormatData,
1144 comptime fmt_str: []const u8,
1145 _: std.fmt.FormatOptions,
1146 writer: anytype,
1147 ) @TypeOf(writer).Error!void {
1148 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_|
1149 @compileError("invalid format string: '" ++ fmt_str ++ "'");
1148 fn format(data: FormatData, w: *Writer) Writer.Error!void {
11501149 const attribute = data.attribute_index.toAttribute(data.builder);
11511150 switch (attribute) {
11521151 .zeroext,
......@@ -1219,97 +1218,94 @@ pub const Attribute = union(Kind) {
12191218 .no_sanitize_address,
12201219 .no_sanitize_hwaddress,
12211220 .sanitize_address_dyninit,
1222 => try writer.print(" {s}", .{@tagName(attribute)}),
1221 => try w.print(" {s}", .{@tagName(attribute)}),
12231222 .byval,
12241223 .byref,
12251224 .preallocated,
12261225 .inalloca,
12271226 .sret,
12281227 .elementtype,
1229 => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),
1230 .@"align" => |alignment| try writer.print("{ }", .{alignment}),
1228 => |ty| try w.print(" {s}({f%})", .{ @tagName(attribute), ty.fmt(data.builder) }),
1229 .@"align" => |alignment| try w.print("{f }", .{alignment}),
12311230 .dereferenceable,
12321231 .dereferenceable_or_null,
1233 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),
1232 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
12341233 .nofpclass => |fpclass| {
12351234 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
1236 try writer.print(" {s}(", .{@tagName(attribute)});
1235 try w.print(" {s}(", .{@tagName(attribute)});
12371236 var any = false;
12381237 var remaining: Int = @bitCast(fpclass);
12391238 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {
12401239 const pattern: Int = @bitCast(@field(FpClass, decl.name));
12411240 if (remaining & pattern == pattern) {
12421241 if (!any) {
1243 try writer.writeByte(' ');
1242 try w.writeByte(' ');
12441243 any = true;
12451244 }
1246 try writer.writeAll(decl.name);
1245 try w.writeAll(decl.name);
12471246 remaining &= ~pattern;
12481247 }
12491248 }
1250 try writer.writeByte(')');
1249 try w.writeByte(')');
12511250 },
1252 .alignstack => |alignment| try writer.print(
1253 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)
1254 " {s}={d}"
1255 else
1256 " {s}({d})",
1251 .alignstack => |alignment| try w.print(
1252 if (data.mode == .pound) " {s}={d}" else " {s}({d})",
12571253 .{ @tagName(attribute), alignment.toByteUnits() orelse return },
12581254 ),
12591255 .allockind => |allockind| {
1260 try writer.print(" {s}(\"", .{@tagName(attribute)});
1256 try w.print(" {s}(\"", .{@tagName(attribute)});
12611257 var any = false;
12621258 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {
12631259 if (comptime std.mem.eql(u8, field.name, "_")) continue;
12641260 if (@field(allockind, field.name)) {
12651261 if (!any) {
1266 try writer.writeByte(',');
1262 try w.writeByte(',');
12671263 any = true;
12681264 }
1269 try writer.writeAll(field.name);
1265 try w.writeAll(field.name);
12701266 }
12711267 }
1272 try writer.writeAll("\")");
1268 try w.writeAll("\")");
12731269 },
12741270 .allocsize => |allocsize| {
1275 try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
1271 try w.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
12761272 if (allocsize.num_elems != AllocSize.none)
1277 try writer.print(",{d}", .{allocsize.num_elems});
1278 try writer.writeByte(')');
1273 try w.print(",{d}", .{allocsize.num_elems});
1274 try w.writeByte(')');
12791275 },
12801276 .memory => |memory| {
1281 try writer.print(" {s}(", .{@tagName(attribute)});
1277 try w.print(" {s}(", .{@tagName(attribute)});
12821278 var any = memory.other != .none or
12831279 (memory.argmem == .none and memory.inaccessiblemem == .none);
1284 if (any) try writer.writeAll(@tagName(memory.other));
1280 if (any) try w.writeAll(@tagName(memory.other));
12851281 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
12861282 if (@field(memory, kind) != memory.other) {
1287 if (any) try writer.writeAll(", ");
1288 try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
1283 if (any) try w.writeAll(", ");
1284 try w.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
12891285 any = true;
12901286 }
12911287 }
1292 try writer.writeByte(')');
1288 try w.writeByte(')');
12931289 },
12941290 .uwtable => |uwtable| if (uwtable != .none) {
1295 try writer.print(" {s}", .{@tagName(attribute)});
1296 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});
1291 try w.print(" {s}", .{@tagName(attribute)});
1292 if (uwtable != UwTable.default) try w.print("({s})", .{@tagName(uwtable)});
12971293 },
1298 .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{
1294 .vscale_range => |vscale_range| try w.print(" {s}({d},{d})", .{
12991295 @tagName(attribute),
13001296 vscale_range.min.toByteUnits().?,
13011297 vscale_range.max.toByteUnits() orelse 0,
13021298 }),
1303 .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) {
1304 try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)});
1299 .string => |string_attr| if (data.mode == .quote) {
1300 try w.print(" {f\"}", .{string_attr.kind.fmt(data.builder)});
13051301 if (string_attr.value != .empty)
1306 try writer.print("={\"}", .{string_attr.value.fmt(data.builder)});
1302 try w.print("={f\"}", .{string_attr.value.fmt(data.builder)});
13071303 },
13081304 .none => unreachable,
13091305 }
13101306 }
1311 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {
1312 return .{ .data = .{ .attribute_index = self, .builder = builder } };
1307 pub fn fmt(self: Index, builder: *const Builder, mode: FormatData.mode) std.fmt.Formatter(FormatData, format) {
1308 return .{ .data = .{ .attribute_index = self, .builder = builder, .mode = mode } };
13131309 }
13141310
13151311 fn toStorage(self: Index, builder: *const Builder) Storage {
......@@ -1583,18 +1579,13 @@ pub const Attributes = enum(u32) {
15831579 attributes: Attributes,
15841580 builder: *const Builder,
15851581 };
1586 fn format(
1587 data: FormatData,
1588 comptime fmt_str: []const u8,
1589 fmt_opts: std.fmt.FormatOptions,
1590 writer: anytype,
1591 ) @TypeOf(writer).Error!void {
1582 fn format(data: FormatData, w: *Writer) Writer.Error!void {
15921583 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{
15931584 .attribute_index = attribute_index,
15941585 .builder = data.builder,
1595 }, fmt_str, fmt_opts, writer);
1586 }, w);
15961587 }
1597 pub fn fmt(self: Attributes, builder: *const Builder) std.fmt.Formatter(format) {
1588 pub fn fmt(self: Attributes, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
15981589 return .{ .data = .{ .attributes = self, .builder = builder } };
15991590 }
16001591};
......@@ -1781,24 +1772,15 @@ pub const Linkage = enum(u4) {
17811772 extern_weak = 7,
17821773 external = 0,
17831774
1784 pub fn format(
1785 self: Linkage,
1786 comptime _: []const u8,
1787 _: std.fmt.FormatOptions,
1788 writer: anytype,
1789 ) @TypeOf(writer).Error!void {
1790 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1775 pub fn format(self: Linkage, w: *Writer, comptime f: []const u8) Writer.Error!void {
1776 comptime assert(f.len == 0);
1777 if (self != .external) try w.print(" {s}", .{@tagName(self)});
17911778 }
17921779
1793 fn formatOptional(
1794 data: ?Linkage,
1795 comptime _: []const u8,
1796 _: std.fmt.FormatOptions,
1797 writer: anytype,
1798 ) @TypeOf(writer).Error!void {
1799 if (data) |linkage| try writer.print(" {s}", .{@tagName(linkage)});
1780 fn formatOptional(data: ?Linkage, w: *Writer) Writer.Error!void {
1781 if (data) |linkage| try w.print(" {s}", .{@tagName(linkage)});
18001782 }
1801 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {
1783 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(?Linkage, formatOptional) {
18021784 return .{ .data = self };
18031785 }
18041786};
......@@ -1808,13 +1790,8 @@ pub const Preemption = enum {
18081790 dso_local,
18091791 implicit_dso_local,
18101792
1811 pub fn format(
1812 self: Preemption,
1813 comptime _: []const u8,
1814 _: std.fmt.FormatOptions,
1815 writer: anytype,
1816 ) @TypeOf(writer).Error!void {
1817 if (self == .dso_local) try writer.print(" {s}", .{@tagName(self)});
1793 pub fn format(self: Preemption, w: *Writer, comptime _: []const u8) Writer.Error!void {
1794 if (self == .dso_local) try w.print(" {s}", .{@tagName(self)});
18181795 }
18191796};
18201797
......@@ -1831,12 +1808,8 @@ pub const Visibility = enum(u2) {
18311808 };
18321809 }
18331810
1834 pub fn format(
1835 self: Visibility,
1836 comptime _: []const u8,
1837 _: std.fmt.FormatOptions,
1838 writer: anytype,
1839 ) @TypeOf(writer).Error!void {
1811 pub fn format(self: Visibility, comptime format_string: []const u8, writer: *Writer) Writer.Error!void {
1812 comptime assert(format_string.len == 0);
18401813 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
18411814 }
18421815};
......@@ -1846,13 +1819,8 @@ pub const DllStorageClass = enum(u2) {
18461819 dllimport = 1,
18471820 dllexport = 2,
18481821
1849 pub fn format(
1850 self: DllStorageClass,
1851 comptime _: []const u8,
1852 _: std.fmt.FormatOptions,
1853 writer: anytype,
1854 ) @TypeOf(writer).Error!void {
1855 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1822 pub fn format(self: DllStorageClass, w: *Writer, comptime _: []const u8) Writer.Error!void {
1823 if (self != .default) try w.print(" {s}", .{@tagName(self)});
18561824 }
18571825};
18581826
......@@ -1863,15 +1831,10 @@ pub const ThreadLocal = enum(u3) {
18631831 initialexec = 3,
18641832 localexec = 4,
18651833
1866 pub fn format(
1867 self: ThreadLocal,
1868 comptime prefix: []const u8,
1869 _: std.fmt.FormatOptions,
1870 writer: anytype,
1871 ) @TypeOf(writer).Error!void {
1834 pub fn format(self: ThreadLocal, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
18721835 if (self == .default) return;
1873 try writer.print("{s}thread_local", .{prefix});
1874 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});
1836 try w.print("{s}thread_local", .{prefix});
1837 if (self != .generaldynamic) try w.print("({s})", .{@tagName(self)});
18751838 }
18761839};
18771840
......@@ -1882,13 +1845,8 @@ pub const UnnamedAddr = enum(u2) {
18821845 unnamed_addr = 1,
18831846 local_unnamed_addr = 2,
18841847
1885 pub fn format(
1886 self: UnnamedAddr,
1887 comptime _: []const u8,
1888 _: std.fmt.FormatOptions,
1889 writer: anytype,
1890 ) @TypeOf(writer).Error!void {
1891 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1848 pub fn format(self: UnnamedAddr, w: *Writer, comptime _: []const u8) Writer.Error!void {
1849 if (self != .default) try w.print(" {s}", .{@tagName(self)});
18921850 }
18931851};
18941852
......@@ -1981,13 +1939,8 @@ pub const AddrSpace = enum(u24) {
19811939 pub const funcref: AddrSpace = @enumFromInt(20);
19821940 };
19831941
1984 pub fn format(
1985 self: AddrSpace,
1986 comptime prefix: []const u8,
1987 _: std.fmt.FormatOptions,
1988 writer: anytype,
1989 ) @TypeOf(writer).Error!void {
1990 if (self != .default) try writer.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
1942 pub fn format(self: AddrSpace, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
1943 if (self != .default) try w.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
19911944 }
19921945};
19931946
......@@ -1995,15 +1948,8 @@ pub const ExternallyInitialized = enum {
19951948 default,
19961949 externally_initialized,
19971950
1998 pub fn format(
1999 self: ExternallyInitialized,
2000 comptime _: []const u8,
2001 _: std.fmt.FormatOptions,
2002 writer: anytype,
2003 ) @TypeOf(writer).Error!void {
2004 if (self == .default) return;
2005 try writer.writeByte(' ');
2006 try writer.writeAll(@tagName(self));
1951 pub fn format(self: ExternallyInitialized, w: *Writer, comptime _: []const u8) Writer.Error!void {
1952 if (self != .default) try w.print(" {s}", .{@tagName(self)});
20071953 }
20081954};
20091955
......@@ -2026,13 +1972,8 @@ pub const Alignment = enum(u6) {
20261972 return if (self == .default) 0 else (@intFromEnum(self) + 1);
20271973 }
20281974
2029 pub fn format(
2030 self: Alignment,
2031 comptime prefix: []const u8,
2032 _: std.fmt.FormatOptions,
2033 writer: anytype,
2034 ) @TypeOf(writer).Error!void {
2035 try writer.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
1975 pub fn format(self: Alignment, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
1976 try w.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
20361977 }
20371978};
20381979
......@@ -2105,12 +2046,7 @@ pub const CallConv = enum(u10) {
21052046
21062047 pub const default = CallConv.ccc;
21072048
2108 pub fn format(
2109 self: CallConv,
2110 comptime _: []const u8,
2111 _: std.fmt.FormatOptions,
2112 writer: anytype,
2113 ) @TypeOf(writer).Error!void {
2049 pub fn format(self: CallConv, w: *Writer, comptime _: []const u8) Writer.Error!void {
21142050 switch (self) {
21152051 default => {},
21162052 .fastcc,
......@@ -2164,8 +2100,8 @@ pub const CallConv = enum(u10) {
21642100 .aarch64_sme_preservemost_from_x2,
21652101 .m68k_rtdcc,
21662102 .riscv_vectorcallcc,
2167 => try writer.print(" {s}", .{@tagName(self)}),
2168 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
2103 => try w.print(" {s}", .{@tagName(self)}),
2104 _ => try w.print(" cc{d}", .{@intFromEnum(self)}),
21692105 }
21702106 }
21712107};
......@@ -2190,31 +2126,25 @@ pub const StrtabString = enum(u32) {
21902126 const FormatData = struct {
21912127 string: StrtabString,
21922128 builder: *const Builder,
2129 quote_behavior: ?QuoteBehavior,
21932130 };
2194 fn format(
2195 data: FormatData,
2196 comptime fmt_str: []const u8,
2197 _: std.fmt.FormatOptions,
2198 writer: anytype,
2199 ) @TypeOf(writer).Error!void {
2200 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
2201 @compileError("invalid format string: '" ++ fmt_str ++ "'");
2131 fn format(data: FormatData, w: *Writer) Writer.Error!void {
22022132 assert(data.string != .none);
22032133 const string_slice = data.string.slice(data.builder) orelse
2204 return writer.print("{d}", .{@intFromEnum(data.string)});
2205 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
2206 return writer.writeAll(string_slice);
2207 try printEscapedString(
2208 string_slice,
2209 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
2210 .always_quote
2211 else
2212 .quote_unless_valid_identifier,
2213 writer,
2214 );
2134 return w.print("{d}", .{@intFromEnum(data.string)});
2135 const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice);
2136 return printEscapedString(string_slice, quote_behavior, w);
22152137 }
2216 pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) {
2217 return .{ .data = .{ .string = self, .builder = builder } };
2138 pub fn fmt(
2139 self: StrtabString,
2140 builder: *const Builder,
2141 quote_behavior: ?QuoteBehavior,
2142 ) std.fmt.Formatter(FormatData, format) {
2143 return .{ .data = .{
2144 .string = self,
2145 .builder = builder,
2146 .quote_behavior = quote_behavior,
2147 } };
22182148 }
22192149
22202150 fn fromIndex(index: ?usize) StrtabString {
......@@ -2264,7 +2194,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a
22642194}
22652195
22662196pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString {
2267 self.strtab_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
2197 self.strtab_string_bytes.printAssumeCapacity(fmt_str, fmt_args);
22682198 return self.trailingStrtabStringAssumeCapacity();
22692199}
22702200
......@@ -2383,17 +2313,12 @@ pub const Global = struct {
23832313 global: Index,
23842314 builder: *const Builder,
23852315 };
2386 fn format(
2387 data: FormatData,
2388 comptime _: []const u8,
2389 _: std.fmt.FormatOptions,
2390 writer: anytype,
2391 ) @TypeOf(writer).Error!void {
2392 try writer.print("@{}", .{
2316 fn format(data: FormatData, w: *Writer) Writer.Error!void {
2317 try w.print("@{f}", .{
23932318 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),
23942319 });
23952320 }
2396 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {
2321 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
23972322 return .{ .data = .{ .global = self, .builder = builder } };
23982323 }
23992324
......@@ -4833,29 +4758,28 @@ pub const Function = struct {
48334758 instruction: Instruction.Index,
48344759 function: Function.Index,
48354760 builder: *Builder,
4761 flags: Flags,
4762 const Flags = struct {
4763 comma: bool = false,
4764 space: bool = false,
4765 percent: bool = false,
4766 };
48364767 };
4837 fn format(
4838 data: FormatData,
4839 comptime fmt_str: []const u8,
4840 _: std.fmt.FormatOptions,
4841 writer: anytype,
4842 ) @TypeOf(writer).Error!void {
4843 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
4844 @compileError("invalid format string: '" ++ fmt_str ++ "'");
4845 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
4768 fn format(data: FormatData, w: *Writer) Writer.Error!void {
4769 if (data.flags.comma) {
48464770 if (data.instruction == .none) return;
4847 try writer.writeByte(',');
4771 try w.writeByte(',');
48484772 }
4849 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {
4773 if (data.flags.space) {
48504774 if (data.instruction == .none) return;
4851 try writer.writeByte(' ');
4775 try w.writeByte(' ');
48524776 }
4853 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null) try writer.print(
4854 "{%} ",
4777 if (data.flags.percent) try w.print(
4778 "{f%} ",
48554779 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},
48564780 );
48574781 assert(data.instruction != .none);
4858 try writer.print("%{}", .{
4782 try w.print("%{f}", .{
48594783 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),
48604784 });
48614785 }
......@@ -4863,8 +4787,14 @@ pub const Function = struct {
48634787 self: Instruction.Index,
48644788 function: Function.Index,
48654789 builder: *Builder,
4866 ) std.fmt.Formatter(format) {
4867 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
4790 flags: FormatData.Flags,
4791 ) std.fmt.Formatter(FormatData, format) {
4792 return .{ .data = .{
4793 .instruction = self,
4794 .function = function,
4795 .builder = builder,
4796 .flags = flags,
4797 } };
48684798 }
48694799 };
48704800
......@@ -6361,7 +6291,7 @@ pub const WipFunction = struct {
63616291
63626292 while (true) {
63636293 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);
6364 const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{
6294 const unique_name = try wip_name.builder.fmt("{fr}{s}{fr}", .{
63656295 name.fmt(wip_name.builder),
63666296 sep,
63676297 gop.value_ptr.fmt(wip_name.builder),
......@@ -7031,13 +6961,8 @@ pub const MemoryAccessKind = enum(u1) {
70316961 normal,
70326962 @"volatile",
70336963
7034 pub fn format(
7035 self: MemoryAccessKind,
7036 comptime prefix: []const u8,
7037 _: std.fmt.FormatOptions,
7038 writer: anytype,
7039 ) @TypeOf(writer).Error!void {
7040 if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
6964 pub fn format(self: MemoryAccessKind, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
6965 if (self != .normal) try w.print("{s}{s}", .{ prefix, @tagName(self) });
70416966 }
70426967};
70436968
......@@ -7045,13 +6970,8 @@ pub const SyncScope = enum(u1) {
70456970 singlethread,
70466971 system,
70476972
7048 pub fn format(
7049 self: SyncScope,
7050 comptime prefix: []const u8,
7051 _: std.fmt.FormatOptions,
7052 writer: anytype,
7053 ) @TypeOf(writer).Error!void {
7054 if (self != .system) try writer.print(
6973 pub fn format(self: SyncScope, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
6974 if (self != .system) try w.print(
70556975 \\{s}syncscope("{s}")
70566976 , .{ prefix, @tagName(self) });
70576977 }
......@@ -7066,13 +6986,8 @@ pub const AtomicOrdering = enum(u3) {
70666986 acq_rel = 5,
70676987 seq_cst = 6,
70686988
7069 pub fn format(
7070 self: AtomicOrdering,
7071 comptime prefix: []const u8,
7072 _: std.fmt.FormatOptions,
7073 writer: anytype,
7074 ) @TypeOf(writer).Error!void {
7075 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
6989 pub fn format(self: AtomicOrdering, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
6990 if (self != .none) try w.print("{s}{s}", .{ prefix, @tagName(self) });
70766991 }
70776992};
70786993
......@@ -7486,27 +7401,26 @@ pub const Constant = enum(u32) {
74867401 const FormatData = struct {
74877402 constant: Constant,
74887403 builder: *Builder,
7404 flags: Flags,
7405 const Flags = struct {
7406 comma: bool = false,
7407 space: bool = false,
7408 percent: bool = false,
7409 };
74897410 };
7490 fn format(
7491 data: FormatData,
7492 comptime fmt_str: []const u8,
7493 _: std.fmt.FormatOptions,
7494 writer: anytype,
7495 ) @TypeOf(writer).Error!void {
7496 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
7497 @compileError("invalid format string: '" ++ fmt_str ++ "'");
7498 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
7411 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7412 if (data.flags.comma) {
74997413 if (data.constant == .no_init) return;
7500 try writer.writeByte(',');
7414 try w.writeByte(',');
75017415 }
7502 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {
7416 if (data.flags.space) {
75037417 if (data.constant == .no_init) return;
7504 try writer.writeByte(' ');
7418 try w.writeByte(' ');
75057419 }
7506 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null)
7507 try writer.print("{%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});
7420 if (data.flags.percent)
7421 try w.print("{f%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});
75087422 assert(data.constant != .no_init);
7509 if (std.enums.tagName(Constant, data.constant)) |name| return writer.writeAll(name);
7423 if (std.enums.tagName(Constant, data.constant)) |name| return w.writeAll(name);
75107424 switch (data.constant.unwrap()) {
75117425 .constant => |constant| {
75127426 const item = data.builder.constant_items.get(constant);
......@@ -7545,11 +7459,11 @@ pub const Constant = enum(u32) {
75457459 const allocator = stack.get();
75467460 const str = try bigint.toStringAlloc(allocator, 10, undefined);
75477461 defer allocator.free(str);
7548 try writer.writeAll(str);
7462 try w.writeAll(str);
75497463 },
75507464 .half,
75517465 .bfloat,
7552 => |tag| try writer.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {
7466 => |tag| try w.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {
75537467 .half => 'H',
75547468 .bfloat => 'R',
75557469 else => unreachable,
......@@ -7580,7 +7494,7 @@ pub const Constant = enum(u32) {
75807494 ) + 1,
75817495 else => 0,
75827496 };
7583 try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){
7497 try w.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){
75847498 .mantissa = std.math.shl(
75857499 Mantissa64,
75867500 repr.mantissa,
......@@ -7602,13 +7516,13 @@ pub const Constant = enum(u32) {
76027516 },
76037517 .double => {
76047518 const extra = data.builder.constantExtraData(Double, item.data);
7605 try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
7519 try w.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
76067520 },
76077521 .fp128,
76087522 .ppc_fp128,
76097523 => |tag| {
76107524 const extra = data.builder.constantExtraData(Fp128, item.data);
7611 try writer.print("0x{c}{X:0>8}{X:0>8}{X:0>8}{X:0>8}", .{
7525 try w.print("0x{c}{X:0>8}{X:0>8}{X:0>8}{X:0>8}", .{
76127526 @as(u8, switch (tag) {
76137527 .fp128 => 'L',
76147528 .ppc_fp128 => 'M',
......@@ -7622,7 +7536,7 @@ pub const Constant = enum(u32) {
76227536 },
76237537 .x86_fp80 => {
76247538 const extra = data.builder.constantExtraData(Fp80, item.data);
7625 try writer.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{
7539 try w.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{
76267540 extra.hi, extra.lo_hi, extra.lo_lo,
76277541 });
76287542 },
......@@ -7631,7 +7545,7 @@ pub const Constant = enum(u32) {
76317545 .zeroinitializer,
76327546 .undef,
76337547 .poison,
7634 => |tag| try writer.writeAll(@tagName(tag)),
7548 => |tag| try w.writeAll(@tagName(tag)),
76357549 .structure,
76367550 .packed_structure,
76377551 .array,
......@@ -7640,7 +7554,7 @@ pub const Constant = enum(u32) {
76407554 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);
76417555 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));
76427556 const vals = extra.trail.next(len, Constant, data.builder);
7643 try writer.writeAll(switch (tag) {
7557 try w.writeAll(switch (tag) {
76447558 .structure => "{ ",
76457559 .packed_structure => "<{ ",
76467560 .array => "[",
......@@ -7648,10 +7562,10 @@ pub const Constant = enum(u32) {
76487562 else => unreachable,
76497563 });
76507564 for (vals, 0..) |val, index| {
7651 if (index > 0) try writer.writeAll(", ");
7652 try writer.print("{%}", .{val.fmt(data.builder)});
7565 if (index > 0) try w.writeAll(", ");
7566 try w.print("{f%}", .{val.fmt(data.builder)});
76537567 }
7654 try writer.writeAll(switch (tag) {
7568 try w.writeAll(switch (tag) {
76557569 .structure => " }",
76567570 .packed_structure => " }>",
76577571 .array => "]",
......@@ -7662,20 +7576,20 @@ pub const Constant = enum(u32) {
76627576 .splat => {
76637577 const extra = data.builder.constantExtraData(Splat, item.data);
76647578 const len = extra.type.vectorLen(data.builder);
7665 try writer.writeByte('<');
7579 try w.writeByte('<');
76667580 for (0..len) |index| {
7667 if (index > 0) try writer.writeAll(", ");
7668 try writer.print("{%}", .{extra.value.fmt(data.builder)});
7581 if (index > 0) try w.writeAll(", ");
7582 try w.print("{f%}", .{extra.value.fmt(data.builder)});
76697583 }
7670 try writer.writeByte('>');
7584 try w.writeByte('>');
76717585 },
7672 .string => try writer.print("c{\"}", .{
7586 .string => try w.print("c{f\"}", .{
76737587 @as(String, @enumFromInt(item.data)).fmt(data.builder),
76747588 }),
76757589 .blockaddress => |tag| {
76767590 const extra = data.builder.constantExtraData(BlockAddress, item.data);
76777591 const function = extra.function.ptrConst(data.builder);
7678 try writer.print("{s}({}, {})", .{
7592 try w.print("{s}({f}, {f})", .{
76797593 @tagName(tag),
76807594 function.global.fmt(data.builder),
76817595 extra.block.toInst(function).fmt(extra.function, data.builder),
......@@ -7685,7 +7599,7 @@ pub const Constant = enum(u32) {
76857599 .no_cfi,
76867600 => |tag| {
76877601 const function: Function.Index = @enumFromInt(item.data);
7688 try writer.print("{s} {}", .{
7602 try w.print("{s} {f}", .{
76897603 @tagName(tag),
76907604 function.ptrConst(data.builder).global.fmt(data.builder),
76917605 });
......@@ -7697,7 +7611,7 @@ pub const Constant = enum(u32) {
76977611 .addrspacecast,
76987612 => |tag| {
76997613 const extra = data.builder.constantExtraData(Cast, item.data);
7700 try writer.print("{s} ({%} to {%})", .{
7614 try w.print("{s} ({f%} to {f%})", .{
77017615 @tagName(tag),
77027616 extra.val.fmt(data.builder),
77037617 extra.type.fmt(data.builder),
......@@ -7709,13 +7623,13 @@ pub const Constant = enum(u32) {
77097623 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);
77107624 const indices =
77117625 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);
7712 try writer.print("{s} ({%}, {%}", .{
7626 try w.print("{s} ({f%}, {f%}", .{
77137627 @tagName(tag),
77147628 extra.data.type.fmt(data.builder),
77157629 extra.data.base.fmt(data.builder),
77167630 });
7717 for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});
7718 try writer.writeByte(')');
7631 for (indices) |index| try w.print(", {f%}", .{index.fmt(data.builder)});
7632 try w.writeByte(')');
77197633 },
77207634 .add,
77217635 .@"add nsw",
......@@ -7727,7 +7641,7 @@ pub const Constant = enum(u32) {
77277641 .xor,
77287642 => |tag| {
77297643 const extra = data.builder.constantExtraData(Binary, item.data);
7730 try writer.print("{s} ({%}, {%})", .{
7644 try w.print("{s} ({f%}, {f%})", .{
77317645 @tagName(tag),
77327646 extra.lhs.fmt(data.builder),
77337647 extra.rhs.fmt(data.builder),
......@@ -7751,7 +7665,7 @@ pub const Constant = enum(u32) {
77517665 .@"asm sideeffect alignstack inteldialect unwind",
77527666 => |tag| {
77537667 const extra = data.builder.constantExtraData(Assembly, item.data);
7754 try writer.print("{s} {\"}, {\"}", .{
7668 try w.print("{s} {f\"}, {f\"}", .{
77557669 @tagName(tag),
77567670 extra.assembly.fmt(data.builder),
77577671 extra.constraints.fmt(data.builder),
......@@ -7759,11 +7673,15 @@ pub const Constant = enum(u32) {
77597673 },
77607674 }
77617675 },
7762 .global => |global| try writer.print("{}", .{global.fmt(data.builder)}),
7676 .global => |global| try w.print("{f}", .{global.fmt(data.builder)}),
77637677 }
77647678 }
7765 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {
7766 return .{ .data = .{ .constant = self, .builder = builder } };
7679 pub fn fmt(self: Constant, builder: *Builder, flags: FormatData.Flags) std.fmt.Formatter(FormatData, format) {
7680 return .{ .data = .{
7681 .constant = self,
7682 .builder = builder,
7683 .flags = flags,
7684 } };
77677685 }
77687686};
77697687
......@@ -7819,26 +7737,21 @@ pub const Value = enum(u32) {
78197737 function: Function.Index,
78207738 builder: *Builder,
78217739 };
7822 fn format(
7823 data: FormatData,
7824 comptime fmt_str: []const u8,
7825 fmt_opts: std.fmt.FormatOptions,
7826 writer: anytype,
7827 ) @TypeOf(writer).Error!void {
7740 fn format(data: FormatData, w: *Writer) Writer.Error!void {
78287741 switch (data.value.unwrap()) {
78297742 .instruction => |instruction| try Function.Instruction.Index.format(.{
78307743 .instruction = instruction,
78317744 .function = data.function,
78327745 .builder = data.builder,
7833 }, fmt_str, fmt_opts, writer),
7746 }, w),
78347747 .constant => |constant| try Constant.format(.{
78357748 .constant = constant,
78367749 .builder = data.builder,
7837 }, fmt_str, fmt_opts, writer),
7750 }, w),
78387751 .metadata => unreachable,
78397752 }
78407753 }
7841 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) {
7754 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(FormatData, format) {
78427755 return .{ .data = .{ .value = self, .function = function, .builder = builder } };
78437756 }
78447757};
......@@ -7869,15 +7782,10 @@ pub const MetadataString = enum(u32) {
78697782 metadata_string: MetadataString,
78707783 builder: *const Builder,
78717784 };
7872 fn format(
7873 data: FormatData,
7874 comptime _: []const u8,
7875 _: std.fmt.FormatOptions,
7876 writer: anytype,
7877 ) @TypeOf(writer).Error!void {
7878 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, writer);
7785 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7786 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, w);
78797787 }
7880 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {
7788 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
78817789 return .{ .data = .{ .metadata_string = self, .builder = builder } };
78827790 }
78837791};
......@@ -8039,29 +7947,24 @@ pub const Metadata = enum(u32) {
80397947 AllCallsDescribed: bool = false,
80407948 Unused: u2 = 0,
80417949
8042 pub fn format(
8043 self: DIFlags,
8044 comptime _: []const u8,
8045 _: std.fmt.FormatOptions,
8046 writer: anytype,
8047 ) @TypeOf(writer).Error!void {
7950 pub fn format(self: DIFlags, w: *Writer, comptime _: []const u8) Writer.Error!void {
80487951 var need_pipe = false;
80497952 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {
80507953 switch (@typeInfo(field.type)) {
80517954 .bool => if (@field(self, field.name)) {
8052 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
8053 try writer.print("DIFlag{s}", .{field.name});
7955 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
7956 try w.print("DIFlag{s}", .{field.name});
80547957 },
80557958 .@"enum" => if (@field(self, field.name) != .Zero) {
8056 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
8057 try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))});
7959 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
7960 try w.print("DIFlag{s}", .{@tagName(@field(self, field.name))});
80587961 },
80597962 .int => assert(@field(self, field.name) == 0),
80607963 else => @compileError("bad field type: " ++ field.name ++ ": " ++
80617964 @typeName(field.type)),
80627965 }
80637966 }
8064 if (!need_pipe) try writer.writeByte('0');
7967 if (!need_pipe) try w.writeByte('0');
80657968 }
80667969 };
80677970
......@@ -8101,29 +8004,24 @@ pub const Metadata = enum(u32) {
81018004 ObjCDirect: bool = false,
81028005 Unused: u20 = 0,
81038006
8104 pub fn format(
8105 self: DISPFlags,
8106 comptime _: []const u8,
8107 _: std.fmt.FormatOptions,
8108 writer: anytype,
8109 ) @TypeOf(writer).Error!void {
8007 pub fn format(self: DISPFlags, w: *Writer, comptime _: []const u8) Writer.Error!void {
81108008 var need_pipe = false;
81118009 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {
81128010 switch (@typeInfo(field.type)) {
81138011 .bool => if (@field(self, field.name)) {
8114 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
8115 try writer.print("DISPFlag{s}", .{field.name});
8012 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8013 try w.print("DISPFlag{s}", .{field.name});
81168014 },
81178015 .@"enum" => if (@field(self, field.name) != .Zero) {
8118 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;
8119 try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});
8016 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8017 try w.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});
81208018 },
81218019 .int => assert(@field(self, field.name) == 0),
81228020 else => @compileError("bad field type: " ++ field.name ++ ": " ++
81238021 @typeName(field.type)),
81248022 }
81258023 }
8126 if (!need_pipe) try writer.writeByte('0');
8024 if (!need_pipe) try w.writeByte('0');
81278025 }
81288026 };
81298027
......@@ -8298,6 +8196,9 @@ pub const Metadata = enum(u32) {
82988196 formatter: *Formatter,
82998197 prefix: []const u8 = "",
83008198 node: Node,
8199 specialized: ?TODO,
8200
8201 const TODO = opaque {};
83018202
83028203 const Node = union(enum) {
83038204 none,
......@@ -8323,20 +8224,15 @@ pub const Metadata = enum(u32) {
83238224 };
83248225 };
83258226 };
8326 fn format(
8327 data: FormatData,
8328 comptime fmt_str: []const u8,
8329 fmt_opts: std.fmt.FormatOptions,
8330 writer: anytype,
8331 ) @TypeOf(writer).Error!void {
8227 fn format(data: FormatData, w: *Writer) Writer.Error!void {
83328228 if (data.node == .none) return;
83338229
8334 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';
8335 const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str;
8230 const is_specialized = data.specialized != null;
8231 const recurse_fmt_str = data.specialized orelse {};
83368232
8337 if (data.formatter.need_comma) try writer.writeAll(", ");
8233 if (data.formatter.need_comma) try w.writeAll(", ");
83388234 defer data.formatter.need_comma = true;
8339 try writer.writeAll(data.prefix);
8235 try w.writeAll(data.prefix);
83408236
83418237 const builder = data.formatter.builder;
83428238 switch (data.node) {
......@@ -8351,54 +8247,50 @@ pub const Metadata = enum(u32) {
83518247 .expression => {
83528248 var extra = builder.metadataExtraDataTrail(Expression, item.data);
83538249 const elements = extra.trail.next(extra.data.elements_len, u32, builder);
8354 try writer.writeAll("!DIExpression(");
8250 try w.writeAll("!DIExpression(");
83558251 for (elements) |element| try format(.{
83568252 .formatter = data.formatter,
83578253 .node = .{ .u64 = element },
8358 }, "%", fmt_opts, writer);
8359 try writer.writeByte(')');
8254 }, w, "%");
8255 try w.writeByte(')');
83608256 },
83618257 .constant => try Constant.format(.{
83628258 .constant = @enumFromInt(item.data),
83638259 .builder = builder,
8364 }, recurse_fmt_str, fmt_opts, writer),
8260 }, w, recurse_fmt_str),
83658261 else => unreachable,
83668262 }
83678263 },
8368 .index => |node| try writer.print("!{d}", .{node}),
8264 .index => |node| try w.print("!{d}", .{node}),
83698265 inline .local_value, .local_metadata => |node, tag| try Value.format(.{
83708266 .value = node.value,
83718267 .function = node.function,
83728268 .builder = builder,
8373 }, switch (tag) {
8269 }, w, switch (tag) {
83748270 .local_value => recurse_fmt_str,
83758271 .local_metadata => "%",
83768272 else => unreachable,
8377 }, fmt_opts, writer),
8273 }),
83788274 inline .local_inline, .local_index => |node, tag| {
83798275 if (comptime std.mem.eql(u8, recurse_fmt_str, "%"))
8380 try writer.print("{%} ", .{Type.metadata.fmt(builder)});
8276 try w.print("{f%} ", .{Type.metadata.fmt(builder)});
83818277 try format(.{
83828278 .formatter = data.formatter,
83838279 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),
8384 }, "%", fmt_opts, writer);
8280 }, w, "%");
83858281 },
8386 .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{
8282 .string => |node| try w.print((if (is_specialized) "" else "!") ++ "{f}", .{
83878283 node.fmt(builder),
83888284 }),
8389 inline .bool,
8390 .u32,
8391 .u64,
8392 .di_flags,
8393 .sp_flags,
8394 => |node| try writer.print("{}", .{node}),
8395 .raw => |node| try writer.writeAll(node),
8285 inline .bool, .u32, .u64 => |node| try w.print("{}", .{node}),
8286 inline .di_flags, .sp_flags => |node| try w.print("{f}", .{node}),
8287 .raw => |node| try w.writeAll(node),
83968288 }
83978289 }
83988290 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {
83998291 Metadata => Allocator.Error,
84008292 else => error{},
8401 }!std.fmt.Formatter(format) {
8293 }!std.fmt.Formatter(FormatData, format) {
84028294 const Node = @TypeOf(node);
84038295 const MaybeNode = switch (@typeInfo(Node)) {
84048296 .optional => Node,
......@@ -8442,7 +8334,7 @@ pub const Metadata = enum(u32) {
84428334 prefix: []const u8,
84438335 value: Value,
84448336 function: Function.Index,
8445 ) Allocator.Error!std.fmt.Formatter(format) {
8337 ) Allocator.Error!std.fmt.Formatter(FormatData, format) {
84468338 return .{ .data = .{
84478339 .formatter = formatter,
84488340 .prefix = prefix,
......@@ -8506,7 +8398,7 @@ pub const Metadata = enum(u32) {
85068398 DIGlobalVariableExpression,
85078399 },
85088400 nodes: anytype,
8509 writer: anytype,
8401 w: *Writer,
85108402 ) !void {
85118403 comptime var fmt_str: []const u8 = "";
85128404 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
......@@ -8523,10 +8415,10 @@ pub const Metadata = enum(u32) {
85238415 }
85248416 fmt_str = fmt_str ++ "(";
85258417 inline for (fields[2..], names) |*field, name| {
8526 fmt_str = fmt_str ++ "{[" ++ name ++ "]S}";
8418 fmt_str = fmt_str ++ "{[" ++ name ++ "]fS}";
85278419 field.* = .{
85288420 .name = name,
8529 .type = std.fmt.Formatter(format),
8421 .type = std.fmt.Formatter(FormatData, format),
85308422 .default_value_ptr = null,
85318423 .is_comptime = false,
85328424 .alignment = 0,
......@@ -8546,7 +8438,7 @@ pub const Metadata = enum(u32) {
85468438 name ++ ": ",
85478439 @field(nodes, name),
85488440 );
8549 try writer.print(fmt_str, fmt_args);
8441 try w.print(fmt_str, fmt_args);
85508442 }
85518443 };
85528444};
......@@ -8636,7 +8528,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
86368528 inline for (.{ 0, 4 }) |addr_space_index| {
86378529 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
86388530 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8639 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));
8531 @field(Type, std.fmt.comptimePrint("ptr{f }", .{addr_space})));
86408532 }
86418533 }
86428534
......@@ -8759,16 +8651,8 @@ pub fn deinit(self: *Builder) void {
87598651 self.* = undefined;
87608652}
87618653
8762pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {
8763 self.module_asm.clearRetainingCapacity();
8764 return self.appendModuleAsm();
8765}
8766
8767pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {
8768 return self.module_asm.writer(self.gpa);
8769}
8770
8771pub fn finishModuleAsm(self: *Builder) Allocator.Error!void {
8654pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {
8655 self.module_asm = aw.toArrayList();
87728656 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')
87738657 try self.module_asm.append(self.gpa, '\n');
87748658}
......@@ -8804,7 +8688,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo
88048688}
88058689
88068690pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {
8807 self.string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
8691 self.string_bytes.printAssumeCapacity(fmt_str, fmt_args);
88088692 return self.trailingStringAssumeCapacity();
88098693}
88108694
......@@ -9076,9 +8960,13 @@ pub fn getIntrinsic(
90768960 const allocator = stack.get();
90778961
90788962 const name = name: {
9079 const writer = self.strtab_string_bytes.writer(self.gpa);
9080 try writer.print("llvm.{s}", .{@tagName(id)});
9081 for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)});
8963 {
8964 var aw: Writer.Allocating = .fromArrayList(self.gpa, &self.strtab_string_bytes);
8965 const w = &aw.interface;
8966 defer self.strtab_string_bytes = aw.toArrayList();
8967 w.print("llvm.{s}", .{@tagName(id)}) catch return error.OutOfMemory;
8968 for (overload) |ty| w.print(".{fm}", .{ty.fmt(self)}) catch return error.OutOfMemory;
8969 }
90828970 break :name try self.trailingStrtabString();
90838971 };
90848972 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
......@@ -9492,110 +9380,74 @@ pub fn asmValue(
94929380 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
94939381}
94949382
9495pub fn dump(self: *Builder) void {
9383pub fn dump(b: *Builder) void {
9384 var buffer: [4000]u8 = undefined;
94969385 const stderr: std.fs.File = .stderr();
9497 self.print(stderr.writer()) catch {};
9386 b.printToFile(stderr, &buffer) catch {};
94989387}
94999388
9500pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool {
9501 var file = std.fs.cwd().createFile(path, .{}) catch |err| {
9502 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9503 return false;
9504 };
9389pub fn printToFilePath(b: *Builder, dir: std.fs.Dir, path: []const u8) !void {
9390 var buffer: [4000]u8 = undefined;
9391 const file = try dir.createFile(path, .{});
95059392 defer file.close();
9506 self.print(file.writer()) catch |err| {
9507 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9508 return false;
9509 };
9510 return true;
9393 try b.printToFile(file, &buffer);
95119394}
95129395
9513pub fn print(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator.Error)!void {
9514 var bw = std.io.bufferedWriter(writer);
9515 try self.printUnbuffered(bw.writer());
9516 try bw.flush();
9517}
9518
9519fn WriterWithErrors(comptime BackingWriter: type, comptime ExtraErrors: type) type {
9520 return struct {
9521 backing_writer: BackingWriter,
9522
9523 pub const Error = BackingWriter.Error || ExtraErrors;
9524 pub const Writer = std.io.GenericWriter(*const Self, Error, write);
9525
9526 const Self = @This();
9527
9528 pub fn writer(self: *const Self) Writer {
9529 return .{ .context = self };
9530 }
9531
9532 pub fn write(self: *const Self, bytes: []const u8) Error!usize {
9533 return self.backing_writer.write(bytes);
9534 }
9535 };
9396pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void {
9397 var fw = file.writer(buffer);
9398 try print(b, &fw.interface);
9399 try fw.interface.flush();
95369400}
9537fn writerWithErrors(
9538 backing_writer: anytype,
9539 comptime ExtraErrors: type,
9540) WriterWithErrors(@TypeOf(backing_writer), ExtraErrors) {
9541 return .{ .backing_writer = backing_writer };
9542}
9543
9544pub fn printUnbuffered(
9545 self: *Builder,
9546 backing_writer: anytype,
9547) (@TypeOf(backing_writer).Error || Allocator.Error)!void {
9548 const writer_with_errors = writerWithErrors(backing_writer, Allocator.Error);
9549 const writer = writer_with_errors.writer();
95509401
9402pub fn print(self: *Builder, w: *Writer) Writer.Error!void {
95519403 var need_newline = false;
95529404 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
95539405 defer metadata_formatter.map.deinit(self.gpa);
95549406
95559407 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
9556 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9557 if (self.source_filename != .none) try writer.print(
9408 if (need_newline) try w.writeByte('\n') else need_newline = true;
9409 if (self.source_filename != .none) try w.print(
95589410 \\; ModuleID = '{s}'
9559 \\source_filename = {"}
9411 \\source_filename = {f"}
95609412 \\
95619413 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
9562 if (self.data_layout != .none) try writer.print(
9563 \\target datalayout = {"}
9414 if (self.data_layout != .none) try w.print(
9415 \\target datalayout = {f"}
95649416 \\
95659417 , .{self.data_layout.fmt(self)});
9566 if (self.target_triple != .none) try writer.print(
9567 \\target triple = {"}
9418 if (self.target_triple != .none) try w.print(
9419 \\target triple = {f"}
95689420 \\
95699421 , .{self.target_triple.fmt(self)});
95709422 }
95719423
95729424 if (self.module_asm.items.len > 0) {
9573 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9425 if (need_newline) try w.writeByte('\n') else need_newline = true;
95749426 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
95759427 while (line_it.next()) |line| {
9576 try writer.writeAll("module asm ");
9577 try printEscapedString(line, .always_quote, writer);
9578 try writer.writeByte('\n');
9428 try w.writeAll("module asm ");
9429 try printEscapedString(line, .always_quote, w);
9430 try w.writeByte('\n');
95799431 }
95809432 }
95819433
95829434 if (self.types.count() > 0) {
9583 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9584 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
9585 \\%{} = type {}
9435 if (need_newline) try w.writeByte('\n') else need_newline = true;
9436 for (self.types.keys(), self.types.values()) |id, ty| try w.print(
9437 \\%{f} = type {f}
95869438 \\
95879439 , .{ id.fmt(self), ty.fmt(self) });
95889440 }
95899441
95909442 if (self.variables.items.len > 0) {
9591 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9443 if (need_newline) try w.writeByte('\n') else need_newline = true;
95929444 for (self.variables.items) |variable| {
95939445 if (variable.global.getReplacement(self) != .none) continue;
95949446 const global = variable.global.ptrConst(self);
95959447 metadata_formatter.need_comma = true;
95969448 defer metadata_formatter.need_comma = undefined;
9597 try writer.print(
9598 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{}
9449 try w.print(
9450 \\{f} ={f}{f}{f}{f}{f }{f}{f }{f} {s} {f%}{f }{f, }{f}
95999451 \\
96009452 , .{
96019453 variable.global.fmt(self),
......@@ -9618,14 +9470,14 @@ pub fn printUnbuffered(
96189470 }
96199471
96209472 if (self.aliases.items.len > 0) {
9621 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9473 if (need_newline) try w.writeByte('\n') else need_newline = true;
96229474 for (self.aliases.items) |alias| {
96239475 if (alias.global.getReplacement(self) != .none) continue;
96249476 const global = alias.global.ptrConst(self);
96259477 metadata_formatter.need_comma = true;
96269478 defer metadata_formatter.need_comma = undefined;
9627 try writer.print(
9628 \\{} ={}{}{}{}{ }{} alias {%}, {%}{}
9479 try w.print(
9480 \\{f} ={f}{f}{f}{f}{f }{f} alias {f%}, {f%}{f}
96299481 \\
96309482 , .{
96319483 alias.global.fmt(self),
......@@ -9647,17 +9499,17 @@ pub fn printUnbuffered(
96479499
96489500 for (0.., self.functions.items) |function_i, function| {
96499501 if (function.global.getReplacement(self) != .none) continue;
9650 if (need_newline) try writer.writeByte('\n') else need_newline = true;
9502 if (need_newline) try w.writeByte('\n') else need_newline = true;
96519503 const function_index: Function.Index = @enumFromInt(function_i);
96529504 const global = function.global.ptrConst(self);
96539505 const params_len = global.type.functionParameters(self).len;
96549506 const function_attributes = function.attributes.func(self);
9655 if (function_attributes != .none) try writer.print(
9656 \\; Function Attrs:{}
9507 if (function_attributes != .none) try w.print(
9508 \\; Function Attrs:{f}
96579509 \\
96589510 , .{function_attributes.fmt(self)});
9659 try writer.print(
9660 \\{s}{}{}{}{}{}{"} {%} {}(
9511 try w.print(
9512 \\{s}{f}{f}{f}{f}{f}{f"} {f%} {f}(
96619513 , .{
96629514 if (function.instructions.len > 0) "define" else "declare",
96639515 global.linkage,
......@@ -9670,40 +9522,40 @@ pub fn printUnbuffered(
96709522 function.global.fmt(self),
96719523 });
96729524 for (0..params_len) |arg| {
9673 if (arg > 0) try writer.writeAll(", ");
9674 try writer.print(
9675 \\{%}{"}
9525 if (arg > 0) try w.writeAll(", ");
9526 try w.print(
9527 \\{f%}{f"}
96769528 , .{
96779529 global.type.functionParameters(self)[arg].fmt(self),
96789530 function.attributes.param(arg, self).fmt(self),
96799531 });
96809532 if (function.instructions.len > 0)
9681 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
9533 try w.print(" {f}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
96829534 else
9683 try writer.print(" %{d}", .{arg});
9535 try w.print(" %{d}", .{arg});
96849536 }
96859537 switch (global.type.functionKind(self)) {
96869538 .normal => {},
96879539 .vararg => {
9688 if (params_len > 0) try writer.writeAll(", ");
9689 try writer.writeAll("...");
9540 if (params_len > 0) try w.writeAll(", ");
9541 try w.writeAll("...");
96909542 },
96919543 }
9692 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
9693 if (function_attributes != .none) try writer.print(" #{d}", .{
9544 try w.print("){f}{f }", .{ global.unnamed_addr, global.addr_space });
9545 if (function_attributes != .none) try w.print(" #{d}", .{
96949546 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
96959547 });
96969548 {
96979549 metadata_formatter.need_comma = false;
96989550 defer metadata_formatter.need_comma = undefined;
9699 try writer.print("{ }{}", .{
9551 try w.print("{f }{f}", .{
97009552 function.alignment,
97019553 try metadata_formatter.fmt(" !dbg ", global.dbg),
97029554 });
97039555 }
97049556 if (function.instructions.len > 0) {
97059557 var block_incoming_len: u32 = undefined;
9706 try writer.writeAll(" {\n");
9558 try w.writeAll(" {\n");
97079559 var maybe_dbg_index: ?u32 = null;
97089560 for (params_len..function.instructions.len) |instruction_i| {
97099561 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
......@@ -9801,7 +9653,7 @@ pub fn printUnbuffered(
98019653 .xor,
98029654 => |tag| {
98039655 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9804 try writer.print(" %{} = {s} {%}, {}", .{
9656 try w.print(" %{f} = {s} {f%}, {f}", .{
98059657 instruction_index.name(&function).fmt(self),
98069658 @tagName(tag),
98079659 extra.lhs.fmt(function_index, self),
......@@ -9823,7 +9675,7 @@ pub fn printUnbuffered(
98239675 .zext,
98249676 => |tag| {
98259677 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9826 try writer.print(" %{} = {s} {%} to {%}", .{
9678 try w.print(" %{f} = {s} {f%} to {f%}", .{
98279679 instruction_index.name(&function).fmt(self),
98289680 @tagName(tag),
98299681 extra.val.fmt(function_index, self),
......@@ -9834,7 +9686,7 @@ pub fn printUnbuffered(
98349686 .@"alloca inalloca",
98359687 => |tag| {
98369688 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9837 try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{
9689 try w.print(" %{f} = {s} {f%}{f,%}{f, }{f, }", .{
98389690 instruction_index.name(&function).fmt(self),
98399691 @tagName(tag),
98409692 extra.type.fmt(self),
......@@ -9850,7 +9702,7 @@ pub fn printUnbuffered(
98509702 .atomicrmw => |tag| {
98519703 const extra =
98529704 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9853 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{
9705 try w.print(" %{f} = {s}{f } {s} {f%}, {f%}{f }{f }{f, }", .{
98549706 instruction_index.name(&function).fmt(self),
98559707 @tagName(tag),
98569708 extra.info.access_kind,
......@@ -9866,19 +9718,19 @@ pub fn printUnbuffered(
98669718 block_incoming_len = instruction.data;
98679719 const name = instruction_index.name(&function);
98689720 if (@intFromEnum(instruction_index) > params_len)
9869 try writer.writeByte('\n');
9870 try writer.print("{}:\n", .{name.fmt(self)});
9721 try w.writeByte('\n');
9722 try w.print("{f}:\n", .{name.fmt(self)});
98719723 continue;
98729724 },
98739725 .br => |tag| {
98749726 const target: Function.Block.Index = @enumFromInt(instruction.data);
9875 try writer.print(" {s} {%}", .{
9727 try w.print(" {s} {f%}", .{
98769728 @tagName(tag), target.toInst(&function).fmt(function_index, self),
98779729 });
98789730 },
98799731 .br_cond => {
98809732 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9881 try writer.print(" br {%}, {%}, {%}", .{
9733 try w.print(" br {f%}, {f%}, {f%}", .{
98829734 extra.cond.fmt(function_index, self),
98839735 extra.then.toInst(&function).fmt(function_index, self),
98849736 extra.@"else".toInst(&function).fmt(function_index, self),
......@@ -9887,8 +9739,8 @@ pub fn printUnbuffered(
98879739 defer metadata_formatter.need_comma = undefined;
98889740 switch (extra.weights) {
98899741 .none => {},
9890 .unpredictable => try writer.writeAll("!unpredictable !{}"),
9891 _ => try writer.print("{}", .{
9742 .unpredictable => try w.writeAll("!unpredictable !{}"),
9743 _ => try w.print("{f}", .{
98929744 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),
98939745 }),
98949746 }
......@@ -9905,16 +9757,16 @@ pub fn printUnbuffered(
99059757 var extra =
99069758 function.extraDataTrail(Function.Instruction.Call, instruction.data);
99079759 const args = extra.trail.next(extra.data.args_len, Value, &function);
9908 try writer.writeAll(" ");
9760 try w.writeAll(" ");
99099761 const ret_ty = extra.data.ty.functionReturn(self);
99109762 switch (ret_ty) {
99119763 .void => {},
9912 else => try writer.print("%{} = ", .{
9764 else => try w.print("%{f} = ", .{
99139765 instruction_index.name(&function).fmt(self),
99149766 }),
99159767 .none => unreachable,
99169768 }
9917 try writer.print("{s}{}{}{} {%} {}(", .{
9769 try w.print("{s}{f}{f}{f} {f%} {f}(", .{
99189770 @tagName(tag),
99199771 extra.data.info.call_conv,
99209772 extra.data.attributes.ret(self).fmt(self),
......@@ -9926,21 +9778,21 @@ pub fn printUnbuffered(
99269778 extra.data.callee.fmt(function_index, self),
99279779 });
99289780 for (0.., args) |arg_index, arg| {
9929 if (arg_index > 0) try writer.writeAll(", ");
9781 if (arg_index > 0) try w.writeAll(", ");
99309782 metadata_formatter.need_comma = false;
99319783 defer metadata_formatter.need_comma = undefined;
9932 try writer.print("{%}{}{}", .{
9784 try w.print("{f%}{f}{f}", .{
99339785 arg.typeOf(function_index, self).fmt(self),
99349786 extra.data.attributes.param(arg_index, self).fmt(self),
99359787 try metadata_formatter.fmtLocal(" ", arg, function_index),
99369788 });
99379789 }
9938 try writer.writeByte(')');
9790 try w.writeByte(')');
99399791 if (extra.data.info.has_op_bundle_cold) {
9940 try writer.writeAll(" [ \"cold\"() ]");
9792 try w.writeAll(" [ \"cold\"() ]");
99419793 }
99429794 const call_function_attributes = extra.data.attributes.func(self);
9943 if (call_function_attributes != .none) try writer.print(" #{d}", .{
9795 if (call_function_attributes != .none) try w.print(" #{d}", .{
99449796 (try attribute_groups.getOrPutValue(
99459797 self.gpa,
99469798 call_function_attributes,
......@@ -9953,7 +9805,7 @@ pub fn printUnbuffered(
99539805 => |tag| {
99549806 const extra =
99559807 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9956 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{
9808 try w.print(" %{f} = {s}{f } {f%}, {f%}, {f%}{f }{f }{f }{f, }", .{
99579809 instruction_index.name(&function).fmt(self),
99589810 @tagName(tag),
99599811 extra.info.access_kind,
......@@ -9969,7 +9821,7 @@ pub fn printUnbuffered(
99699821 .extractelement => |tag| {
99709822 const extra =
99719823 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9972 try writer.print(" %{} = {s} {%}, {%}", .{
9824 try w.print(" %{f} = {s} {f%}, {f%}", .{
99739825 instruction_index.name(&function).fmt(self),
99749826 @tagName(tag),
99759827 extra.val.fmt(function_index, self),
......@@ -9982,16 +9834,16 @@ pub fn printUnbuffered(
99829834 instruction.data,
99839835 );
99849836 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9985 try writer.print(" %{} = {s} {%}", .{
9837 try w.print(" %{f} = {s} {f%}", .{
99869838 instruction_index.name(&function).fmt(self),
99879839 @tagName(tag),
99889840 extra.data.val.fmt(function_index, self),
99899841 });
9990 for (indices) |index| try writer.print(", {d}", .{index});
9842 for (indices) |index| try w.print(", {d}", .{index});
99919843 },
99929844 .fence => |tag| {
99939845 const info: MemoryAccessInfo = @bitCast(instruction.data);
9994 try writer.print(" {s}{ }{ }", .{
9846 try w.print(" {s}{f }{f }", .{
99959847 @tagName(tag),
99969848 info.sync_scope,
99979849 info.success_ordering,
......@@ -10001,7 +9853,7 @@ pub fn printUnbuffered(
100019853 .@"fneg fast",
100029854 => |tag| {
100039855 const val: Value = @enumFromInt(instruction.data);
10004 try writer.print(" %{} = {s} {%}", .{
9856 try w.print(" %{f} = {s} {f%}", .{
100059857 instruction_index.name(&function).fmt(self),
100069858 @tagName(tag),
100079859 val.fmt(function_index, self),
......@@ -10015,13 +9867,13 @@ pub fn printUnbuffered(
100159867 instruction.data,
100169868 );
100179869 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
10018 try writer.print(" %{} = {s} {%}, {%}", .{
9870 try w.print(" %{f} = {s} {f%}, {f%}", .{
100199871 instruction_index.name(&function).fmt(self),
100209872 @tagName(tag),
100219873 extra.data.type.fmt(self),
100229874 extra.data.base.fmt(function_index, self),
100239875 });
10024 for (indices) |index| try writer.print(", {%}", .{
9876 for (indices) |index| try w.print(", {f%}", .{
100259877 index.fmt(function_index, self),
100269878 });
100279879 },
......@@ -10030,22 +9882,22 @@ pub fn printUnbuffered(
100309882 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);
100319883 const targets =
100329884 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);
10033 try writer.print(" {s} {%}, [", .{
9885 try w.print(" {s} {f%}, [", .{
100349886 @tagName(tag),
100359887 extra.data.addr.fmt(function_index, self),
100369888 });
100379889 for (0.., targets) |target_index, target| {
10038 if (target_index > 0) try writer.writeAll(", ");
10039 try writer.print("{%}", .{
9890 if (target_index > 0) try w.writeAll(", ");
9891 try w.print("{f%}", .{
100409892 target.toInst(&function).fmt(function_index, self),
100419893 });
100429894 }
10043 try writer.writeByte(']');
9895 try w.writeByte(']');
100449896 },
100459897 .insertelement => |tag| {
100469898 const extra =
100479899 function.extraData(Function.Instruction.InsertElement, instruction.data);
10048 try writer.print(" %{} = {s} {%}, {%}, {%}", .{
9900 try w.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
100499901 instruction_index.name(&function).fmt(self),
100509902 @tagName(tag),
100519903 extra.val.fmt(function_index, self),
......@@ -10057,19 +9909,19 @@ pub fn printUnbuffered(
100579909 var extra =
100589910 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
100599911 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
10060 try writer.print(" %{} = {s} {%}, {%}", .{
9912 try w.print(" %{f} = {s} {f%}, {f%}", .{
100619913 instruction_index.name(&function).fmt(self),
100629914 @tagName(tag),
100639915 extra.data.val.fmt(function_index, self),
100649916 extra.data.elem.fmt(function_index, self),
100659917 });
10066 for (indices) |index| try writer.print(", {d}", .{index});
9918 for (indices) |index| try w.print(", {d}", .{index});
100679919 },
100689920 .load,
100699921 .@"load atomic",
100709922 => |tag| {
100719923 const extra = function.extraData(Function.Instruction.Load, instruction.data);
10072 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{
9924 try w.print(" %{f} = {s}{f } {f%}, {f%}{f }{f }{f, }", .{
100739925 instruction_index.name(&function).fmt(self),
100749926 @tagName(tag),
100759927 extra.info.access_kind,
......@@ -10087,14 +9939,14 @@ pub fn printUnbuffered(
100879939 const vals = extra.trail.next(block_incoming_len, Value, &function);
100889940 const blocks =
100899941 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
10090 try writer.print(" %{} = {s} {%} ", .{
9942 try w.print(" %{f} = {s} {f%} ", .{
100919943 instruction_index.name(&function).fmt(self),
100929944 @tagName(tag),
100939945 vals[0].typeOf(function_index, self).fmt(self),
100949946 });
100959947 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
10096 if (incoming_index > 0) try writer.writeAll(", ");
10097 try writer.print("[ {}, {} ]", .{
9948 if (incoming_index > 0) try w.writeAll(", ");
9949 try w.print("[ {f}, {f} ]", .{
100989950 incoming_val.fmt(function_index, self),
100999951 incoming_block.toInst(&function).fmt(function_index, self),
101009952 });
......@@ -10102,19 +9954,19 @@ pub fn printUnbuffered(
101029954 },
101039955 .ret => |tag| {
101049956 const val: Value = @enumFromInt(instruction.data);
10105 try writer.print(" {s} {%}", .{
9957 try w.print(" {s} {f%}", .{
101069958 @tagName(tag),
101079959 val.fmt(function_index, self),
101089960 });
101099961 },
101109962 .@"ret void",
101119963 .@"unreachable",
10112 => |tag| try writer.print(" {s}", .{@tagName(tag)}),
9964 => |tag| try w.print(" {s}", .{@tagName(tag)}),
101139965 .select,
101149966 .@"select fast",
101159967 => |tag| {
101169968 const extra = function.extraData(Function.Instruction.Select, instruction.data);
10117 try writer.print(" %{} = {s} {%}, {%}, {%}", .{
9969 try w.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
101189970 instruction_index.name(&function).fmt(self),
101199971 @tagName(tag),
101209972 extra.cond.fmt(function_index, self),
......@@ -10125,7 +9977,7 @@ pub fn printUnbuffered(
101259977 .shufflevector => |tag| {
101269978 const extra =
101279979 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
10128 try writer.print(" %{} = {s} {%}, {%}, {%}", .{
9980 try w.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
101299981 instruction_index.name(&function).fmt(self),
101309982 @tagName(tag),
101319983 extra.lhs.fmt(function_index, self),
......@@ -10137,7 +9989,7 @@ pub fn printUnbuffered(
101379989 .@"store atomic",
101389990 => |tag| {
101399991 const extra = function.extraData(Function.Instruction.Store, instruction.data);
10140 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{
9992 try w.print(" {s}{f } {f%}, {f%}{f }{f }{f, }", .{
101419993 @tagName(tag),
101429994 extra.info.access_kind,
101439995 extra.val.fmt(function_index, self),
......@@ -10153,32 +10005,32 @@ pub fn printUnbuffered(
1015310005 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
1015410006 const blocks =
1015510007 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
10156 try writer.print(" {s} {%}, {%} [\n", .{
10008 try w.print(" {s} {f%}, {f%} [\n", .{
1015710009 @tagName(tag),
1015810010 extra.data.val.fmt(function_index, self),
1015910011 extra.data.default.toInst(&function).fmt(function_index, self),
1016010012 });
10161 for (vals, blocks) |case_val, case_block| try writer.print(
10162 " {%}, {%}\n",
10013 for (vals, blocks) |case_val, case_block| try w.print(
10014 " {f%}, {f%}\n",
1016310015 .{
1016410016 case_val.fmt(self),
1016510017 case_block.toInst(&function).fmt(function_index, self),
1016610018 },
1016710019 );
10168 try writer.writeAll(" ]");
10020 try w.writeAll(" ]");
1016910021 metadata_formatter.need_comma = true;
1017010022 defer metadata_formatter.need_comma = undefined;
1017110023 switch (extra.data.weights) {
1017210024 .none => {},
10173 .unpredictable => try writer.writeAll("!unpredictable !{}"),
10174 _ => try writer.print("{}", .{
10025 .unpredictable => try w.writeAll("!unpredictable !{}"),
10026 _ => try w.print("{f}", .{
1017510027 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),
1017610028 }),
1017710029 }
1017810030 },
1017910031 .va_arg => |tag| {
1018010032 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
10181 try writer.print(" %{} = {s} {%}, {%}", .{
10033 try w.print(" %{f} = {s} {f%}, {f%}", .{
1018210034 instruction_index.name(&function).fmt(self),
1018310035 @tagName(tag),
1018410036 extra.list.fmt(function_index, self),
......@@ -10188,45 +10040,45 @@ pub fn printUnbuffered(
1018810040 }
1018910041
1019010042 if (maybe_dbg_index) |dbg_index| {
10191 try writer.print(", !dbg !{}", .{dbg_index});
10043 try w.print(", !dbg !{d}", .{dbg_index});
1019210044 }
10193 try writer.writeByte('\n');
10045 try w.writeByte('\n');
1019410046 }
10195 try writer.writeByte('}');
10047 try w.writeByte('}');
1019610048 }
10197 try writer.writeByte('\n');
10049 try w.writeByte('\n');
1019810050 }
1019910051
1020010052 if (attribute_groups.count() > 0) {
10201 if (need_newline) try writer.writeByte('\n') else need_newline = true;
10053 if (need_newline) try w.writeByte('\n') else need_newline = true;
1020210054 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
10203 try writer.print(
10204 \\attributes #{d} = {{{#"} }}
10055 try w.print(
10056 \\attributes #{d} = {{{f#"} }}
1020510057 \\
1020610058 , .{ attribute_group_index, attribute_group.fmt(self) });
1020710059 }
1020810060
1020910061 if (self.metadata_named.count() > 0) {
10210 if (need_newline) try writer.writeByte('\n') else need_newline = true;
10062 if (need_newline) try w.writeByte('\n') else need_newline = true;
1021110063 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {
1021210064 const elements: []const Metadata =
1021310065 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);
10214 try writer.writeByte('!');
10215 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer);
10216 try writer.writeAll(" = !{");
10066 try w.writeByte('!');
10067 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, w);
10068 try w.writeAll(" = !{");
1021710069 metadata_formatter.need_comma = false;
1021810070 defer metadata_formatter.need_comma = undefined;
10219 for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)});
10220 try writer.writeAll("}\n");
10071 for (elements) |element| try w.print("{f}", .{try metadata_formatter.fmt("", element)});
10072 try w.writeAll("}\n");
1022110073 }
1022210074 }
1022310075
1022410076 if (metadata_formatter.map.count() > 0) {
10225 if (need_newline) try writer.writeByte('\n') else need_newline = true;
10077 if (need_newline) try w.writeByte('\n') else need_newline = true;
1022610078 var metadata_index: usize = 0;
1022710079 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
1022810080 @setEvalBranchQuota(10_000);
10229 try writer.print("!{} = ", .{metadata_index});
10081 try w.print("!{d} = ", .{metadata_index});
1023010082 metadata_formatter.need_comma = false;
1023110083 defer metadata_formatter.need_comma = undefined;
1023210084
......@@ -10239,7 +10091,7 @@ pub fn printUnbuffered(
1023910091 .scope = location.scope,
1024010092 .inlinedAt = location.inlined_at,
1024110093 .isImplicitCode = false,
10242 }, writer);
10094 }, w);
1024310095 continue;
1024410096 },
1024510097 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),
......@@ -10255,7 +10107,7 @@ pub fn printUnbuffered(
1025510107 .checksumkind = null,
1025610108 .checksum = null,
1025710109 .source = null,
10258 }, writer);
10110 }, w);
1025910111 },
1026010112 .compile_unit,
1026110113 .@"compile_unit optimized",
......@@ -10286,7 +10138,7 @@ pub fn printUnbuffered(
1028610138 .rangesBaseAddress = null,
1028710139 .sysroot = null,
1028810140 .sdk = null,
10289 }, writer);
10141 }, w);
1029010142 },
1029110143 .subprogram,
1029210144 .@"subprogram local",
......@@ -10320,7 +10172,7 @@ pub fn printUnbuffered(
1032010172 .thrownTypes = null,
1032110173 .annotations = null,
1032210174 .targetFuncName = null,
10323 }, writer);
10175 }, w);
1032410176 },
1032510177 .lexical_block => {
1032610178 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);
......@@ -10329,7 +10181,7 @@ pub fn printUnbuffered(
1032910181 .file = extra.file,
1033010182 .line = extra.line,
1033110183 .column = extra.column,
10332 }, writer);
10184 }, w);
1033310185 },
1033410186 .location => {
1033510187 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);
......@@ -10339,7 +10191,7 @@ pub fn printUnbuffered(
1033910191 .scope = extra.scope,
1034010192 .inlinedAt = extra.inlined_at,
1034110193 .isImplicitCode = false,
10342 }, writer);
10194 }, w);
1034310195 },
1034410196 .basic_bool_type,
1034510197 .basic_unsigned_type,
......@@ -10368,7 +10220,7 @@ pub fn printUnbuffered(
1036810220 else => unreachable,
1036910221 }),
1037010222 .flags = null,
10371 }, writer);
10223 }, w);
1037210224 },
1037310225 .composite_struct_type,
1037410226 .composite_union_type,
......@@ -10413,7 +10265,7 @@ pub fn printUnbuffered(
1041310265 .allocated = null,
1041410266 .rank = null,
1041510267 .annotations = null,
10416 }, writer);
10268 }, w);
1041710269 },
1041810270 .derived_pointer_type,
1041910271 .derived_member_type,
......@@ -10446,7 +10298,7 @@ pub fn printUnbuffered(
1044610298 .extraData = null,
1044710299 .dwarfAddressSpace = null,
1044810300 .annotations = null,
10449 }, writer);
10301 }, w);
1045010302 },
1045110303 .subroutine_type => {
1045210304 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
......@@ -10454,7 +10306,7 @@ pub fn printUnbuffered(
1045410306 .flags = null,
1045510307 .cc = null,
1045610308 .types = extra.types_tuple,
10457 }, writer);
10309 }, w);
1045810310 },
1045910311 .enumerator_unsigned,
1046010312 .enumerator_signed_positive,
......@@ -10504,7 +10356,7 @@ pub fn printUnbuffered(
1050410356 => false,
1050510357 else => unreachable,
1050610358 },
10507 }, writer);
10359 }, w);
1050810360 },
1050910361 .subrange => {
1051010362 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);
......@@ -10513,31 +10365,31 @@ pub fn printUnbuffered(
1051310365 .lowerBound = extra.lower_bound,
1051410366 .upperBound = null,
1051510367 .stride = null,
10516 }, writer);
10368 }, w);
1051710369 },
1051810370 .tuple => {
1051910371 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);
1052010372 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10521 try writer.writeAll("!{");
10522 for (elements) |element| try writer.print("{[element]%}", .{
10373 try w.writeAll("!{");
10374 for (elements) |element| try w.print("{[element]f%}", .{
1052310375 .element = try metadata_formatter.fmt("", element),
1052410376 });
10525 try writer.writeAll("}\n");
10377 try w.writeAll("}\n");
1052610378 },
1052710379 .str_tuple => {
1052810380 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);
1052910381 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10530 try writer.print("!{{{[str]%}", .{
10382 try w.print("!{{{[str]f%}", .{
1053110383 .str = try metadata_formatter.fmt("", extra.data.str),
1053210384 });
10533 for (elements) |element| try writer.print("{[element]%}", .{
10385 for (elements) |element| try w.print("{[element]f%}", .{
1053410386 .element = try metadata_formatter.fmt("", element),
1053510387 });
10536 try writer.writeAll("}\n");
10388 try w.writeAll("}\n");
1053710389 },
1053810390 .module_flag => {
1053910391 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);
10540 try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{
10392 try w.print("!{{{[behavior]f%}{[name]f%}{[constant]f%}}}\n", .{
1054110393 .behavior = try metadata_formatter.fmt("", extra.behavior),
1054210394 .name = try metadata_formatter.fmt("", extra.name),
1054310395 .constant = try metadata_formatter.fmt("", extra.constant),
......@@ -10555,7 +10407,7 @@ pub fn printUnbuffered(
1055510407 .flags = null,
1055610408 .@"align" = null,
1055710409 .annotations = null,
10558 }, writer);
10410 }, w);
1055910411 },
1056010412 .parameter => {
1056110413 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);
......@@ -10569,7 +10421,7 @@ pub fn printUnbuffered(
1056910421 .flags = null,
1057010422 .@"align" = null,
1057110423 .annotations = null,
10572 }, writer);
10424 }, w);
1057310425 },
1057410426 .global_var,
1057510427 .@"global_var local",
......@@ -10592,7 +10444,7 @@ pub fn printUnbuffered(
1059210444 .templateParams = null,
1059310445 .@"align" = null,
1059410446 .annotations = null,
10595 }, writer);
10447 }, w);
1059610448 },
1059710449 .global_var_expression => {
1059810450 const extra =
......@@ -10600,7 +10452,7 @@ pub fn printUnbuffered(
1060010452 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{
1060110453 .@"var" = extra.variable,
1060210454 .expr = extra.expression,
10603 }, writer);
10455 }, w);
1060410456 },
1060510457 }
1060610458 }
......@@ -10619,22 +10471,18 @@ fn isValidIdentifier(id: []const u8) bool {
1061910471}
1062010472
1062110473const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };
10622fn printEscapedString(
10623 slice: []const u8,
10624 quotes: QuoteBehavior,
10625 writer: anytype,
10626) @TypeOf(writer).Error!void {
10474fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, w: *Writer) Writer.Error!void {
1062710475 const need_quotes = switch (quotes) {
1062810476 .always_quote => true,
1062910477 .quote_unless_valid_identifier => !isValidIdentifier(slice),
1063010478 };
10631 if (need_quotes) try writer.writeByte('"');
10479 if (need_quotes) try w.writeByte('"');
1063210480 for (slice) |byte| switch (byte) {
10633 '\\' => try writer.writeAll("\\\\"),
10634 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(byte),
10635 else => try writer.print("\\{X:0>2}", .{byte}),
10481 '\\' => try w.writeAll("\\\\"),
10482 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try w.writeByte(byte),
10483 else => try w.print("\\{X:0>2}", .{byte}),
1063610484 };
10637 if (need_quotes) try writer.writeByte('"');
10485 if (need_quotes) try w.writeByte('"');
1063810486}
1063910487
1064010488fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {
......@@ -12019,7 +11867,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:
1201911867}
1202011868
1202111869pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {
12022 self.metadata_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
11870 self.metadata_string_bytes.printAssumeCapacity(fmt_str, fmt_args);
1202311871 return self.trailingMetadataStringAssumeCapacity();
1202411872}
1202511873
......@@ -15261,13 +15109,3 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1526115109
1526215110 return bitcode.toOwnedSlice();
1526315111}
15264
15265const Allocator = std.mem.Allocator;
15266const assert = std.debug.assert;
15267const bitcode_writer = @import("bitcode_writer.zig");
15268const Builder = @This();
15269const builtin = @import("builtin");
15270const DW = std.dwarf;
15271const ir = @import("ir.zig");
15272const log = std.log.scoped(.llvm);
15273const std = @import("../../std.zig");
lib/std/zig/parser_test.zig+1-1
......@@ -6324,7 +6324,7 @@ test "ampersand" {
63246324var fixed_buffer_mem: [100 * 1024]u8 = undefined;
63256325
63266326fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
6327 const stderr = std.fs.File.stderr().writer();
6327 const stderr = std.fs.File.stderr().deprecatedWriter();
63286328
63296329 var tree = try std.zig.Ast.parse(allocator, source, .zig);
63306330 defer tree.deinit(allocator);
lib/std/zig/perf_test.zig+1-1
......@@ -23,7 +23,7 @@ pub fn main() !void {
2323 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));
2424
2525 var stdout_file: std.fs.File = .stdout();
26 const stdout = stdout_file.writer();
26 const stdout = stdout_file.deprecatedWriter();
2727 try stdout.print("parsing speed: {:.2}/s, {:.2} used \n", .{
2828 fmtIntSizeBin(bytes_per_sec),
2929 fmtIntSizeBin(memory_used),
lib/std/zig/render.zig+3-3
......@@ -1564,7 +1564,7 @@ fn renderBuiltinCall(
15641564 defer r.gpa.free(new_string);
15651565
15661566 try renderToken(r, builtin_token + 1, .none); // (
1567 try ais.writer().print("\"{}\"", .{std.zig.fmtEscapes(new_string)});
1567 try ais.writer().print("\"{f}\"", .{std.zig.fmtString(new_string)});
15681568 return renderToken(r, str_lit_token + 1, space); // )
15691569 }
15701570 }
......@@ -2872,7 +2872,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
28722872 .success => |codepoint| {
28732873 if (codepoint <= 0x7f) {
28742874 const buf = [1]u8{@as(u8, @intCast(codepoint))};
2875 try std.fmt.format(writer, "{}", .{std.zig.fmtEscapes(&buf)});
2875 try std.fmt.deprecatedFormat(writer, "{f}", .{std.zig.fmtString(&buf)});
28762876 } else {
28772877 try writer.writeAll(escape_sequence);
28782878 }
......@@ -2884,7 +2884,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
28842884 },
28852885 0x00...('\\' - 1), ('\\' + 1)...0x7f => {
28862886 const buf = [1]u8{byte};
2887 try std.fmt.format(writer, "{}", .{std.zig.fmtEscapes(&buf)});
2887 try std.fmt.deprecatedFormat(writer, "{f}", .{std.zig.fmtString(&buf)});
28882888 pos += 1;
28892889 },
28902890 0x80...0xff => {
lib/std/zig/string_literal.zig+2-9
......@@ -44,14 +44,7 @@ pub const Error = union(enum) {
4444 raw_string: []const u8,
4545 };
4646
47 fn formatMessage(
48 self: FormatMessage,
49 comptime f: []const u8,
50 options: std.fmt.FormatOptions,
51 writer: anytype,
52 ) !void {
53 _ = f;
54 _ = options;
47 fn formatMessage(self: FormatMessage, writer: *std.io.Writer) std.io.Writer.Error!void {
5548 switch (self.err) {
5649 .invalid_escape_character => |bad_index| try writer.print(
5750 "invalid escape character: '{c}'",
......@@ -93,7 +86,7 @@ pub const Error = union(enum) {
9386 }
9487 }
9588
96 pub fn fmt(self: @This(), raw_string: []const u8) std.fmt.Formatter(formatMessage) {
89 pub fn fmt(self: @This(), raw_string: []const u8) std.fmt.Formatter(FormatMessage, formatMessage) {
9790 return .{ .data = .{
9891 .err = self,
9992 .raw_string = raw_string,
lib/std/zip.zig+1-1
......@@ -557,7 +557,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
557557 self.compression_method,
558558 self.uncompressed_size,
559559 limited_reader.reader(),
560 out_file.writer(),
560 out_file.deprecatedWriter(),
561561 );
562562 if (limited_reader.bytes_left != 0)
563563 return error.ZipDecompressTruncated;
lib/std/zip/test.zig+1-1
......@@ -33,7 +33,7 @@ pub fn expectFiles(
3333 var file = try dir.openFile(normalized_sub_path, .{});
3434 defer file.close();
3535 var content_buf: [4096]u8 = undefined;
36 const n = try file.reader().readAll(&content_buf);
36 const n = try file.deprecatedReader().readAll(&content_buf);
3737 try testing.expectEqualStrings(test_file.content, content_buf[0..n]);
3838 }
3939}
lib/std/zon/parse.zig+112-130
......@@ -64,22 +64,14 @@ pub const Error = union(enum) {
6464 }
6565 };
6666
67 fn formatMessage(
68 self: []const u8,
69 comptime f: []const u8,
70 options: std.fmt.FormatOptions,
71 writer: anytype,
72 ) !void {
73 _ = f;
74 _ = options;
75
67 fn formatMessage(self: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
7668 // Just writes the string for now, but we're keeping this behind a formatter so we have
7769 // the option to extend it in the future to print more advanced messages (like `Error`
7870 // does) without breaking the API.
79 try writer.writeAll(self);
71 try w.writeAll(self);
8072 }
8173
82 pub fn fmtMessage(self: Note, diag: *const Diagnostics) std.fmt.Formatter(Note.formatMessage) {
74 pub fn fmtMessage(self: Note, diag: *const Diagnostics) std.fmt.Formatter([]const u8, Note.formatMessage) {
8375 return .{ .data = switch (self) {
8476 .zoir => |note| note.msg.get(diag.zoir),
8577 .type_check => |note| note.msg,
......@@ -155,21 +147,14 @@ pub const Error = union(enum) {
155147 diag: *const Diagnostics,
156148 };
157149
158 fn formatMessage(
159 self: FormatMessage,
160 comptime f: []const u8,
161 options: std.fmt.FormatOptions,
162 writer: anytype,
163 ) !void {
164 _ = f;
165 _ = options;
150 fn formatMessage(self: FormatMessage, w: *std.io.Writer) std.io.Writer.Error!void {
166151 switch (self.err) {
167 .zoir => |err| try writer.writeAll(err.msg.get(self.diag.zoir)),
168 .type_check => |tc| try writer.writeAll(tc.message),
152 .zoir => |err| try w.writeAll(err.msg.get(self.diag.zoir)),
153 .type_check => |tc| try w.writeAll(tc.message),
169154 }
170155 }
171156
172 pub fn fmtMessage(self: @This(), diag: *const Diagnostics) std.fmt.Formatter(formatMessage) {
157 pub fn fmtMessage(self: @This(), diag: *const Diagnostics) std.fmt.Formatter(FormatMessage, formatMessage) {
173158 return .{ .data = .{
174159 .err = self,
175160 .diag = diag,
......@@ -241,25 +226,19 @@ pub const Diagnostics = struct {
241226 return .{ .diag = self };
242227 }
243228
244 pub fn format(
245 self: *const @This(),
246 comptime fmt: []const u8,
247 options: std.fmt.FormatOptions,
248 writer: anytype,
249 ) !void {
250 _ = fmt;
251 _ = options;
229 pub fn format(self: *const @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
230 comptime assert(fmt.len == 0);
252231 var errors = self.iterateErrors();
253232 while (errors.next()) |err| {
254233 const loc = err.getLocation(self);
255234 const msg = err.fmtMessage(self);
256 try writer.print("{}:{}: error: {}\n", .{ loc.line + 1, loc.column + 1, msg });
235 try w.print("{d}:{d}: error: {f}\n", .{ loc.line + 1, loc.column + 1, msg });
257236
258237 var notes = err.iterateNotes(self);
259238 while (notes.next()) |note| {
260239 const note_loc = note.getLocation(self);
261240 const note_msg = note.fmtMessage(self);
262 try writer.print("{}:{}: note: {s}\n", .{
241 try w.print("{d}:{d}: note: {f}\n", .{
263242 note_loc.line + 1,
264243 note_loc.column + 1,
265244 note_msg,
......@@ -646,7 +625,7 @@ const Parser = struct {
646625 .failure => |err| {
647626 const token = self.ast.nodeMainToken(ast_node);
648627 const raw_string = self.ast.tokenSlice(token);
649 return self.failTokenFmt(token, @intCast(err.offset()), "{s}", .{err.fmt(raw_string)});
628 return self.failTokenFmt(token, @intCast(err.offset()), "{f}", .{err.fmt(raw_string)});
650629 },
651630 }
652631
......@@ -1087,7 +1066,10 @@ const Parser = struct {
10871066 try writer.writeAll(msg);
10881067 inline for (info.fields, 0..) |field_info, i| {
10891068 if (i != 0) try writer.writeAll(", ");
1090 try writer.print("'{p_}'", .{std.zig.fmtId(field_info.name)});
1069 try writer.print("'{f}'", .{std.zig.fmtIdFlags(field_info.name, .{
1070 .allow_primitive = true,
1071 .allow_underscore = true,
1072 })});
10911073 }
10921074 break :b .{
10931075 .token = token,
......@@ -1298,7 +1280,7 @@ test "std.zon ast errors" {
12981280 error.ParseZon,
12991281 fromSlice(struct {}, gpa, ".{.x = 1 .y = 2}", &diag, .{}),
13001282 );
1301 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{}", .{diag});
1283 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{diag});
13021284}
13031285
13041286test "std.zon comments" {
......@@ -1320,7 +1302,7 @@ test "std.zon comments" {
13201302 , &diag, .{}));
13211303 try std.testing.expectFmt(
13221304 "1:1: error: expected expression, found 'a document comment'\n",
1323 "{}",
1305 "{f}",
13241306 .{diag},
13251307 );
13261308 }
......@@ -1341,7 +1323,7 @@ test "std.zon failure/oom formatting" {
13411323 &diag,
13421324 .{},
13431325 ));
1344 try std.testing.expectFmt("", "{}", .{diag});
1326 try std.testing.expectFmt("", "{f}", .{diag});
13451327}
13461328
13471329test "std.zon fromSlice syntax error" {
......@@ -1421,7 +1403,7 @@ test "std.zon unions" {
14211403 \\1:4: note: supported: 'x', 'y'
14221404 \\
14231405 ,
1424 "{}",
1406 "{f}",
14251407 .{diag},
14261408 );
14271409 }
......@@ -1435,7 +1417,7 @@ test "std.zon unions" {
14351417 error.ParseZon,
14361418 fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),
14371419 );
1438 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{}", .{diag});
1420 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
14391421 }
14401422
14411423 // Extra field
......@@ -1447,7 +1429,7 @@ test "std.zon unions" {
14471429 error.ParseZon,
14481430 fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
14491431 );
1450 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});
1432 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14511433 }
14521434
14531435 // No fields
......@@ -1459,7 +1441,7 @@ test "std.zon unions" {
14591441 error.ParseZon,
14601442 fromSlice(Union, gpa, ".{}", &diag, .{}),
14611443 );
1462 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});
1444 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14631445 }
14641446
14651447 // Enum literals cannot coerce into untagged unions
......@@ -1468,7 +1450,7 @@ test "std.zon unions" {
14681450 var diag: Diagnostics = .{};
14691451 defer diag.deinit(gpa);
14701452 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
1471 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});
1453 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14721454 }
14731455
14741456 // Unknown field for enum literal coercion
......@@ -1482,7 +1464,7 @@ test "std.zon unions" {
14821464 \\1:2: note: supported: 'x'
14831465 \\
14841466 ,
1485 "{}",
1467 "{f}",
14861468 .{diag},
14871469 );
14881470 }
......@@ -1493,7 +1475,7 @@ test "std.zon unions" {
14931475 var diag: Diagnostics = .{};
14941476 defer diag.deinit(gpa);
14951477 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
1496 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});
1478 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14971479 }
14981480}
14991481
......@@ -1549,7 +1531,7 @@ test "std.zon structs" {
15491531 \\1:12: note: supported: 'x', 'y'
15501532 \\
15511533 ,
1552 "{}",
1534 "{f}",
15531535 .{diag},
15541536 );
15551537 }
......@@ -1567,7 +1549,7 @@ test "std.zon structs" {
15671549 \\1:4: error: duplicate struct field name
15681550 \\1:12: note: duplicate name here
15691551 \\
1570 , "{}", .{diag});
1552 , "{f}", .{diag});
15711553 }
15721554
15731555 // Ignore unknown fields
......@@ -1592,7 +1574,7 @@ test "std.zon structs" {
15921574 \\1:4: error: unexpected field 'x'
15931575 \\1:4: note: none expected
15941576 \\
1595 , "{}", .{diag});
1577 , "{f}", .{diag});
15961578 }
15971579
15981580 // Missing field
......@@ -1604,7 +1586,7 @@ test "std.zon structs" {
16041586 error.ParseZon,
16051587 fromSlice(Vec2, gpa, ".{.x=1.5}", &diag, .{}),
16061588 );
1607 try std.testing.expectFmt("1:2: error: missing required field y\n", "{}", .{diag});
1589 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{diag});
16081590 }
16091591
16101592 // Default field
......@@ -1631,7 +1613,7 @@ test "std.zon structs" {
16311613 try std.testing.expectFmt(
16321614 \\1:18: error: cannot initialize comptime field
16331615 \\
1634 , "{}", .{diag});
1616 , "{f}", .{diag});
16351617 }
16361618
16371619 // Enum field (regression test, we were previously getting the field name in an
......@@ -1661,7 +1643,7 @@ test "std.zon structs" {
16611643 \\1:1: error: types are not available in ZON
16621644 \\1:1: note: replace the type with '.'
16631645 \\
1664 , "{}", .{diag});
1646 , "{f}", .{diag});
16651647 }
16661648
16671649 // Arrays
......@@ -1674,7 +1656,7 @@ test "std.zon structs" {
16741656 \\1:1: error: types are not available in ZON
16751657 \\1:1: note: replace the type with '.'
16761658 \\
1677 , "{}", .{diag});
1659 , "{f}", .{diag});
16781660 }
16791661
16801662 // Slices
......@@ -1687,7 +1669,7 @@ test "std.zon structs" {
16871669 \\1:1: error: types are not available in ZON
16881670 \\1:1: note: replace the type with '.'
16891671 \\
1690 , "{}", .{diag});
1672 , "{f}", .{diag});
16911673 }
16921674
16931675 // Tuples
......@@ -1706,7 +1688,7 @@ test "std.zon structs" {
17061688 \\1:1: error: types are not available in ZON
17071689 \\1:1: note: replace the type with '.'
17081690 \\
1709 , "{}", .{diag});
1691 , "{f}", .{diag});
17101692 }
17111693
17121694 // Nested
......@@ -1719,7 +1701,7 @@ test "std.zon structs" {
17191701 \\1:9: error: types are not available in ZON
17201702 \\1:9: note: replace the type with '.'
17211703 \\
1722 , "{}", .{diag});
1704 , "{f}", .{diag});
17231705 }
17241706 }
17251707}
......@@ -1764,7 +1746,7 @@ test "std.zon tuples" {
17641746 error.ParseZon,
17651747 fromSlice(Tuple, gpa, ".{0.5, true, 123}", &diag, .{}),
17661748 );
1767 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{}", .{diag});
1749 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{diag});
17681750 }
17691751
17701752 // Extra field
......@@ -1778,7 +1760,7 @@ test "std.zon tuples" {
17781760 );
17791761 try std.testing.expectFmt(
17801762 "1:2: error: missing tuple field with index 1\n",
1781 "{}",
1763 "{f}",
17821764 .{diag},
17831765 );
17841766 }
......@@ -1792,7 +1774,7 @@ test "std.zon tuples" {
17921774 error.ParseZon,
17931775 fromSlice(Tuple, gpa, ".{.foo = 10.0}", &diag, .{}),
17941776 );
1795 try std.testing.expectFmt("1:2: error: expected tuple\n", "{}", .{diag});
1777 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{diag});
17961778 }
17971779
17981780 // Struct with missing field names
......@@ -1804,7 +1786,7 @@ test "std.zon tuples" {
18041786 error.ParseZon,
18051787 fromSlice(Struct, gpa, ".{10.0}", &diag, .{}),
18061788 );
1807 try std.testing.expectFmt("1:2: error: expected struct\n", "{}", .{diag});
1789 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{diag});
18081790 }
18091791
18101792 // Comptime field
......@@ -1824,7 +1806,7 @@ test "std.zon tuples" {
18241806 try std.testing.expectFmt(
18251807 \\1:9: error: cannot initialize comptime field
18261808 \\
1827 , "{}", .{diag});
1809 , "{f}", .{diag});
18281810 }
18291811}
18301812
......@@ -1936,7 +1918,7 @@ test "std.zon arrays and slices" {
19361918 );
19371919 try std.testing.expectFmt(
19381920 "1:3: error: index 0 outside of array of length 0\n",
1939 "{}",
1921 "{f}",
19401922 .{diag},
19411923 );
19421924 }
......@@ -1951,7 +1933,7 @@ test "std.zon arrays and slices" {
19511933 );
19521934 try std.testing.expectFmt(
19531935 "1:8: error: index 1 outside of array of length 1\n",
1954 "{}",
1936 "{f}",
19551937 .{diag},
19561938 );
19571939 }
......@@ -1966,7 +1948,7 @@ test "std.zon arrays and slices" {
19661948 );
19671949 try std.testing.expectFmt(
19681950 "1:2: error: expected 2 array elements; found 1\n",
1969 "{}",
1951 "{f}",
19701952 .{diag},
19711953 );
19721954 }
......@@ -1981,7 +1963,7 @@ test "std.zon arrays and slices" {
19811963 );
19821964 try std.testing.expectFmt(
19831965 "1:2: error: expected 3 array elements; found 0\n",
1984 "{}",
1966 "{f}",
19851967 .{diag},
19861968 );
19871969 }
......@@ -1996,7 +1978,7 @@ test "std.zon arrays and slices" {
19961978 error.ParseZon,
19971979 fromSlice([3]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
19981980 );
1999 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{}", .{diag});
1981 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
20001982 }
20011983
20021984 // Slice
......@@ -2007,7 +1989,7 @@ test "std.zon arrays and slices" {
20071989 error.ParseZon,
20081990 fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
20091991 );
2010 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{}", .{diag});
1992 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
20111993 }
20121994 }
20131995
......@@ -2021,7 +2003,7 @@ test "std.zon arrays and slices" {
20212003 error.ParseZon,
20222004 fromSlice([3]u8, gpa, "'a'", &diag, .{}),
20232005 );
2024 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2006 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20252007 }
20262008
20272009 // Slice
......@@ -2032,7 +2014,7 @@ test "std.zon arrays and slices" {
20322014 error.ParseZon,
20332015 fromSlice([]u8, gpa, "'a'", &diag, .{}),
20342016 );
2035 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2017 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20362018 }
20372019 }
20382020
......@@ -2046,7 +2028,7 @@ test "std.zon arrays and slices" {
20462028 );
20472029 try std.testing.expectFmt(
20482030 "1:3: error: pointers are not available in ZON\n",
2049 "{}",
2031 "{f}",
20502032 .{diag},
20512033 );
20522034 }
......@@ -2085,7 +2067,7 @@ test "std.zon string literal" {
20852067 error.ParseZon,
20862068 fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),
20872069 );
2088 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2070 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20892071 }
20902072
20912073 {
......@@ -2095,7 +2077,7 @@ test "std.zon string literal" {
20952077 error.ParseZon,
20962078 fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),
20972079 );
2098 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2080 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20992081 }
21002082 }
21012083
......@@ -2112,7 +2094,7 @@ test "std.zon string literal" {
21122094 error.ParseZon,
21132095 fromSlice([4:0]u8, gpa, "\"abcd\"", &diag, .{}),
21142096 );
2115 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2097 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21162098 }
21172099
21182100 {
......@@ -2122,7 +2104,7 @@ test "std.zon string literal" {
21222104 error.ParseZon,
21232105 fromSlice([4:0]u8, gpa, "\\\\abcd", &diag, .{}),
21242106 );
2125 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2107 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21262108 }
21272109 }
21282110
......@@ -2164,7 +2146,7 @@ test "std.zon string literal" {
21642146 error.ParseZon,
21652147 fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),
21662148 );
2167 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2149 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21682150 }
21692151
21702152 {
......@@ -2174,7 +2156,7 @@ test "std.zon string literal" {
21742156 error.ParseZon,
21752157 fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),
21762158 );
2177 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2159 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21782160 }
21792161 }
21802162
......@@ -2186,7 +2168,7 @@ test "std.zon string literal" {
21862168 error.ParseZon,
21872169 fromSlice([]const u8, gpa, "true", &diag, .{}),
21882170 );
2189 try std.testing.expectFmt("1:1: error: expected string\n", "{}", .{diag});
2171 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
21902172 }
21912173
21922174 // Expecting string literal, getting an incompatible tuple
......@@ -2197,7 +2179,7 @@ test "std.zon string literal" {
21972179 error.ParseZon,
21982180 fromSlice([]const u8, gpa, ".{false}", &diag, .{}),
21992181 );
2200 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{}", .{diag});
2182 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
22012183 }
22022184
22032185 // Invalid string literal
......@@ -2208,7 +2190,7 @@ test "std.zon string literal" {
22082190 error.ParseZon,
22092191 fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),
22102192 );
2211 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{}", .{diag});
2193 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
22122194 }
22132195
22142196 // Slice wrong child type
......@@ -2220,7 +2202,7 @@ test "std.zon string literal" {
22202202 error.ParseZon,
22212203 fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),
22222204 );
2223 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2205 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22242206 }
22252207
22262208 {
......@@ -2230,7 +2212,7 @@ test "std.zon string literal" {
22302212 error.ParseZon,
22312213 fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),
22322214 );
2233 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2215 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22342216 }
22352217 }
22362218
......@@ -2243,7 +2225,7 @@ test "std.zon string literal" {
22432225 error.ParseZon,
22442226 fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
22452227 );
2246 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2228 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22472229 }
22482230
22492231 {
......@@ -2253,7 +2235,7 @@ test "std.zon string literal" {
22532235 error.ParseZon,
22542236 fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
22552237 );
2256 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});
2238 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22572239 }
22582240 }
22592241
......@@ -2327,7 +2309,7 @@ test "std.zon enum literals" {
23272309 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
23282310 \\
23292311 ,
2330 "{}",
2312 "{f}",
23312313 .{diag},
23322314 );
23332315 }
......@@ -2345,7 +2327,7 @@ test "std.zon enum literals" {
23452327 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
23462328 \\
23472329 ,
2348 "{}",
2330 "{f}",
23492331 .{diag},
23502332 );
23512333 }
......@@ -2358,7 +2340,7 @@ test "std.zon enum literals" {
23582340 error.ParseZon,
23592341 fromSlice(Enum, gpa, "true", &diag, .{}),
23602342 );
2361 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{}", .{diag});
2343 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{diag});
23622344 }
23632345
23642346 // Test embedded nulls in an identifier
......@@ -2371,7 +2353,7 @@ test "std.zon enum literals" {
23712353 );
23722354 try std.testing.expectFmt(
23732355 "1:2: error: identifier cannot contain null bytes\n",
2374 "{}",
2356 "{f}",
23752357 .{diag},
23762358 );
23772359 }
......@@ -2397,13 +2379,13 @@ test "std.zon parse bool" {
23972379 \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
23982380 \\1:2: note: precede identifier with '.' for an enum literal
23992381 \\
2400 , "{}", .{diag});
2382 , "{f}", .{diag});
24012383 }
24022384 {
24032385 var diag: Diagnostics = .{};
24042386 defer diag.deinit(gpa);
24052387 try std.testing.expectError(error.ParseZon, fromSlice(bool, gpa, "123", &diag, .{}));
2406 try std.testing.expectFmt("1:1: error: expected type 'bool'\n", "{}", .{diag});
2388 try std.testing.expectFmt("1:1: error: expected type 'bool'\n", "{f}", .{diag});
24072389 }
24082390}
24092391
......@@ -2476,7 +2458,7 @@ test "std.zon parse int" {
24762458 ));
24772459 try std.testing.expectFmt(
24782460 "1:1: error: type 'i66' cannot represent value\n",
2479 "{}",
2461 "{f}",
24802462 .{diag},
24812463 );
24822464 }
......@@ -2492,7 +2474,7 @@ test "std.zon parse int" {
24922474 ));
24932475 try std.testing.expectFmt(
24942476 "1:1: error: type 'i66' cannot represent value\n",
2495 "{}",
2477 "{f}",
24962478 .{diag},
24972479 );
24982480 }
......@@ -2581,7 +2563,7 @@ test "std.zon parse int" {
25812563 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{}));
25822564 try std.testing.expectFmt(
25832565 "1:3: error: invalid digit 'a' for decimal base\n",
2584 "{}",
2566 "{f}",
25852567 .{diag},
25862568 );
25872569 }
......@@ -2591,7 +2573,7 @@ test "std.zon parse int" {
25912573 var diag: Diagnostics = .{};
25922574 defer diag.deinit(gpa);
25932575 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "true", &diag, .{}));
2594 try std.testing.expectFmt("1:1: error: expected type 'u8'\n", "{}", .{diag});
2576 try std.testing.expectFmt("1:1: error: expected type 'u8'\n", "{f}", .{diag});
25952577 }
25962578
25972579 // Failing because an int is out of range
......@@ -2601,7 +2583,7 @@ test "std.zon parse int" {
26012583 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{}));
26022584 try std.testing.expectFmt(
26032585 "1:1: error: type 'u8' cannot represent value\n",
2604 "{}",
2586 "{f}",
26052587 .{diag},
26062588 );
26072589 }
......@@ -2613,7 +2595,7 @@ test "std.zon parse int" {
26132595 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{}));
26142596 try std.testing.expectFmt(
26152597 "1:1: error: type 'i8' cannot represent value\n",
2616 "{}",
2598 "{f}",
26172599 .{diag},
26182600 );
26192601 }
......@@ -2625,7 +2607,7 @@ test "std.zon parse int" {
26252607 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{}));
26262608 try std.testing.expectFmt(
26272609 "1:1: error: type 'u8' cannot represent value\n",
2628 "{}",
2610 "{f}",
26292611 .{diag},
26302612 );
26312613 }
......@@ -2637,7 +2619,7 @@ test "std.zon parse int" {
26372619 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{}));
26382620 try std.testing.expectFmt(
26392621 "1:1: error: type 'u8' cannot represent value\n",
2640 "{}",
2622 "{f}",
26412623 .{diag},
26422624 );
26432625 }
......@@ -2649,7 +2631,7 @@ test "std.zon parse int" {
26492631 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{}));
26502632 try std.testing.expectFmt(
26512633 "1:1: error: type 'u8' cannot represent value\n",
2652 "{}",
2634 "{f}",
26532635 .{diag},
26542636 );
26552637 }
......@@ -2664,7 +2646,7 @@ test "std.zon parse int" {
26642646 \\1:2: note: use '0' for an integer zero
26652647 \\1:2: note: use '-0.0' for a floating-point signed zero
26662648 \\
2667 , "{}", .{diag});
2649 , "{f}", .{diag});
26682650 }
26692651
26702652 // Negative integer zero casted to float
......@@ -2677,7 +2659,7 @@ test "std.zon parse int" {
26772659 \\1:2: note: use '0' for an integer zero
26782660 \\1:2: note: use '-0.0' for a floating-point signed zero
26792661 \\
2680 , "{}", .{diag});
2662 , "{f}", .{diag});
26812663 }
26822664
26832665 // Negative float 0 is allowed
......@@ -2693,7 +2675,7 @@ test "std.zon parse int" {
26932675 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{}));
26942676 try std.testing.expectFmt(
26952677 "1:1: error: expected number or 'inf' after '-'\n",
2696 "{}",
2678 "{f}",
26972679 .{diag},
26982680 );
26992681 }
......@@ -2707,7 +2689,7 @@ test "std.zon parse int" {
27072689 );
27082690 try std.testing.expectFmt(
27092691 "1:1: error: expected number or 'inf' after '-'\n",
2710 "{}",
2692 "{f}",
27112693 .{diag},
27122694 );
27132695 }
......@@ -2717,7 +2699,7 @@ test "std.zon parse int" {
27172699 var diag: Diagnostics = .{};
27182700 defer diag.deinit(gpa);
27192701 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "0xg", &diag, .{}));
2720 try std.testing.expectFmt("1:3: error: invalid digit 'g' for hex base\n", "{}", .{diag});
2702 try std.testing.expectFmt("1:3: error: invalid digit 'g' for hex base\n", "{f}", .{diag});
27212703 }
27222704
27232705 // Notes on invalid int literal
......@@ -2729,7 +2711,7 @@ test "std.zon parse int" {
27292711 \\1:1: error: number '0123' has leading zero
27302712 \\1:1: note: use '0o' prefix for octal literals
27312713 \\
2732 , "{}", .{diag});
2714 , "{f}", .{diag});
27332715 }
27342716}
27352717
......@@ -2742,7 +2724,7 @@ test "std.zon negative char" {
27422724 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{}));
27432725 try std.testing.expectFmt(
27442726 "1:1: error: expected number or 'inf' after '-'\n",
2745 "{}",
2727 "{f}",
27462728 .{diag},
27472729 );
27482730 }
......@@ -2752,7 +2734,7 @@ test "std.zon negative char" {
27522734 try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{}));
27532735 try std.testing.expectFmt(
27542736 "1:1: error: expected number or 'inf' after '-'\n",
2755 "{}",
2737 "{f}",
27562738 .{diag},
27572739 );
27582740 }
......@@ -2839,7 +2821,7 @@ test "std.zon parse float" {
28392821 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{}));
28402822 try std.testing.expectFmt(
28412823 "1:1: error: expected number or 'inf' after '-'\n",
2842 "{}",
2824 "{f}",
28432825 .{diag},
28442826 );
28452827 }
......@@ -2849,7 +2831,7 @@ test "std.zon parse float" {
28492831 var diag: Diagnostics = .{};
28502832 defer diag.deinit(gpa);
28512833 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));
2852 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});
2834 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
28532835 }
28542836
28552837 // nan as int not allowed
......@@ -2857,7 +2839,7 @@ test "std.zon parse float" {
28572839 var diag: Diagnostics = .{};
28582840 defer diag.deinit(gpa);
28592841 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));
2860 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});
2842 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
28612843 }
28622844
28632845 // inf as int not allowed
......@@ -2865,7 +2847,7 @@ test "std.zon parse float" {
28652847 var diag: Diagnostics = .{};
28662848 defer diag.deinit(gpa);
28672849 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "inf", &diag, .{}));
2868 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});
2850 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
28692851 }
28702852
28712853 // -inf as int not allowed
......@@ -2873,7 +2855,7 @@ test "std.zon parse float" {
28732855 var diag: Diagnostics = .{};
28742856 defer diag.deinit(gpa);
28752857 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-inf", &diag, .{}));
2876 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});
2858 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
28772859 }
28782860
28792861 // Bad identifier as float
......@@ -2886,7 +2868,7 @@ test "std.zon parse float" {
28862868 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
28872869 \\1:1: note: precede identifier with '.' for an enum literal
28882870 \\
2889 , "{}", .{diag});
2871 , "{f}", .{diag});
28902872 }
28912873
28922874 {
......@@ -2895,7 +2877,7 @@ test "std.zon parse float" {
28952877 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{}));
28962878 try std.testing.expectFmt(
28972879 "1:1: error: expected number or 'inf' after '-'\n",
2898 "{}",
2880 "{f}",
28992881 .{diag},
29002882 );
29012883 }
......@@ -2908,7 +2890,7 @@ test "std.zon parse float" {
29082890 error.ParseZon,
29092891 fromSlice(f32, gpa, "\"foo\"", &diag, .{}),
29102892 );
2911 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{}", .{diag});
2893 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{diag});
29122894 }
29132895}
29142896
......@@ -3152,7 +3134,7 @@ test "std.zon vector" {
31523134 );
31533135 try std.testing.expectFmt(
31543136 "1:2: error: expected 2 vector elements; found 1\n",
3155 "{}",
3137 "{f}",
31563138 .{diag},
31573139 );
31583140 }
......@@ -3167,7 +3149,7 @@ test "std.zon vector" {
31673149 );
31683150 try std.testing.expectFmt(
31693151 "1:2: error: expected 2 vector elements; found 3\n",
3170 "{}",
3152 "{f}",
31713153 .{diag},
31723154 );
31733155 }
......@@ -3182,7 +3164,7 @@ test "std.zon vector" {
31823164 );
31833165 try std.testing.expectFmt(
31843166 "1:8: error: expected type 'f32'\n",
3185 "{}",
3167 "{f}",
31863168 .{diag},
31873169 );
31883170 }
......@@ -3195,7 +3177,7 @@ test "std.zon vector" {
31953177 error.ParseZon,
31963178 fromSlice(@Vector(3, u8), gpa, "true", &diag, .{}),
31973179 );
3198 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{}", .{diag});
3180 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{diag});
31993181 }
32003182
32013183 // Elements should get freed on error
......@@ -3206,7 +3188,7 @@ test "std.zon vector" {
32063188 error.ParseZon,
32073189 fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
32083190 );
3209 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{}", .{diag});
3191 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{f}", .{diag});
32103192 }
32113193}
32123194
......@@ -3330,7 +3312,7 @@ test "std.zon add pointers" {
33303312 error.ParseZon,
33313313 fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),
33323314 );
3333 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{}", .{diag});
3315 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
33343316 }
33353317
33363318 {
......@@ -3340,7 +3322,7 @@ test "std.zon add pointers" {
33403322 error.ParseZon,
33413323 fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),
33423324 );
3343 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{}", .{diag});
3325 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
33443326 }
33453327
33463328 {
......@@ -3350,7 +3332,7 @@ test "std.zon add pointers" {
33503332 error.ParseZon,
33513333 fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
33523334 );
3353 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{}", .{diag});
3335 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{f}", .{diag});
33543336 }
33553337
33563338 {
......@@ -3360,7 +3342,7 @@ test "std.zon add pointers" {
33603342 error.ParseZon,
33613343 fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),
33623344 );
3363 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{}", .{diag});
3345 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
33643346 }
33653347
33663348 {
......@@ -3370,7 +3352,7 @@ test "std.zon add pointers" {
33703352 error.ParseZon,
33713353 fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
33723354 );
3373 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{}", .{diag});
3355 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
33743356 }
33753357
33763358 {
......@@ -3380,7 +3362,7 @@ test "std.zon add pointers" {
33803362 error.ParseZon,
33813363 fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
33823364 );
3383 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{}", .{diag});
3365 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
33843366 }
33853367
33863368 {
......@@ -3390,7 +3372,7 @@ test "std.zon add pointers" {
33903372 error.ParseZon,
33913373 fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
33923374 );
3393 try std.testing.expectFmt("1:1: error: expected optional union\n", "{}", .{diag});
3375 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
33943376 }
33953377
33963378 {
......@@ -3400,7 +3382,7 @@ test "std.zon add pointers" {
34003382 error.ParseZon,
34013383 fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),
34023384 );
3403 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});
3385 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34043386 }
34053387
34063388 {
......@@ -3410,7 +3392,7 @@ test "std.zon add pointers" {
34103392 error.ParseZon,
34113393 fromSlice(?[3]u8, gpa, "true", &diag, .{}),
34123394 );
3413 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});
3395 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34143396 }
34153397
34163398 {
......@@ -3420,7 +3402,7 @@ test "std.zon add pointers" {
34203402 error.ParseZon,
34213403 fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),
34223404 );
3423 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});
3405 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34243406 }
34253407
34263408 {
......@@ -3430,7 +3412,7 @@ test "std.zon add pointers" {
34303412 error.ParseZon,
34313413 fromSlice(?[]u8, gpa, "true", &diag, .{}),
34323414 );
3433 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});
3415 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34343416 }
34353417
34363418 {
......@@ -3440,7 +3422,7 @@ test "std.zon add pointers" {
34403422 error.ParseZon,
34413423 fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),
34423424 );
3443 try std.testing.expectFmt("1:1: error: expected optional string\n", "{}", .{diag});
3425 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
34443426 }
34453427
34463428 {
......@@ -3450,7 +3432,7 @@ test "std.zon add pointers" {
34503432 error.ParseZon,
34513433 fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
34523434 );
3453 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{}", .{diag});
3435 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
34543436 }
34553437}
34563438
lib/std/zon/stringify.zig+8-7
......@@ -501,7 +501,7 @@ pub fn Serializer(Writer: type) type {
501501 try self.int(val);
502502 },
503503 .float, .comptime_float => try self.float(val),
504 .bool, .null => try std.fmt.format(self.writer, "{}", .{val}),
504 .bool, .null => try std.fmt.deprecatedFormat(self.writer, "{}", .{val}),
505505 .enum_literal => try self.ident(@tagName(val)),
506506 .@"enum" => try self.ident(@tagName(val)),
507507 .pointer => |pointer| {
......@@ -615,7 +615,8 @@ pub fn Serializer(Writer: type) type {
615615
616616 /// Serialize an integer.
617617 pub fn int(self: *Self, val: anytype) Writer.Error!void {
618 try std.fmt.formatInt(val, 10, .lower, .{}, self.writer);
618 //try self.writer.printIntOptions(val, 10, .lower, .{});
619 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});
619620 }
620621
621622 /// Serialize a float.
......@@ -630,12 +631,12 @@ pub fn Serializer(Writer: type) type {
630631 } else if (std.math.isNegativeZero(val)) {
631632 return self.writer.writeAll("-0.0");
632633 } else {
633 try std.fmt.format(self.writer, "{d}", .{val});
634 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});
634635 },
635636 .comptime_float => if (val == 0) {
636637 return self.writer.writeAll("0");
637638 } else {
638 try std.fmt.format(self.writer, "{d}", .{val});
639 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});
639640 },
640641 else => comptime unreachable,
641642 }
......@@ -645,7 +646,7 @@ pub fn Serializer(Writer: type) type {
645646 ///
646647 /// Escapes the identifier if necessary.
647648 pub fn ident(self: *Self, name: []const u8) Writer.Error!void {
648 try self.writer.print(".{p_}", .{std.zig.fmtId(name)});
649 try self.writer.print(".{f}", .{std.zig.fmtIdPU(name)});
649650 }
650651
651652 /// Serialize `val` as a Unicode codepoint.
......@@ -658,7 +659,7 @@ pub fn Serializer(Writer: type) type {
658659 var buf: [8]u8 = undefined;
659660 const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint;
660661 const str = buf[0..len];
661 try std.fmt.format(self.writer, "'{'}'", .{std.zig.fmtEscapes(str)});
662 try std.fmt.deprecatedFormat(self.writer, "'{f}'", .{std.zig.fmtChar(str)});
662663 }
663664
664665 /// Like `value`, but always serializes `val` as a tuple.
......@@ -716,7 +717,7 @@ pub fn Serializer(Writer: type) type {
716717
717718 /// Like `value`, but always serializes `val` as a string.
718719 pub fn string(self: *Self, val: []const u8) Writer.Error!void {
719 try std.fmt.format(self.writer, "\"{}\"", .{std.zig.fmtEscapes(val)});
720 try std.fmt.deprecatedFormat(self.writer, "\"{f}\"", .{std.zig.fmtString(val)});
720721 }
721722
722723 /// Options for formatting multiline strings.
lib/ubsan_rt.zig+37-58
......@@ -119,12 +119,7 @@ const Value = extern struct {
119119 }
120120 }
121121
122 pub fn format(
123 value: Value,
124 comptime fmt: []const u8,
125 _: std.fmt.FormatOptions,
126 writer: anytype,
127 ) !void {
122 pub fn format(value: Value, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
128123 comptime assert(fmt.len == 0);
129124
130125 // Work around x86_64 backend limitation.
......@@ -136,12 +131,12 @@ const Value = extern struct {
136131 switch (value.td.kind) {
137132 .integer => {
138133 if (value.td.isSigned()) {
139 try writer.print("{}", .{value.getSignedInteger()});
134 try writer.print("{d}", .{value.getSignedInteger()});
140135 } else {
141 try writer.print("{}", .{value.getUnsignedInteger()});
136 try writer.print("{d}", .{value.getUnsignedInteger()});
142137 }
143138 },
144 .float => try writer.print("{}", .{value.getFloat()}),
139 .float => try writer.print("{d}", .{value.getFloat()}),
145140 .unknown => try writer.writeAll("(unknown)"),
146141 }
147142 }
......@@ -172,17 +167,12 @@ fn overflowHandler(
172167 ) callconv(.c) noreturn {
173168 const lhs: Value = .{ .handle = lhs_handle, .td = data.td };
174169 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
175
176 const is_signed = data.td.isSigned();
177 const fmt = "{s} integer overflow: " ++ "{} " ++
178 operator ++ " {} cannot be represented in type {s}";
179
180 panic(@returnAddress(), fmt, .{
181 if (is_signed) "signed" else "unsigned",
182 lhs,
183 rhs,
184 data.td.getName(),
185 });
170 const signed_str = if (data.td.isSigned()) "signed" else "unsigned";
171 panic(
172 @returnAddress(),
173 "{s} integer overflow: {f} " ++ operator ++ " {f} cannot be represented in type {s}",
174 .{ signed_str, lhs, rhs, data.td.getName() },
175 );
186176 }
187177 };
188178
......@@ -201,11 +191,9 @@ fn negationHandler(
201191 value_handle: ValueHandle,
202192) callconv(.c) noreturn {
203193 const value: Value = .{ .handle = value_handle, .td = data.td };
204 panic(
205 @returnAddress(),
206 "negation of {} cannot be represented in type {s}",
207 .{ value, data.td.getName() },
208 );
194 panic(@returnAddress(), "negation of {f} cannot be represented in type {s}", .{
195 value, data.td.getName(),
196 });
209197}
210198
211199fn divRemHandlerAbort(
......@@ -225,11 +213,9 @@ fn divRemHandler(
225213 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
226214
227215 if (rhs.isMinusOne()) {
228 panic(
229 @returnAddress(),
230 "division of {} by -1 cannot be represented in type {s}",
231 .{ lhs, data.td.getName() },
232 );
216 panic(@returnAddress(), "division of {f} by -1 cannot be represented in type {s}", .{
217 lhs, data.td.getName(),
218 });
233219 } else panic(@returnAddress(), "division by zero", .{});
234220}
235221
......@@ -269,8 +255,8 @@ fn alignmentAssumptionHandler(
269255 if (maybe_offset) |offset| {
270256 panic(
271257 @returnAddress(),
272 "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++
273 "offset address is {} aligned, misalignment offset is {} bytes",
258 "assumption of {f} byte alignment (with offset of {d} byte) for pointer of type {s} failed\n" ++
259 "offset address is {d} aligned, misalignment offset is {d} bytes",
274260 .{
275261 alignment,
276262 @intFromPtr(offset),
......@@ -282,8 +268,8 @@ fn alignmentAssumptionHandler(
282268 } else {
283269 panic(
284270 @returnAddress(),
285 "assumption of {} byte alignment for pointer of type {s} failed\n" ++
286 "address is {} aligned, misalignment offset is {} bytes",
271 "assumption of {f} byte alignment for pointer of type {s} failed\n" ++
272 "address is {d} aligned, misalignment offset is {d} bytes",
287273 .{
288274 alignment,
289275 data.td.getName(),
......@@ -320,21 +306,21 @@ fn shiftOob(
320306 rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())
321307 {
322308 if (rhs.isNegative()) {
323 panic(@returnAddress(), "shift exponent {} is negative", .{rhs});
309 panic(@returnAddress(), "shift exponent {f} is negative", .{rhs});
324310 } else {
325311 panic(
326312 @returnAddress(),
327 "shift exponent {} is too large for {}-bit type {s}",
313 "shift exponent {f} is too large for {d}-bit type {s}",
328314 .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },
329315 );
330316 }
331317 } else {
332318 if (lhs.isNegative()) {
333 panic(@returnAddress(), "left shift of negative value {}", .{lhs});
319 panic(@returnAddress(), "left shift of negative value {f}", .{lhs});
334320 } else {
335321 panic(
336322 @returnAddress(),
337 "left shift of {} by {} places cannot be represented in type {s}",
323 "left shift of {f} by {f} places cannot be represented in type {s}",
338324 .{ lhs, rhs, data.lhs_type.getName() },
339325 );
340326 }
......@@ -359,11 +345,10 @@ fn outOfBounds(
359345 index_handle: ValueHandle,
360346) callconv(.c) noreturn {
361347 const index: Value = .{ .handle = index_handle, .td = data.index_type };
362 panic(
363 @returnAddress(),
364 "index {} out of bounds for type {s}",
365 .{ index, data.array_type.getName() },
366 );
348 panic(@returnAddress(), "index {f} out of bounds for type {s}", .{
349 index,
350 data.array_type.getName(),
351 });
367352}
368353
369354const PointerOverflowData = extern struct {
......@@ -387,7 +372,7 @@ fn pointerOverflow(
387372 if (result == 0) {
388373 panic(@returnAddress(), "applying zero offset to null pointer", .{});
389374 } else {
390 panic(@returnAddress(), "applying non-zero offset {} to null pointer", .{result});
375 panic(@returnAddress(), "applying non-zero offset {d} to null pointer", .{result});
391376 }
392377 } else {
393378 if (result == 0) {
......@@ -483,7 +468,7 @@ fn typeMismatch(
483468 } else if (!std.mem.isAligned(handle, alignment)) {
484469 panic(
485470 @returnAddress(),
486 "{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment",
471 "{s} misaligned address 0x{x} for type {s}, which requires {d} byte alignment",
487472 .{ data.kind.getName(), handle, data.td.getName(), alignment },
488473 );
489474 } else {
......@@ -531,7 +516,7 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn {
531516fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
532517 panic(
533518 @returnAddress(),
534 "null pointer passed as argument {}, which is declared to never be null",
519 "null pointer passed as argument {d}, which is declared to never be null",
535520 .{data.arg_index},
536521 );
537522}
......@@ -553,11 +538,9 @@ fn loadInvalidValue(
553538 value_handle: ValueHandle,
554539) callconv(.c) noreturn {
555540 const value: Value = .{ .handle = value_handle, .td = data.td };
556 panic(
557 @returnAddress(),
558 "load of value {}, which is not valid for type {s}",
559 .{ value, data.td.getName() },
560 );
541 panic(@returnAddress(), "load of value {f}, which is not valid for type {s}", .{
542 value, data.td.getName(),
543 });
561544}
562545
563546const InvalidBuiltinData = extern struct {
......@@ -596,11 +579,7 @@ fn vlaBoundNotPositive(
596579 bound_handle: ValueHandle,
597580) callconv(.c) noreturn {
598581 const bound: Value = .{ .handle = bound_handle, .td = data.td };
599 panic(
600 @returnAddress(),
601 "variable length array bound evaluates to non-positive value {}",
602 .{bound},
603 );
582 panic(@returnAddress(), "variable length array bound evaluates to non-positive value {f}", .{bound});
604583}
605584
606585const FloatCastOverflowData = extern struct {
......@@ -631,13 +610,13 @@ fn floatCastOverflow(
631610 if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {
632611 const data: *const FloatCastOverflowData = @ptrCast(data_handle);
633612 const from_value: Value = .{ .handle = from_handle, .td = data.from };
634 panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{
613 panic(@returnAddress(), "{f} is outside the range of representable values of type {s}", .{
635614 from_value, data.to.getName(),
636615 });
637616 } else {
638617 const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);
639618 const from_value: Value = .{ .handle = from_handle, .td = data.from };
640 panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{
619 panic(@returnAddress(), "{f} is outside the range of representable values of type {s}", .{
641620 from_value, data.to.getName(),
642621 });
643622 }
src/Air/print.zig+4-4
......@@ -73,11 +73,11 @@ pub fn writeInst(
7373}
7474
7575pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
76 air.write(std.fs.File.stderr().writer(), pt, liveness);
76 air.write(std.fs.File.stderr().deprecatedWriter(), pt, liveness);
7777}
7878
7979pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
80 air.writeInst(std.fs.File.stderr().writer(), inst, pt, liveness);
80 air.writeInst(std.fs.File.stderr().deprecatedWriter(), inst, pt, liveness);
8181}
8282
8383const Writer = struct {
......@@ -704,7 +704,7 @@ const Writer = struct {
704704 }
705705 }
706706 const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len];
707 try s.print(", \"{}\"", .{std.zig.fmtEscapes(asm_source)});
707 try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)});
708708 }
709709
710710 fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
......@@ -716,7 +716,7 @@ const Writer = struct {
716716 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
717717 try w.writeOperand(s, inst, 0, pl_op.operand);
718718 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
719 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});
719 try s.print(", \"{f}\"", .{std.zig.fmtString(name.toSlice(w.air))});
720720 }
721721
722722 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
src/Builtin.zig+40-40
......@@ -51,60 +51,60 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
5151 const zig_backend = opts.zig_backend;
5252
5353 @setEvalBranchQuota(4000);
54 try buffer.writer().print(
54 try buffer.print(
5555 \\const std = @import("std");
5656 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
5757 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
5858 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
5959 \\pub const zig_version_string = "{s}";
60 \\pub const zig_backend = std.builtin.CompilerBackend.{p_};
60 \\pub const zig_backend = std.builtin.CompilerBackend.{f};
6161 \\
62 \\pub const output_mode: std.builtin.OutputMode = .{p_};
63 \\pub const link_mode: std.builtin.LinkMode = .{p_};
64 \\pub const unwind_tables: std.builtin.UnwindTables = .{p_};
62 \\pub const output_mode: std.builtin.OutputMode = .{f};
63 \\pub const link_mode: std.builtin.LinkMode = .{f};
64 \\pub const unwind_tables: std.builtin.UnwindTables = .{f};
6565 \\pub const is_test = {};
6666 \\pub const single_threaded = {};
67 \\pub const abi: std.Target.Abi = .{p_};
67 \\pub const abi: std.Target.Abi = .{f};
6868 \\pub const cpu: std.Target.Cpu = .{{
69 \\ .arch = .{p_},
70 \\ .model = &std.Target.{p_}.cpu.{p_},
71 \\ .features = std.Target.{p_}.featureSet(&.{{
69 \\ .arch = .{f},
70 \\ .model = &std.Target.{f}.cpu.{f},
71 \\ .features = std.Target.{f}.featureSet(&.{{
7272 \\
7373 , .{
7474 build_options.version,
75 std.zig.fmtId(@tagName(zig_backend)),
76 std.zig.fmtId(@tagName(opts.output_mode)),
77 std.zig.fmtId(@tagName(opts.link_mode)),
78 std.zig.fmtId(@tagName(opts.unwind_tables)),
75 std.zig.fmtIdPU(@tagName(zig_backend)),
76 std.zig.fmtIdPU(@tagName(opts.output_mode)),
77 std.zig.fmtIdPU(@tagName(opts.link_mode)),
78 std.zig.fmtIdPU(@tagName(opts.unwind_tables)),
7979 opts.is_test,
8080 opts.single_threaded,
81 std.zig.fmtId(@tagName(target.abi)),
82 std.zig.fmtId(@tagName(target.cpu.arch)),
83 std.zig.fmtId(arch_family_name),
84 std.zig.fmtId(target.cpu.model.name),
85 std.zig.fmtId(arch_family_name),
81 std.zig.fmtIdPU(@tagName(target.abi)),
82 std.zig.fmtIdPU(@tagName(target.cpu.arch)),
83 std.zig.fmtIdPU(arch_family_name),
84 std.zig.fmtIdPU(target.cpu.model.name),
85 std.zig.fmtIdPU(arch_family_name),
8686 });
8787
8888 for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {
8989 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
9090 const is_enabled = target.cpu.features.isEnabled(index);
9191 if (is_enabled) {
92 try buffer.writer().print(" .{p_},\n", .{std.zig.fmtId(feature.name)});
92 try buffer.print(" .{f},\n", .{std.zig.fmtIdPU(feature.name)});
9393 }
9494 }
95 try buffer.writer().print(
95 try buffer.print(
9696 \\ }}),
9797 \\}};
9898 \\pub const os: std.Target.Os = .{{
99 \\ .tag = .{p_},
99 \\ .tag = .{f},
100100 \\ .version_range = .{{
101101 ,
102 .{std.zig.fmtId(@tagName(target.os.tag))},
102 .{std.zig.fmtIdPU(@tagName(target.os.tag))},
103103 );
104104
105105 switch (target.os.versionRange()) {
106106 .none => try buffer.appendSlice(" .none = {} },\n"),
107 .semver => |semver| try buffer.writer().print(
107 .semver => |semver| try buffer.print(
108108 \\ .semver = .{{
109109 \\ .min = .{{
110110 \\ .major = {},
......@@ -127,7 +127,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
127127 semver.max.minor,
128128 semver.max.patch,
129129 }),
130 .linux => |linux| try buffer.writer().print(
130 .linux => |linux| try buffer.print(
131131 \\ .linux = .{{
132132 \\ .range = .{{
133133 \\ .min = .{{
......@@ -164,7 +164,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
164164
165165 linux.android,
166166 }),
167 .hurd => |hurd| try buffer.writer().print(
167 .hurd => |hurd| try buffer.print(
168168 \\ .hurd = .{{
169169 \\ .range = .{{
170170 \\ .min = .{{
......@@ -198,10 +198,10 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
198198 hurd.glibc.minor,
199199 hurd.glibc.patch,
200200 }),
201 .windows => |windows| try buffer.writer().print(
201 .windows => |windows| try buffer.print(
202202 \\ .windows = .{{
203 \\ .min = {c},
204 \\ .max = {c},
203 \\ .min = {fc},
204 \\ .max = {fc},
205205 \\ }}}},
206206 \\
207207 , .{ windows.min, windows.max }),
......@@ -217,7 +217,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
217217 );
218218
219219 if (target.dynamic_linker.get()) |dl| {
220 try buffer.writer().print(
220 try buffer.print(
221221 \\ .dynamic_linker = .init("{s}"),
222222 \\}};
223223 \\
......@@ -237,9 +237,9 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
237237 // knows libc will provide it, and likewise c.zig will not export memcpy.
238238 const link_libc = opts.link_libc;
239239
240 try buffer.writer().print(
241 \\pub const object_format: std.Target.ObjectFormat = .{p_};
242 \\pub const mode: std.builtin.OptimizeMode = .{p_};
240 try buffer.print(
241 \\pub const object_format: std.Target.ObjectFormat = .{f};
242 \\pub const mode: std.builtin.OptimizeMode = .{f};
243243 \\pub const link_libc = {};
244244 \\pub const link_libcpp = {};
245245 \\pub const have_error_return_tracing = {};
......@@ -249,12 +249,12 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
249249 \\pub const position_independent_code = {};
250250 \\pub const position_independent_executable = {};
251251 \\pub const strip_debug_info = {};
252 \\pub const code_model: std.builtin.CodeModel = .{p_};
252 \\pub const code_model: std.builtin.CodeModel = .{f};
253253 \\pub const omit_frame_pointer = {};
254254 \\
255255 , .{
256 std.zig.fmtId(@tagName(target.ofmt)),
257 std.zig.fmtId(@tagName(opts.optimize_mode)),
256 std.zig.fmtIdPU(@tagName(target.ofmt)),
257 std.zig.fmtIdPU(@tagName(opts.optimize_mode)),
258258 link_libc,
259259 opts.link_libcpp,
260260 opts.error_tracing,
......@@ -264,15 +264,15 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
264264 opts.pic,
265265 opts.pie,
266266 opts.strip,
267 std.zig.fmtId(@tagName(opts.code_model)),
267 std.zig.fmtIdPU(@tagName(opts.code_model)),
268268 opts.omit_frame_pointer,
269269 });
270270
271271 if (target.os.tag == .wasi) {
272 try buffer.writer().print(
273 \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{p_};
272 try buffer.print(
273 \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{f};
274274 \\
275 , .{std.zig.fmtId(@tagName(opts.wasi_exec_model))});
275 , .{std.zig.fmtIdPU(@tagName(opts.wasi_exec_model))});
276276 }
277277
278278 if (opts.is_test) {
......@@ -317,7 +317,7 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
317317 if (root_dir.statFile(sub_path)) |stat| {
318318 if (stat.size != file.source.?.len) {
319319 std.log.warn(
320 "the cached file '{}' had the wrong size. Expected {d}, found {d}. " ++
320 "the cached file '{f}{s}' had the wrong size. Expected {d}, found {d}. " ++
321321 "Overwriting with correct file contents now",
322322 .{ file.path.fmt(comp), file.source.?.len, stat.size },
323323 );
src/Compilation.zig+6-6
......@@ -1001,7 +1001,7 @@ pub const CObject = struct {
10011001
10021002 var line = std.ArrayList(u8).init(eb.gpa);
10031003 defer line.deinit();
1004 file.reader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;
1004 file.deprecatedReader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;
10051005
10061006 break :source_line try eb.addString(line.items);
10071007 };
......@@ -1069,7 +1069,7 @@ pub const CObject = struct {
10691069
10701070 const file = try std.fs.cwd().openFile(path, .{});
10711071 defer file.close();
1072 var br = std.io.bufferedReader(file.reader());
1072 var br = std.io.bufferedReader(file.deprecatedReader());
10731073 const reader = br.reader();
10741074 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });
10751075 defer bc.deinit();
......@@ -1875,7 +1875,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18751875 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
18761876 std.debug.lockStdErr();
18771877 defer std.debug.unlockStdErr();
1878 const stderr = std.fs.File.stderr().writer();
1878 const stderr = std.fs.File.stderr().deprecatedWriter();
18791879 nosuspend {
18801880 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;
18811881 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
......@@ -3932,7 +3932,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
39323932 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
39333933 // However, we haven't reported any such error.
39343934 // This is a compiler bug.
3935 const stderr = std.fs.File.stderr().writer();
3935 const stderr = std.fs.File.stderr().deprecatedWriter();
39363936 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");
39373937 try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
39383938 while (ref) |r| {
......@@ -4894,7 +4894,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
48944894 var walker = try mod_dir.walk(comp.gpa);
48954895 defer walker.deinit();
48964896
4897 var archiver = std.tar.writer(tar_file.writer().any());
4897 var archiver = std.tar.writer(tar_file.deprecatedWriter().any());
48984898 archiver.prefix = name;
48994899
49004900 while (try walker.next()) |entry| {
......@@ -7214,7 +7214,7 @@ pub fn lockAndSetMiscFailure(
72147214pub fn dump_argv(argv: []const []const u8) void {
72157215 std.debug.lockStdErr();
72167216 defer std.debug.unlockStdErr();
7217 const stderr = std.fs.File.stderr().writer();
7217 const stderr = std.fs.File.stderr().deprecatedWriter();
72187218 for (argv[0 .. argv.len - 1]) |arg| {
72197219 nosuspend stderr.print("{s} ", .{arg}) catch return;
72207220 }
src/InternPool.zig+3-3
......@@ -1892,7 +1892,7 @@ pub const NullTerminatedString = enum(u32) {
18921892 if (comptime std.mem.eql(u8, specifier, "")) {
18931893 try writer.writeAll(slice);
18941894 } else if (comptime std.mem.eql(u8, specifier, "i")) {
1895 try writer.print("{p}", .{std.zig.fmtId(slice)});
1895 try writer.print("{f}", .{std.zig.fmtIdP(slice)});
18961896 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");
18971897 }
18981898
......@@ -11259,7 +11259,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
1125911259}
1126011260
1126111261fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11262 var bw = std.io.bufferedWriter(std.fs.File.stderr().writer());
11262 var bw = std.io.bufferedWriter(std.fs.File.stderr().deprecatedWriter());
1126311263 const w = bw.writer();
1126411264 for (ip.locals, 0..) |*local, tid| {
1126511265 const items = local.shared.items.view();
......@@ -11369,7 +11369,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
1136911369 defer arena_allocator.deinit();
1137011370 const arena = arena_allocator.allocator();
1137111371
11372 var bw = std.io.bufferedWriter(std.fs.File.stderr().writer());
11372 var bw = std.io.bufferedWriter(std.fs.File.stderr().deprecatedWriter());
1137311373 const w = bw.writer();
1137411374
1137511375 var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .empty;
src/Package.zig+1-1
......@@ -134,7 +134,7 @@ pub const Hash = struct {
134134 }
135135 var bin_digest: [Algo.digest_length]u8 = undefined;
136136 Algo.hash(sub_path, &bin_digest, .{});
137 _ = std.fmt.bufPrint(result.bytes[i..], "{}", .{std.fmt.fmtSliceHexLower(&bin_digest)}) catch unreachable;
137 _ = std.fmt.bufPrint(result.bytes[i..], "{x}", .{&bin_digest}) catch unreachable;
138138 return result;
139139 }
140140};
src/Package/Fetch.zig+15-15
......@@ -201,7 +201,7 @@ pub const JobQueue = struct {
201201 const hash_slice = hash.toSlice();
202202
203203 try buf.writer().print(
204 \\ pub const {} = struct {{
204 \\ pub const {f} = struct {{
205205 \\
206206 , .{std.zig.fmtId(hash_slice)});
207207
......@@ -233,9 +233,9 @@ pub const JobQueue = struct {
233233
234234 if (fetch.has_build_zig) {
235235 try buf.writer().print(
236 \\ pub const build_zig = @import("{}");
236 \\ pub const build_zig = @import("{f}");
237237 \\
238 , .{std.zig.fmtEscapes(hash_slice)});
238 , .{std.zig.fmtString(hash_slice)});
239239 }
240240
241241 if (fetch.manifest) |*manifest| {
......@@ -246,8 +246,8 @@ pub const JobQueue = struct {
246246 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {
247247 const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue;
248248 try buf.writer().print(
249 " .{{ \"{}\", \"{}\" }},\n",
250 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },
249 " .{{ \"{f}\", \"{f}\" }},\n",
250 .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) },
251251 );
252252 }
253253
......@@ -278,8 +278,8 @@ pub const JobQueue = struct {
278278 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {
279279 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;
280280 try buf.writer().print(
281 " .{{ \"{}\", \"{}\" }},\n",
282 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },
281 " .{{ \"{f}\", \"{f}\" }},\n",
282 .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) },
283283 );
284284 }
285285 try buf.appendSlice("};\n");
......@@ -1321,7 +1321,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {
13211321 .{@errorName(err)},
13221322 ));
13231323 if (len == 0) break;
1324 zip_file.writer().writeAll(buf[0..len]) catch |err| return f.fail(f.location_tok, try eb.printString(
1324 zip_file.deprecatedWriter().writeAll(buf[0..len]) catch |err| return f.fail(f.location_tok, try eb.printString(
13251325 "write temporary zip file failed: {s}",
13261326 .{@errorName(err)},
13271327 ));
......@@ -1374,7 +1374,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
13741374 var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true });
13751375 defer pack_file.close();
13761376 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
1377 try fifo.pump(resource.fetch_stream.reader(), pack_file.writer());
1377 try fifo.pump(resource.fetch_stream.reader(), pack_file.deprecatedWriter());
13781378 try pack_file.sync();
13791379
13801380 var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true });
......@@ -1382,7 +1382,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
13821382 {
13831383 const index_prog_node = f.prog_node.start("Index pack", 0);
13841384 defer index_prog_node.end();
1385 var index_buffered_writer = std.io.bufferedWriter(index_file.writer());
1385 var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter());
13861386 try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer());
13871387 try index_buffered_writer.flush();
13881388 try index_file.sync();
......@@ -1655,13 +1655,13 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
16551655
16561656fn dumpHashInfo(all_files: []const *const HashedFile) !void {
16571657 const stdout: std.fs.File = .stdout();
1658 var bw = std.io.bufferedWriter(stdout.writer());
1658 var bw = std.io.bufferedWriter(stdout.deprecatedWriter());
16591659 const w = bw.writer();
16601660
16611661 for (all_files) |hashed_file| {
1662 try w.print("{s}: {s}: {s}\n", .{
1662 try w.print("{s}: {x}: {s}\n", .{
16631663 @tagName(hashed_file.kind),
1664 std.fmt.fmtSliceHexLower(&hashed_file.hash),
1664 &hashed_file.hash,
16651665 hashed_file.normalized_path,
16661666 });
16671667 }
......@@ -2074,7 +2074,7 @@ test "zip" {
20742074 {
20752075 var zip_file = try tmp.dir.createFile("test.zip", .{});
20762076 defer zip_file.close();
2077 var bw = std.io.bufferedWriter(zip_file.writer());
2077 var bw = std.io.bufferedWriter(zip_file.deprecatedWriter());
20782078 var store: [test_files.len]std.zip.testutil.FileStore = undefined;
20792079 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});
20802080 try bw.flush();
......@@ -2107,7 +2107,7 @@ test "zip with one root folder" {
21072107 {
21082108 var zip_file = try tmp.dir.createFile("test.zip", .{});
21092109 defer zip_file.close();
2110 var bw = std.io.bufferedWriter(zip_file.writer());
2110 var bw = std.io.bufferedWriter(zip_file.deprecatedWriter());
21112111 var store: [test_files.len]std.zip.testutil.FileStore = undefined;
21122112 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});
21132113 try bw.flush();
src/Package/Fetch/git.zig+9-9
......@@ -127,7 +127,7 @@ pub const Oid = union(Format) {
127127 ) @TypeOf(writer).Error!void {
128128 _ = fmt;
129129 _ = options;
130 try writer.print("{}", .{std.fmt.fmtSliceHexLower(oid.slice())});
130 try writer.print("{x}", .{oid.slice()});
131131 }
132132
133133 pub fn slice(oid: *const Oid) []const u8 {
......@@ -353,7 +353,7 @@ const Odb = struct {
353353 fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb {
354354 try pack_file.seekTo(0);
355355 try index_file.seekTo(0);
356 const index_header = try IndexHeader.read(index_file.reader());
356 const index_header = try IndexHeader.read(index_file.deprecatedReader());
357357 return .{
358358 .format = format,
359359 .pack_file = pack_file,
......@@ -377,7 +377,7 @@ const Odb = struct {
377377 const base_object = while (true) {
378378 if (odb.cache.get(base_offset)) |base_object| break base_object;
379379
380 base_header = try EntryHeader.read(odb.format, odb.pack_file.reader());
380 base_header = try EntryHeader.read(odb.format, odb.pack_file.deprecatedReader());
381381 switch (base_header) {
382382 .ofs_delta => |ofs_delta| {
383383 try delta_offsets.append(odb.allocator, base_offset);
......@@ -390,7 +390,7 @@ const Odb = struct {
390390 base_offset = try odb.pack_file.getPos();
391391 },
392392 else => {
393 const base_data = try readObjectRaw(odb.allocator, odb.pack_file.reader(), base_header.uncompressedLength());
393 const base_data = try readObjectRaw(odb.allocator, odb.pack_file.deprecatedReader(), base_header.uncompressedLength());
394394 errdefer odb.allocator.free(base_data);
395395 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };
396396 try odb.cache.put(odb.allocator, base_offset, base_object);
......@@ -420,7 +420,7 @@ const Odb = struct {
420420 const found_index = while (start_index < end_index) {
421421 const mid_index = start_index + (end_index - start_index) / 2;
422422 try odb.index_file.seekTo(IndexHeader.size + mid_index * oid_length);
423 const mid_oid = try Oid.readBytes(odb.format, odb.index_file.reader());
423 const mid_oid = try Oid.readBytes(odb.format, odb.index_file.deprecatedReader());
424424 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {
425425 .lt => start_index = mid_index + 1,
426426 .gt => end_index = mid_index,
......@@ -431,12 +431,12 @@ const Odb = struct {
431431 const n_objects = odb.index_header.fan_out_table[255];
432432 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);
433433 try odb.index_file.seekTo(offset_values_start + found_index * 4);
434 const l1_offset: packed struct { value: u31, big: bool } = @bitCast(try odb.index_file.reader().readInt(u32, .big));
434 const l1_offset: packed struct { value: u31, big: bool } = @bitCast(try odb.index_file.deprecatedReader().readInt(u32, .big));
435435 const pack_offset = pack_offset: {
436436 if (l1_offset.big) {
437437 const l2_offset_values_start = offset_values_start + n_objects * 4;
438438 try odb.index_file.seekTo(l2_offset_values_start + l1_offset.value * 4);
439 break :pack_offset try odb.index_file.reader().readInt(u64, .big);
439 break :pack_offset try odb.index_file.deprecatedReader().readInt(u64, .big);
440440 } else {
441441 break :pack_offset l1_offset.value;
442442 }
......@@ -1561,7 +1561,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void
15611561
15621562 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });
15631563 defer index_file.close();
1564 try indexPack(testing.allocator, format, pack_file, index_file.writer());
1564 try indexPack(testing.allocator, format, pack_file, index_file.deprecatedWriter());
15651565
15661566 // Arbitrary size limit on files read while checking the repository contents
15671567 // (all files in the test repo are known to be smaller than this)
......@@ -1678,7 +1678,7 @@ pub fn main() !void {
16781678 std.debug.print("Starting index...\n", .{});
16791679 var index_file = try git_dir.createFile("idx", .{ .read = true });
16801680 defer index_file.close();
1681 var index_buffered_writer = std.io.bufferedWriter(index_file.writer());
1681 var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter());
16821682 try indexPack(allocator, format, pack_file, index_buffered_writer.writer());
16831683 try index_buffered_writer.flush();
16841684 try index_file.sync();
src/Package/Manifest.zig+2-2
......@@ -401,7 +401,7 @@ const Parse = struct {
401401 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});
402402
403403 if (name.len > max_name_len)
404 return fail(p, main_token, "name '{}' exceeds max length of {d}", .{
404 return fail(p, main_token, "name '{f}' exceeds max length of {d}", .{
405405 std.zig.fmtId(name), max_name_len,
406406 });
407407
......@@ -416,7 +416,7 @@ const Parse = struct {
416416 return fail(p, main_token, "name must be a valid bare zig identifier", .{});
417417
418418 if (ident_name.len > max_name_len)
419 return fail(p, main_token, "name '{}' exceeds max length of {d}", .{
419 return fail(p, main_token, "name '{f}' exceeds max length of {d}", .{
420420 std.zig.fmtId(ident_name), max_name_len,
421421 });
422422
src/Sema.zig+454-452
......@@ -5,6 +5,39 @@
55//! Does type checking, comptime control flow, and safety-check generation.
66//! This is the the heart of the Zig compiler.
77
8const std = @import("std");
9const math = std.math;
10const mem = std.mem;
11const Allocator = mem.Allocator;
12const assert = std.debug.assert;
13const log = std.log.scoped(.sema);
14
15const Sema = @This();
16const Value = @import("Value.zig");
17const MutableValue = @import("mutable_value.zig").MutableValue;
18const Type = @import("Type.zig");
19const Air = @import("Air.zig");
20const Zir = std.zig.Zir;
21const Zcu = @import("Zcu.zig");
22const trace = @import("tracy.zig").trace;
23const Namespace = Zcu.Namespace;
24const CompileError = Zcu.CompileError;
25const SemaError = Zcu.SemaError;
26const LazySrcLoc = Zcu.LazySrcLoc;
27const RangeSet = @import("RangeSet.zig");
28const target_util = @import("target.zig");
29const Package = @import("Package.zig");
30const crash_report = @import("crash_report.zig");
31const build_options = @import("build_options");
32const Compilation = @import("Compilation.zig");
33const InternPool = @import("InternPool.zig");
34const Alignment = InternPool.Alignment;
35const AnalUnit = InternPool.AnalUnit;
36const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;
37const Cache = std.Build.Cache;
38const LowerZon = @import("Sema/LowerZon.zig");
39const arith = @import("Sema/arith.zig");
40
841pt: Zcu.PerThread,
942/// Alias to `zcu.gpa`.
1043gpa: Allocator,
......@@ -157,39 +190,6 @@ pub fn getComptimeAlloc(sema: *Sema, idx: ComptimeAllocIndex) *ComptimeAlloc {
157190 return &sema.comptime_allocs.items[@intFromEnum(idx)];
158191}
159192
160const std = @import("std");
161const math = std.math;
162const mem = std.mem;
163const Allocator = mem.Allocator;
164const assert = std.debug.assert;
165const log = std.log.scoped(.sema);
166
167const Sema = @This();
168const Value = @import("Value.zig");
169const MutableValue = @import("mutable_value.zig").MutableValue;
170const Type = @import("Type.zig");
171const Air = @import("Air.zig");
172const Zir = std.zig.Zir;
173const Zcu = @import("Zcu.zig");
174const trace = @import("tracy.zig").trace;
175const Namespace = Zcu.Namespace;
176const CompileError = Zcu.CompileError;
177const SemaError = Zcu.SemaError;
178const LazySrcLoc = Zcu.LazySrcLoc;
179const RangeSet = @import("RangeSet.zig");
180const target_util = @import("target.zig");
181const Package = @import("Package.zig");
182const crash_report = @import("crash_report.zig");
183const build_options = @import("build_options");
184const Compilation = @import("Compilation.zig");
185const InternPool = @import("InternPool.zig");
186const Alignment = InternPool.Alignment;
187const AnalUnit = InternPool.AnalUnit;
188const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;
189const Cache = std.Build.Cache;
190const LowerZon = @import("Sema/LowerZon.zig");
191const arith = @import("Sema/arith.zig");
192
193193pub const default_branch_quota = 1000;
194194
195195pub const InferredErrorSet = struct {
......@@ -888,7 +888,7 @@ const ComptimeReason = union(enum) {
888888 /// Evaluating at comptime because of a comptime-only type. This field is separate so that
889889 /// the type in question can be included in the error message. AstGen could never emit this
890890 /// reason, because it knows nothing of types.
891 /// The format string looks like "foo '{}' bar", where "{}" is the comptime-only type.
891 /// The format string looks like "foo '{f}' bar", where "{f}" is the comptime-only type.
892892 /// We will then explain why this type is comptime-only.
893893 comptime_only: struct {
894894 ty: Type,
......@@ -930,17 +930,17 @@ const ComptimeReason = union(enum) {
930930 .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" },
931931 .tuple_init => .{ "initializer of comptime-only tuple", "must be comptime-known" },
932932 };
933 try sema.errNote(src, err_msg, "{s} '{}' {s}", .{ pre, co.ty.fmt(sema.pt), post });
933 try sema.errNote(src, err_msg, "{s} '{f}' {s}", .{ pre, co.ty.fmt(sema.pt), post });
934934 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
935935 },
936936 .comptime_only_param_ty => |co| {
937 try sema.errNote(src, err_msg, "argument to parameter with comptime-only type '{}' must be comptime-known", .{co.ty.fmt(sema.pt)});
937 try sema.errNote(src, err_msg, "argument to parameter with comptime-only type '{f}' must be comptime-known", .{co.ty.fmt(sema.pt)});
938938 try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{});
939939 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
940940 },
941941 .comptime_only_ret_ty => |co| {
942942 const function_with: []const u8 = if (co.is_generic_inst) "generic function instantiated with" else "function with";
943 try sema.errNote(src, err_msg, "call to {s} comptime-only return type '{}' is evaluated at comptime", .{ function_with, co.ty.fmt(sema.pt) });
943 try sema.errNote(src, err_msg, "call to {s} comptime-only return type '{f}' is evaluated at comptime", .{ function_with, co.ty.fmt(sema.pt) });
944944 try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{});
945945 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
946946 },
......@@ -1905,7 +1905,7 @@ fn analyzeBodyInner(
19051905 const err_union = try sema.resolveInst(extra.data.operand);
19061906 const err_union_ty = sema.typeOf(err_union);
19071907 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
1908 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{
1908 return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{
19091909 err_union_ty.fmt(pt),
19101910 });
19111911 }
......@@ -2339,7 +2339,7 @@ pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) Compile
23392339
23402340fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError {
23412341 const pt = sema.pt;
2342 return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{
2342 return sema.fail(block, src, "remainder division with '{f}' and '{f}': signed integers and floats must use @rem or @mod", .{
23432343 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
23442344 });
23452345}
......@@ -2347,7 +2347,7 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T
23472347fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError {
23482348 const pt = sema.pt;
23492349 const msg = msg: {
2350 const msg = try sema.errMsg(src, "expected optional type, found '{}'", .{
2350 const msg = try sema.errMsg(src, "expected optional type, found '{f}'", .{
23512351 non_optional_ty.fmt(pt),
23522352 });
23532353 errdefer msg.destroy(sema.gpa);
......@@ -2363,12 +2363,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non
23632363fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
23642364 const pt = sema.pt;
23652365 const msg = msg: {
2366 const msg = try sema.errMsg(src, "type '{}' does not support array initialization syntax", .{
2366 const msg = try sema.errMsg(src, "type '{f}' does not support array initialization syntax", .{
23672367 ty.fmt(pt),
23682368 });
23692369 errdefer msg.destroy(sema.gpa);
23702370 if (ty.isSlice(pt.zcu)) {
2371 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(pt.zcu).fmt(pt)});
2371 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.elemType2(pt.zcu).fmt(pt)});
23722372 }
23732373 break :msg msg;
23742374 };
......@@ -2377,7 +2377,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty
23772377
23782378fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
23792379 const pt = sema.pt;
2380 return sema.fail(block, src, "type '{}' does not support struct initialization syntax", .{
2380 return sema.fail(block, src, "type '{f}' does not support struct initialization syntax", .{
23812381 ty.fmt(pt),
23822382 });
23832383}
......@@ -2390,7 +2390,7 @@ fn failWithErrorSetCodeMissing(
23902390 src_err_set_ty: Type,
23912391) CompileError {
23922392 const pt = sema.pt;
2393 return sema.fail(block, src, "expected type '{}', found type '{}'", .{
2393 return sema.fail(block, src, "expected type '{f}', found type '{f}'", .{
23942394 dest_err_set_ty.fmt(pt), src_err_set_ty.fmt(pt),
23952395 });
23962396}
......@@ -2398,7 +2398,7 @@ fn failWithErrorSetCodeMissing(
23982398pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError {
23992399 const pt = sema.pt;
24002400 return sema.failWithOwnedErrorMsg(block, msg: {
2401 const msg = try sema.errMsg(src, "overflow of integer type '{}' with value '{}'", .{
2401 const msg = try sema.errMsg(src, "overflow of integer type '{f}' with value '{f}'", .{
24022402 int_ty.fmt(pt), val.fmtValueSema(pt, sema),
24032403 });
24042404 errdefer msg.destroy(sema.gpa);
......@@ -2448,7 +2448,7 @@ fn failWithInvalidFieldAccess(
24482448 const child_ty = inner_ty.optionalChild(zcu);
24492449 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt;
24502450 const msg = msg: {
2451 const msg = try sema.errMsg(src, "optional type '{}' does not support field access", .{object_ty.fmt(pt)});
2451 const msg = try sema.errMsg(src, "optional type '{f}' does not support field access", .{object_ty.fmt(pt)});
24522452 errdefer msg.destroy(sema.gpa);
24532453 try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{});
24542454 break :msg msg;
......@@ -2458,14 +2458,14 @@ fn failWithInvalidFieldAccess(
24582458 const child_ty = inner_ty.errorUnionPayload(zcu);
24592459 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err;
24602460 const msg = msg: {
2461 const msg = try sema.errMsg(src, "error union type '{}' does not support field access", .{object_ty.fmt(pt)});
2461 const msg = try sema.errMsg(src, "error union type '{f}' does not support field access", .{object_ty.fmt(pt)});
24622462 errdefer msg.destroy(sema.gpa);
24632463 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
24642464 break :msg msg;
24652465 };
24662466 return sema.failWithOwnedErrorMsg(block, msg);
24672467 }
2468 return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(pt)});
2468 return sema.fail(block, src, "type '{f}' does not support field access", .{object_ty.fmt(pt)});
24692469}
24702470
24712471fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool {
......@@ -2494,7 +2494,7 @@ fn failWithComptimeErrorRetTrace(
24942494 const pt = sema.pt;
24952495 const zcu = pt.zcu;
24962496 const msg = msg: {
2497 const msg = try sema.errMsg(src, "caught unexpected error '{}'", .{name.fmt(&zcu.intern_pool)});
2497 const msg = try sema.errMsg(src, "caught unexpected error '{f}'", .{name.fmt(&zcu.intern_pool)});
24982498 errdefer msg.destroy(sema.gpa);
24992499
25002500 for (sema.comptime_err_ret_trace.items) |src_loc| {
......@@ -3005,7 +3005,7 @@ pub fn createTypeName(
30053005 inst: ?Zir.Inst.Index,
30063006 /// This is used purely to give the type a unique name in the `anon` case.
30073007 type_index: InternPool.Index,
3008) !struct {
3008) CompileError!struct {
30093009 name: InternPool.NullTerminatedString,
30103010 nav: InternPool.Nav.Index.Optional,
30113011} {
......@@ -3024,11 +3024,10 @@ pub fn createTypeName(
30243024 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
30253025 const zir_tags = sema.code.instructions.items(.tag);
30263026
3027 var buf: std.ArrayListUnmanaged(u8) = .empty;
3028 defer buf.deinit(gpa);
3029
3030 const writer = buf.writer(gpa);
3031 try writer.print("{}(", .{block.type_name_ctx.fmt(ip)});
3027 var aw: std.io.Writer.Allocating = .init(gpa);
3028 defer aw.deinit();
3029 const bw = &aw.interface;
3030 bw.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory;
30323031
30333032 var arg_i: usize = 0;
30343033 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {
......@@ -3041,18 +3040,18 @@ pub fn createTypeName(
30413040 // result in a compile error.
30423041 const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat
30433042
3044 if (arg_i != 0) try writer.writeByte(',');
3043 if (arg_i != 0) bw.writeByte(',') catch return error.OutOfMemory;
30453044
30463045 // Limiting the depth here helps avoid type names getting too long, which
30473046 // in turn helps to avoid unreasonably long symbol names for namespaced
30483047 // symbols. Such names should ideally be human-readable, and additionally,
30493048 // some tooling may not support very long symbol names.
3050 try writer.print("{}", .{Value.fmtValueSemaFull(.{
3049 bw.print("{f}", .{Value.fmtValueSemaFull(.{
30513050 .val = arg_val,
30523051 .pt = pt,
30533052 .opt_sema = sema,
30543053 .depth = 1,
3055 })});
3054 })}) catch return error.OutOfMemory;
30563055
30573056 arg_i += 1;
30583057 continue;
......@@ -3060,9 +3059,9 @@ pub fn createTypeName(
30603059 else => continue,
30613060 };
30623061
3063 try writer.writeByte(')');
3062 try bw.writeByte(')');
30643063 return .{
3065 .name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls),
3064 .name = try ip.getOrPutString(gpa, pt.tid, aw.getWritten(), .no_embedded_nulls),
30663065 .nav = .none,
30673066 };
30683067 },
......@@ -3074,7 +3073,7 @@ pub fn createTypeName(
30743073 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
30753074 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
30763075 return .{
3077 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{
3076 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{
30783077 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
30793078 }, .no_embedded_nulls),
30803079 .nav = .none,
......@@ -3097,7 +3096,7 @@ pub fn createTypeName(
30973096 // that builtin from the language, we can consider this.
30983097
30993098 return .{
3100 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{
3099 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}__{s}_{d}", .{
31013100 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
31023101 }, .no_embedded_nulls),
31033102 .nav = .none,
......@@ -3581,7 +3580,7 @@ fn ensureResultUsed(
35813580 },
35823581 else => {
35833582 const msg = msg: {
3584 const msg = try sema.errMsg(src, "value of type '{}' ignored", .{ty.fmt(pt)});
3583 const msg = try sema.errMsg(src, "value of type '{f}' ignored", .{ty.fmt(pt)});
35853584 errdefer msg.destroy(sema.gpa);
35863585 try sema.errNote(src, msg, "all non-void values must be used", .{});
35873586 try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{});
......@@ -3851,7 +3850,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
38513850 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.
38523851 // TODO: source location of runtime control flow
38533852 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
3854 return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(pt)});
3853 return sema.fail(block, init_src, "value with comptime-only type '{f}' depends on runtime control flow", .{elem_ty.fmt(pt)});
38553854 }
38563855
38573856 // This is a runtime value.
......@@ -4348,7 +4347,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
43484347 // The alloc wasn't comptime-known per the above logic, so the
43494348 // type cannot be comptime-only.
43504349 // TODO: source location of runtime control flow
4351 return sema.fail(block, src, "value with comptime-only type '{}' depends on runtime control flow", .{final_elem_ty.fmt(pt)});
4350 return sema.fail(block, src, "value with comptime-only type '{f}' depends on runtime control flow", .{final_elem_ty.fmt(pt)});
43524351 }
43534352 if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) {
43544353 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
......@@ -4445,7 +4444,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
44454444 if (!object_ty.isIndexable(zcu)) {
44464445 // Instead of using checkIndexable we customize this error.
44474446 const msg = msg: {
4448 const msg = try sema.errMsg(arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(pt)});
4447 const msg = try sema.errMsg(arg_src, "type '{f}' is not indexable and not a range", .{object_ty.fmt(pt)});
44494448 errdefer msg.destroy(sema.gpa);
44504449 try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{});
44514450
......@@ -4480,10 +4479,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
44804479 .for_node_offset = inst_data.src_node,
44814480 .input_index = len_idx,
44824481 } });
4483 try sema.errNote(a_src, msg, "length {} here", .{
4482 try sema.errNote(a_src, msg, "length {f} here", .{
44844483 v.fmtValueSema(pt, sema),
44854484 });
4486 try sema.errNote(arg_src, msg, "length {} here", .{
4485 try sema.errNote(arg_src, msg, "length {f} here", .{
44874486 arg_val.fmtValueSema(pt, sema),
44884487 });
44894488 break :msg msg;
......@@ -4515,7 +4514,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
45154514 .for_node_offset = inst_data.src_node,
45164515 .input_index = i,
45174516 } });
4518 try sema.errNote(arg_src, msg, "type '{}' has no upper bound", .{
4517 try sema.errNote(arg_src, msg, "type '{f}' has no upper bound", .{
45194518 object_ty.fmt(pt),
45204519 });
45214520 }
......@@ -4591,7 +4590,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
45914590 switch (val_ty.zigTypeTag(zcu)) {
45924591 .array, .vector => {},
45934592 else => if (!val_ty.isTuple(zcu)) {
4594 return sema.fail(block, src, "expected array of '{}', found '{}'", .{ elem_ty.fmt(pt), val_ty.fmt(pt) });
4593 return sema.fail(block, src, "expected array of '{f}', found '{f}'", .{ elem_ty.fmt(pt), val_ty.fmt(pt) });
45954594 },
45964595 }
45974596 const want_ty = try pt.arrayType(.{
......@@ -4665,7 +4664,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
46654664 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;
46664665 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {
46674666 return sema.failWithOwnedErrorMsg(block, msg: {
4668 const msg = try sema.errMsg(src, "expected type '{}', found pointer", .{ty_operand.fmt(pt)});
4667 const msg = try sema.errMsg(src, "expected type '{f}', found pointer", .{ty_operand.fmt(pt)});
46694668 errdefer msg.destroy(sema.gpa);
46704669 try sema.errNote(src, msg, "address-of operator always returns a pointer", .{});
46714670 break :msg msg;
......@@ -5074,7 +5073,7 @@ fn validateStructInit(
50745073 }
50755074 continue;
50765075 };
5077 const template = "missing struct field: {}";
5076 const template = "missing struct field: {f}";
50785077 const args = .{field_name.fmt(ip)};
50795078 if (root_msg) |msg| {
50805079 try sema.errNote(init_src, msg, template, args);
......@@ -5204,7 +5203,7 @@ fn validateStructInit(
52045203 }
52055204 continue;
52065205 };
5207 const template = "missing struct field: {}";
5206 const template = "missing struct field: {f}";
52085207 const args = .{field_name.fmt(ip)};
52095208 if (root_msg) |msg| {
52105209 try sema.errNote(init_src, msg, template, args);
......@@ -5508,11 +5507,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
55085507 const operand_ty = sema.typeOf(operand);
55095508
55105509 if (operand_ty.zigTypeTag(zcu) != .pointer) {
5511 return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(pt)});
5510 return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{operand_ty.fmt(pt)});
55125511 } else switch (operand_ty.ptrSize(zcu)) {
55135512 .one, .c => {},
5514 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(pt)}),
5515 .slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(pt)}),
5513 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{operand_ty.fmt(pt)}),
5514 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),
55165515 }
55175516
55185517 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) {
......@@ -5529,7 +5528,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
55295528 const msg = msg: {
55305529 const msg = try sema.errMsg(
55315530 src,
5532 "values of type '{}' must be comptime-known, but operand value is runtime-known",
5531 "values of type '{f}' must be comptime-known, but operand value is runtime-known",
55335532 .{elem_ty.fmt(pt)},
55345533 );
55355534 errdefer msg.destroy(sema.gpa);
......@@ -5561,7 +5560,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
55615560
55625561 if (!typeIsDestructurable(operand_ty, zcu)) {
55635562 return sema.failWithOwnedErrorMsg(block, msg: {
5564 const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)});
5563 const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)});
55655564 errdefer msg.destroy(sema.gpa);
55665565 try sema.errNote(destructure_src, msg, "result destructured here", .{});
55675566 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {
......@@ -5604,12 +5603,12 @@ fn failWithBadMemberAccess(
56045603 else => unreachable,
56055604 };
56065605 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {
5607 return sema.fail(block, field_src, "root source file struct '{}' has no member named '{}'", .{
5606 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
56085607 agg_ty.fmt(pt), field_name.fmt(ip),
56095608 });
56105609 };
56115610
5612 return sema.fail(block, field_src, "{s} '{}' has no member named '{}'", .{
5611 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
56135612 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
56145613 });
56155614}
......@@ -5629,7 +5628,7 @@ fn failWithBadStructFieldAccess(
56295628 const msg = msg: {
56305629 const msg = try sema.errMsg(
56315630 field_src,
5632 "no field named '{}' in struct '{}'",
5631 "no field named '{f}' in struct '{f}'",
56335632 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },
56345633 );
56355634 errdefer msg.destroy(sema.gpa);
......@@ -5655,7 +5654,7 @@ fn failWithBadUnionFieldAccess(
56555654 const msg = msg: {
56565655 const msg = try sema.errMsg(
56575656 field_src,
5658 "no field named '{}' in union '{}'",
5657 "no field named '{f}' in union '{f}'",
56595658 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },
56605659 );
56615660 errdefer msg.destroy(gpa);
......@@ -5907,30 +5906,30 @@ fn zirCompileLog(
59075906 const zcu = pt.zcu;
59085907 const gpa = zcu.gpa;
59095908
5910 var buf: std.ArrayListUnmanaged(u8) = .empty;
5911 defer buf.deinit(gpa);
5912
5913 const writer = buf.writer(gpa);
5909 var aw: std.io.Writer.Allocating = .init(gpa);
5910 defer aw.deinit();
5911 const bw = &aw.interface;
59145912
59155913 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
59165914 const src_node = extra.data.src_node;
59175915 const args = sema.code.refSlice(extra.end, extended.small);
59185916
59195917 for (args, 0..) |arg_ref, i| {
5920 if (i != 0) try writer.print(", ", .{});
5918 if (i != 0) bw.writeAll(", ") catch return error.OutOfMemory;
59215919
59225920 const arg = try sema.resolveInst(arg_ref);
59235921 const arg_ty = sema.typeOf(arg);
59245922 if (try sema.resolveValueResolveLazy(arg)) |val| {
5925 try writer.print("@as({}, {})", .{
5923 bw.print("@as({f}, {f})", .{
59265924 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),
5927 });
5925 }) catch return error.OutOfMemory;
59285926 } else {
5929 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(pt)});
5927 bw.print("@as({f}, [runtime value])", .{arg_ty.fmt(pt)}) catch return error.OutOfMemory;
59305928 }
59315929 }
5930 bw.writeByte('\n') catch return error.OutOfMemory;
59325931
5933 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);
5932 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, aw.getWritten(), .no_embedded_nulls);
59345933
59355934 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {
59365935 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{
......@@ -6472,7 +6471,7 @@ fn resolveAnalyzedBlock(
64726471 const type_src = src; // TODO: better source location
64736472 if (try resolved_ty.comptimeOnlySema(pt)) {
64746473 const msg = msg: {
6475 const msg = try sema.errMsg(type_src, "value with comptime-only type '{}' depends on runtime control flow", .{resolved_ty.fmt(pt)});
6474 const msg = try sema.errMsg(type_src, "value with comptime-only type '{f}' depends on runtime control flow", .{resolved_ty.fmt(pt)});
64766475 errdefer msg.destroy(sema.gpa);
64776476
64786477 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;
......@@ -6588,7 +6587,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
65886587
65896588 {
65906589 if (ptr_ty.zigTypeTag(zcu) != .pointer) {
6591 return sema.fail(block, ptr_src, "expected pointer type, found '{}'", .{ptr_ty.fmt(pt)});
6590 return sema.fail(block, ptr_src, "expected pointer type, found '{f}'", .{ptr_ty.fmt(pt)});
65926591 }
65936592 const ptr_ty_info = ptr_ty.ptrInfo(zcu);
65946593 if (ptr_ty_info.flags.size == .slice) {
......@@ -6611,7 +6610,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
66116610 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);
66126611 if (!try sema.validateExternType(export_ty, .other)) {
66136612 return sema.failWithOwnedErrorMsg(block, msg: {
6614 const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)});
6613 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)});
66156614 errdefer msg.destroy(sema.gpa);
66166615 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
66176616 try sema.addDeclaredHereNote(msg, export_ty);
......@@ -6663,7 +6662,7 @@ pub fn analyzeExport(
66636662
66646663 if (!try sema.validateExternType(export_ty, .other)) {
66656664 return sema.failWithOwnedErrorMsg(block, msg: {
6666 const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)});
6665 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)});
66676666 errdefer msg.destroy(gpa);
66686667
66696668 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
......@@ -7287,7 +7286,7 @@ fn checkCallArgumentCount(
72877286 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))
72887287 {
72897288 const msg = msg: {
7290 const msg = try sema.errMsg(func_src, "cannot call optional type '{}'", .{
7289 const msg = try sema.errMsg(func_src, "cannot call optional type '{f}'", .{
72917290 callee_ty.fmt(pt),
72927291 });
72937292 errdefer msg.destroy(sema.gpa);
......@@ -7299,7 +7298,7 @@ fn checkCallArgumentCount(
72997298 },
73007299 else => {},
73017300 }
7302 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(pt)});
7301 return sema.fail(block, func_src, "type '{f}' not a function", .{callee_ty.fmt(pt)});
73037302 };
73047303
73057304 const func_ty_info = zcu.typeToFunc(func_ty).?;
......@@ -7362,7 +7361,7 @@ fn callBuiltin(
73627361 },
73637362 else => {},
73647363 }
7365 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(pt)});
7364 std.debug.panic("type '{f}' is not a function calling builtin fn", .{callee_ty.fmt(pt)});
73667365 };
73677366
73687367 const func_ty_info = zcu.typeToFunc(func_ty).?;
......@@ -7746,7 +7745,7 @@ fn analyzeCall(
77467745
77477746 if (!param_ty.isValidParamType(zcu)) {
77487747 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
7749 return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{
7748 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
77507749 opaque_str, param_ty.fmt(pt),
77517750 });
77527751 }
......@@ -7843,7 +7842,7 @@ fn analyzeCall(
78437842
78447843 if (!full_ty.isValidReturnType(zcu)) {
78457844 const opaque_str = if (full_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
7846 return sema.fail(block, func_ret_ty_src, "{s}return type '{}' not allowed", .{
7845 return sema.fail(block, func_ret_ty_src, "{s}return type '{f}' not allowed", .{
78477846 opaque_str, full_ty.fmt(pt),
78487847 });
78497848 }
......@@ -8301,7 +8300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
83018300 }
83028301 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);
83038302 if (owner_func_ty.toIntern() != func_ty.toIntern()) {
8304 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
8303 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{f}' does not match type of calling function '{f}'", .{
83058304 func_ty.fmt(pt), owner_func_ty.fmt(pt),
83068305 });
83078306 }
......@@ -8325,9 +8324,9 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
83258324 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });
83268325 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);
83278326 if (child_type.zigTypeTag(zcu) == .@"opaque") {
8328 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(pt)});
8327 return sema.fail(block, operand_src, "opaque type '{f}' cannot be optional", .{child_type.fmt(pt)});
83298328 } else if (child_type.zigTypeTag(zcu) == .null) {
8330 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(pt)});
8329 return sema.fail(block, operand_src, "type '{f}' cannot be optional", .{child_type.fmt(pt)});
83318330 }
83328331 const opt_type = try pt.optionalType(child_type.toIntern());
83338332
......@@ -8388,7 +8387,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
83888387 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
83898388 switch (vec_ty.zigTypeTag(zcu)) {
83908389 .array, .vector => {},
8391 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{}'", .{vec_ty.fmt(pt)}),
8390 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}),
83928391 }
83938392 return Air.internedToRef(vec_ty.childType(zcu).toIntern());
83948393}
......@@ -8456,7 +8455,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:
84568455 const pt = sema.pt;
84578456 const zcu = pt.zcu;
84588457 if (elem_type.zigTypeTag(zcu) == .@"opaque") {
8459 return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(pt)});
8458 return sema.fail(block, elem_src, "array of opaque type '{f}' not allowed", .{elem_type.fmt(pt)});
84608459 } else if (elem_type.zigTypeTag(zcu) == .noreturn) {
84618460 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});
84628461 }
......@@ -8492,7 +8491,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
84928491 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
84938492
84948493 if (error_set.zigTypeTag(zcu) != .error_set) {
8495 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{
8494 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{
84968495 error_set.fmt(pt),
84978496 });
84988497 }
......@@ -8505,11 +8504,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p
85058504 const pt = sema.pt;
85068505 const zcu = pt.zcu;
85078506 if (payload_ty.zigTypeTag(zcu) == .@"opaque") {
8508 return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{
8507 return sema.fail(block, payload_src, "error union with payload of opaque type '{f}' not allowed", .{
85098508 payload_ty.fmt(pt),
85108509 });
85118510 } else if (payload_ty.zigTypeTag(zcu) == .error_set) {
8512 return sema.fail(block, payload_src, "error union with payload of error set type '{}' not allowed", .{
8511 return sema.fail(block, payload_src, "error union with payload of error set type '{f}' not allowed", .{
85138512 payload_ty.fmt(pt),
85148513 });
85158514 }
......@@ -8647,9 +8646,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
86478646 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);
86488647 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);
86498648 if (lhs_ty.zigTypeTag(zcu) != .error_set)
8650 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(pt)});
8649 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{lhs_ty.fmt(pt)});
86518650 if (rhs_ty.zigTypeTag(zcu) != .error_set)
8652 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(pt)});
8651 return sema.fail(block, rhs_src, "expected error set type, found '{f}'", .{rhs_ty.fmt(pt)});
86538652
86548653 // Anything merged with anyerror is anyerror.
86558654 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {
......@@ -8759,7 +8758,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
87598758 return sema.fail(
87608759 block,
87618760 operand_src,
8762 "untagged union '{}' cannot be converted to integer",
8761 "untagged union '{f}' cannot be converted to integer",
87638762 .{operand_ty.fmt(pt)},
87648763 );
87658764 };
......@@ -8767,7 +8766,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
87678766 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);
87688767 },
87698768 else => {
8770 return sema.fail(block, operand_src, "expected enum or tagged union, found '{}'", .{
8769 return sema.fail(block, operand_src, "expected enum or tagged union, found '{f}'", .{
87718770 operand_ty.fmt(pt),
87728771 });
87738772 },
......@@ -8778,7 +8777,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
87788777 // TODO: use correct solution
87798778 // https://github.com/ziglang/zig/issues/15909
87808779 if (enum_tag_ty.enumFieldCount(zcu) == 0 and !enum_tag_ty.isNonexhaustiveEnum(zcu)) {
8781 return sema.fail(block, operand_src, "cannot use @intFromEnum on empty enum '{}'", .{
8780 return sema.fail(block, operand_src, "cannot use @intFromEnum on empty enum '{f}'", .{
87828781 enum_tag_ty.fmt(pt),
87838782 });
87848783 }
......@@ -8812,7 +8811,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
88128811 const operand_ty = sema.typeOf(operand);
88138812
88148813 if (dest_ty.zigTypeTag(zcu) != .@"enum") {
8815 return sema.fail(block, src, "expected enum, found '{}'", .{dest_ty.fmt(pt)});
8814 return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)});
88168815 }
88178816 _ = try sema.checkIntType(block, operand_src, operand_ty);
88188817
......@@ -8822,7 +8821,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
88228821 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
88238822 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());
88248823 }
8825 return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{
8824 return sema.fail(block, src, "int value '{f}' out of range of non-exhaustive enum '{f}'", .{
88268825 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt),
88278826 });
88288827 }
......@@ -8830,7 +8829,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
88308829 return sema.failWithUseOfUndef(block, operand_src);
88318830 }
88328831 if (!(try sema.enumHasInt(dest_ty, int_val))) {
8833 return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{
8832 return sema.fail(block, src, "enum '{f}' has no tag with value '{f}'", .{
88348833 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),
88358834 });
88368835 }
......@@ -9024,7 +9023,7 @@ fn zirErrUnionPayload(
90249023 const operand_src = src;
90259024 const err_union_ty = sema.typeOf(operand);
90269025 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
9027 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{
9026 return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{
90289027 err_union_ty.fmt(pt),
90299028 });
90309029 }
......@@ -9092,7 +9091,7 @@ fn analyzeErrUnionPayloadPtr(
90929091 assert(operand_ty.zigTypeTag(zcu) == .pointer);
90939092
90949093 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {
9095 return sema.fail(block, src, "expected error union type, found '{}'", .{
9094 return sema.fail(block, src, "expected error union type, found '{f}'", .{
90969095 operand_ty.childType(zcu).fmt(pt),
90979096 });
90989097 }
......@@ -9169,7 +9168,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
91699168 const zcu = pt.zcu;
91709169 const operand_ty = sema.typeOf(operand);
91719170 if (operand_ty.zigTypeTag(zcu) != .error_union) {
9172 return sema.fail(block, src, "expected error union type, found '{}'", .{
9171 return sema.fail(block, src, "expected error union type, found '{f}'", .{
91739172 operand_ty.fmt(pt),
91749173 });
91759174 }
......@@ -9205,7 +9204,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:
92059204 assert(operand_ty.zigTypeTag(zcu) == .pointer);
92069205
92079206 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {
9208 return sema.fail(block, src, "expected error union type, found '{}'", .{
9207 return sema.fail(block, src, "expected error union type, found '{f}'", .{
92099208 operand_ty.childType(zcu).fmt(pt),
92109209 });
92119210 }
......@@ -9450,19 +9449,18 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
94509449fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {
94519450 const CallingConventionsSupportingVarArgsList = struct {
94529451 arch: std.Target.Cpu.Arch,
9453 pub fn format(ctx: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
9454 _ = fmt;
9455 _ = options;
9452 pub fn format(ctx: @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
9453 comptime assert(fmt.len == 0);
94569454 var first = true;
94579455 for (calling_conventions_supporting_var_args) |cc_inner| {
94589456 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {
94599457 if (supported_arch == ctx.arch) break;
94609458 } else continue; // callconv not supported by this arch
94619459 if (!first) {
9462 try writer.writeAll(", ");
9460 try w.writeAll(", ");
94639461 }
94649462 first = false;
9465 try writer.print("'{s}'", .{@tagName(cc_inner)});
9463 try w.print("'{s}'", .{@tagName(cc_inner)});
94669464 }
94679465 }
94689466 };
......@@ -9472,7 +9470,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
94729470 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});
94739471 errdefer msg.destroy(sema.gpa);
94749472 const target = sema.pt.zcu.getTarget();
9475 try sema.errNote(src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});
9473 try sema.errNote(src, msg, "supported calling conventions: {f}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});
94769474 break :msg msg;
94779475 });
94789476 }
......@@ -9520,7 +9518,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)
95209518 }
95219519
95229520 return sema.failWithOwnedErrorMsg(block, msg: {
9523 const msg = try sema.errMsg(src, "value with non-mergable pointer type '{}' depends on runtime control flow", .{peer_ty.fmt(pt)});
9521 const msg = try sema.errMsg(src, "value with non-mergable pointer type '{f}' depends on runtime control flow", .{peer_ty.fmt(pt)});
95249522 errdefer msg.destroy(sema.gpa);
95259523
95269524 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;
......@@ -9598,13 +9596,13 @@ fn funcCommon(
95989596 }
95999597 if (!param_ty.isValidParamType(zcu)) {
96009598 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9601 return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{
9599 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
96029600 opaque_str, param_ty.fmt(pt),
96039601 });
96049602 }
96059603 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {
96069604 const msg = msg: {
9607 const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9605 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{
96089606 param_ty.fmt(pt), @tagName(cc),
96099607 });
96109608 errdefer msg.destroy(sema.gpa);
......@@ -9618,7 +9616,7 @@ fn funcCommon(
96189616 }
96199617 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
96209618 const msg = msg: {
9621 const msg = try sema.errMsg(param_src, "parameter of type '{}' must be declared comptime", .{
9619 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
96229620 param_ty.fmt(pt),
96239621 });
96249622 errdefer msg.destroy(sema.gpa);
......@@ -9798,7 +9796,7 @@ fn finishFunc(
97989796
97999797 if (!return_type.isValidReturnType(zcu)) {
98009798 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9801 return sema.fail(block, ret_ty_src, "{s}return type '{}' not allowed", .{
9799 return sema.fail(block, ret_ty_src, "{s}return type '{f}' not allowed", .{
98029800 opaque_str, return_type.fmt(pt),
98039801 });
98049802 }
......@@ -9806,7 +9804,7 @@ fn finishFunc(
98069804 !try sema.validateExternType(return_type, .ret_ty))
98079805 {
98089806 const msg = msg: {
9809 const msg = try sema.errMsg(ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9807 const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{s}'", .{
98109808 return_type.fmt(pt), @tagName(cc_resolved),
98119809 });
98129810 errdefer msg.destroy(gpa);
......@@ -9828,7 +9826,7 @@ fn finishFunc(
98289826
98299827 const msg = try sema.errMsg(
98309828 ret_ty_src,
9831 "function with comptime-only return type '{}' requires all parameters to be comptime",
9829 "function with comptime-only return type '{f}' requires all parameters to be comptime",
98329830 .{return_type.fmt(pt)},
98339831 );
98349832 errdefer msg.destroy(sema.gpa);
......@@ -9897,17 +9895,16 @@ fn finishFunc(
98979895 .bad_arch => |allowed_archs| {
98989896 const ArchListFormatter = struct {
98999897 archs: []const std.Target.Cpu.Arch,
9900 pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
9901 _ = fmt;
9902 _ = options;
9898 pub fn format(formatter: @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
9899 comptime assert(fmt.len == 0);
99039900 for (formatter.archs, 0..) |arch, i| {
99049901 if (i != 0)
9905 try writer.writeAll(", ");
9906 try writer.print("'{s}'", .{@tagName(arch)});
9902 try w.writeAll(", ");
9903 try w.print("'{s}'", .{@tagName(arch)});
99079904 }
99089905 }
99099906 };
9910 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {}", .{
9907 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {f}", .{
99119908 @tagName(cc_resolved),
99129909 ArchListFormatter{ .archs = allowed_archs },
99139910 });
......@@ -10008,7 +10005,7 @@ fn analyzeAs(
1000810005 const operand = try sema.resolveInst(zir_operand);
1000910006 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
1001010007 switch (dest_ty.zigTypeTag(zcu)) {
10011 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{}'", .{dest_ty.fmt(pt)}),
10008 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)}),
1001210009 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
1001310010 else => {},
1001410011 }
......@@ -10036,12 +10033,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1003610033 const ptr_ty = operand_ty.scalarType(zcu);
1003710034 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
1003810035 if (!ptr_ty.isPtrAtRuntime(zcu)) {
10039 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(pt)});
10036 return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)});
1004010037 }
1004110038 const pointee_ty = ptr_ty.childType(zcu);
1004210039 if (try ptr_ty.comptimeOnlySema(pt)) {
1004310040 const msg = msg: {
10044 const msg = try sema.errMsg(ptr_src, "comptime-only type '{}' has no pointer address", .{pointee_ty.fmt(pt)});
10041 const msg = try sema.errMsg(ptr_src, "comptime-only type '{f}' has no pointer address", .{pointee_ty.fmt(pt)});
1004510042 errdefer msg.destroy(sema.gpa);
1004610043 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);
1004710044 break :msg msg;
......@@ -10289,14 +10286,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1028910286 .type,
1029010287 .undefined,
1029110288 .void,
10292 => return sema.fail(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)}),
10289 => return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}),
1029310290
1029410291 .@"enum" => {
1029510292 const msg = msg: {
10296 const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)});
10293 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
1029710294 errdefer msg.destroy(sema.gpa);
1029810295 switch (operand_ty.zigTypeTag(zcu)) {
10299 .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(pt)}),
10296 .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
1030010297 else => {},
1030110298 }
1030210299
......@@ -10307,11 +10304,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1030710304
1030810305 .pointer => {
1030910306 const msg = msg: {
10310 const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)});
10307 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
1031110308 errdefer msg.destroy(sema.gpa);
1031210309 switch (operand_ty.zigTypeTag(zcu)) {
10313 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(pt)}),
10314 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(pt)}),
10310 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
10311 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}),
1031510312 else => {},
1031610313 }
1031710314
......@@ -10325,7 +10322,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1032510322 .@"union" => "union",
1032610323 else => unreachable,
1032710324 };
10328 return sema.fail(block, src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{
10325 return sema.fail(block, src, "cannot @bitCast to '{f}'; {s} does not have a guaranteed in-memory layout", .{
1032910326 dest_ty.fmt(pt), container,
1033010327 });
1033110328 },
......@@ -10353,14 +10350,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1035310350 .type,
1035410351 .undefined,
1035510352 .void,
10356 => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)}),
10353 => return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)}),
1035710354
1035810355 .@"enum" => {
1035910356 const msg = msg: {
10360 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)});
10357 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
1036110358 errdefer msg.destroy(sema.gpa);
1036210359 switch (dest_ty.zigTypeTag(zcu)) {
10363 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{}'", .{dest_ty.fmt(pt)}),
10360 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{f}'", .{dest_ty.fmt(pt)}),
1036410361 else => {},
1036510362 }
1036610363
......@@ -10370,11 +10367,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1037010367 },
1037110368 .pointer => {
1037210369 const msg = msg: {
10373 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)});
10370 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
1037410371 errdefer msg.destroy(sema.gpa);
1037510372 switch (dest_ty.zigTypeTag(zcu)) {
10376 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{}'", .{dest_ty.fmt(pt)}),
10377 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(pt)}),
10373 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{f}'", .{dest_ty.fmt(pt)}),
10374 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}),
1037810375 else => {},
1037910376 }
1038010377
......@@ -10388,7 +10385,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1038810385 .@"union" => "union",
1038910386 else => unreachable,
1039010387 };
10391 return sema.fail(block, operand_src, "cannot @bitCast from '{}'; {s} does not have a guaranteed in-memory layout", .{
10388 return sema.fail(block, operand_src, "cannot @bitCast from '{f}'; {s} does not have a guaranteed in-memory layout", .{
1039210389 operand_ty.fmt(pt), container,
1039310390 });
1039410391 },
......@@ -10431,7 +10428,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1043110428 else => return sema.fail(
1043210429 block,
1043310430 src,
10434 "expected float or vector type, found '{}'",
10431 "expected float or vector type, found '{f}'",
1043510432 .{dest_ty.fmt(pt)},
1043610433 ),
1043710434 };
......@@ -10441,7 +10438,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1044110438 else => return sema.fail(
1044210439 block,
1044310440 operand_src,
10444 "expected float or vector type, found '{}'",
10441 "expected float or vector type, found '{f}'",
1044510442 .{operand_ty.fmt(pt)},
1044610443 ),
1044710444 }
......@@ -10525,7 +10522,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1052510522 if (indexable_ty.zigTypeTag(zcu) != .pointer) {
1052610523 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });
1052710524 const msg = msg: {
10528 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{}'", .{
10525 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{f}'", .{
1052910526 indexable_ty.fmt(pt),
1053010527 });
1053110528 errdefer msg.destroy(sema.gpa);
......@@ -10667,7 +10664,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1066710664 const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand));
1066810665 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {
1066910666 .pointer => lhs_ptr_ty.childType(zcu),
10670 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{lhs_ptr_ty.fmt(pt)}),
10667 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{lhs_ptr_ty.fmt(pt)}),
1067110668 };
1067210669
1067310670 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {
......@@ -10682,7 +10679,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1068210679 };
1068310680 },
1068410681 },
10685 else => return sema.fail(block, src, "slice of non-array type '{}'", .{lhs_ty.fmt(pt)}),
10682 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{lhs_ty.fmt(pt)}),
1068610683 };
1068710684
1068810685 return Air.internedToRef(sentinel_ty.toIntern());
......@@ -10877,7 +10874,7 @@ const SwitchProngAnalysis = struct {
1087710874 .base_node_inst = capture_src.base_node_inst,
1087810875 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },
1087910876 };
10880 return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{}'", .{
10877 return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{f}'", .{
1088110878 operand_ty.fmt(pt),
1088210879 });
1088310880 }
......@@ -11309,7 +11306,7 @@ fn switchCond(
1130911306 .@"enum",
1131011307 => {
1131111308 if (operand_ty.isSlice(zcu)) {
11312 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(pt)});
11309 return sema.fail(block, src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
1131311310 }
1131411311 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
1131511312 return Air.internedToRef(opv.toIntern());
......@@ -11344,7 +11341,7 @@ fn switchCond(
1134411341 .vector,
1134511342 .frame,
1134611343 .@"anyframe",
11347 => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(pt)}),
11344 => return sema.fail(block, src, "switch on type '{f}'", .{operand_ty.fmt(pt)}),
1134811345 }
1134911346}
1135011347
......@@ -11445,7 +11442,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
1144511442 operand_ty;
1144611443
1144711444 if (operand_err_set.zigTypeTag(zcu) != .error_union) {
11448 return sema.fail(block, switch_src, "expected error union type, found '{}'", .{
11445 return sema.fail(block, switch_src, "expected error union type, found '{f}'", .{
1144911446 operand_ty.fmt(pt),
1145011447 });
1145111448 }
......@@ -11699,7 +11696,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1169911696 // Even if the operand is comptime-known, this `switch` is runtime.
1170011697 if (try operand_ty.comptimeOnlySema(pt)) {
1170111698 return sema.failWithOwnedErrorMsg(block, msg: {
11702 const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{}'", .{operand_ty.fmt(pt)});
11699 const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)});
1170311700 errdefer msg.destroy(gpa);
1170411701 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});
1170511702 break :msg msg;
......@@ -11923,14 +11920,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1192311920 cond_ty,
1192411921 i,
1192511922 msg,
11926 "unhandled enumeration value: '{}'",
11923 "unhandled enumeration value: '{f}'",
1192711924 .{field_name.fmt(&zcu.intern_pool)},
1192811925 );
1192911926 }
1193011927 try sema.errNote(
1193111928 cond_ty.srcLoc(zcu),
1193211929 msg,
11933 "enum '{}' declared here",
11930 "enum '{f}' declared here",
1193411931 .{cond_ty.fmt(pt)},
1193511932 );
1193611933 break :msg msg;
......@@ -12142,7 +12139,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1214212139 return sema.fail(
1214312140 block,
1214412141 src,
12145 "else prong required when switching on type '{}'",
12142 "else prong required when switching on type '{f}'",
1214612143 .{cond_ty.fmt(pt)},
1214712144 );
1214812145 }
......@@ -12218,7 +12215,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1221812215 .@"anyframe",
1221912216 .comptime_float,
1222012217 .float,
12221 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{
12218 => return sema.fail(block, operand_src, "invalid switch operand type '{f}'", .{
1222212219 raw_operand_ty.fmt(pt),
1222312220 }),
1222412221 }
......@@ -12747,7 +12744,7 @@ fn analyzeSwitchRuntimeBlock(
1274712744 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {
1274812745 .@"enum" => {
1274912746 if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) {
12750 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{
12747 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
1275112748 operand_ty.fmt(pt),
1275212749 });
1275312750 }
......@@ -12803,7 +12800,7 @@ fn analyzeSwitchRuntimeBlock(
1280312800 },
1280412801 .error_set => {
1280512802 if (operand_ty.isAnyError(zcu)) {
12806 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{
12803 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
1280712804 operand_ty.fmt(pt),
1280812805 });
1280912806 }
......@@ -12964,7 +12961,7 @@ fn analyzeSwitchRuntimeBlock(
1296412961 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));
1296512962 }
1296612963 },
12967 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{
12964 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
1296812965 operand_ty.fmt(pt),
1296912966 }),
1297012967 };
......@@ -13478,7 +13475,7 @@ fn validateErrSetSwitch(
1347813475 try sema.errNote(
1347913476 src,
1348013477 msg,
13481 "unhandled error value: 'error.{}'",
13478 "unhandled error value: 'error.{f}'",
1348213479 .{error_name.fmt(ip)},
1348313480 );
1348413481 }
......@@ -13704,7 +13701,7 @@ fn validateSwitchNoRange(
1370413701 const msg = msg: {
1370513702 const msg = try sema.errMsg(
1370613703 operand_src,
13707 "ranges not allowed when switching on type '{}'",
13704 "ranges not allowed when switching on type '{f}'",
1370813705 .{operand_ty.fmt(sema.pt)},
1370913706 );
1371013707 errdefer msg.destroy(sema.gpa);
......@@ -13862,7 +13859,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1386213859 .array_type => break :hf field_name.eqlSlice("len", ip),
1386313860 else => {},
1386413861 }
13865 return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
13862 return sema.fail(block, ty_src, "type '{f}' does not support '@hasField'", .{
1386613863 ty.fmt(pt),
1386713864 });
1386813865 };
......@@ -14050,7 +14047,7 @@ fn zirShl(
1405014047 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1405114048 const rhs_elem = try rhs_val.elemValue(pt, i);
1405214049 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {
14053 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{
14050 return sema.fail(block, rhs_src, "shift amount '{f}' at index '{d}' is too large for operand type '{f}'", .{
1405414051 rhs_elem.fmtValueSema(pt, sema),
1405514052 i,
1405614053 scalar_ty.fmt(pt),
......@@ -14058,7 +14055,7 @@ fn zirShl(
1405814055 }
1405914056 }
1406014057 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {
14061 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
14058 return sema.fail(block, rhs_src, "shift amount '{f}' is too large for operand type '{f}'", .{
1406214059 rhs_val.fmtValueSema(pt, sema),
1406314060 scalar_ty.fmt(pt),
1406414061 });
......@@ -14069,14 +14066,14 @@ fn zirShl(
1406914066 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1407014067 const rhs_elem = try rhs_val.elemValue(pt, i);
1407114068 if (rhs_elem.compareHetero(.lt, try pt.intValue(scalar_rhs_ty, 0), zcu)) {
14072 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
14069 return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
1407314070 rhs_elem.fmtValueSema(pt, sema),
1407414071 i,
1407514072 });
1407614073 }
1407714074 }
1407814075 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
14079 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
14076 return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
1408014077 rhs_val.fmtValueSema(pt, sema),
1408114078 });
1408214079 }
......@@ -14231,7 +14228,7 @@ fn zirShr(
1423114228 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1423214229 const rhs_elem = try rhs_val.elemValue(pt, i);
1423314230 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {
14234 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{
14231 return sema.fail(block, rhs_src, "shift amount '{f}' at index '{d}' is too large for operand type '{f}'", .{
1423514232 rhs_elem.fmtValueSema(pt, sema),
1423614233 i,
1423714234 scalar_ty.fmt(pt),
......@@ -14239,7 +14236,7 @@ fn zirShr(
1423914236 }
1424014237 }
1424114238 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {
14242 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
14239 return sema.fail(block, rhs_src, "shift amount '{f}' is too large for operand type '{f}'", .{
1424314240 rhs_val.fmtValueSema(pt, sema),
1424414241 scalar_ty.fmt(pt),
1424514242 });
......@@ -14250,14 +14247,14 @@ fn zirShr(
1425014247 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
1425114248 const rhs_elem = try rhs_val.elemValue(pt, i);
1425214249 if (rhs_elem.compareHetero(.lt, try pt.intValue(rhs_ty.childType(zcu), 0), zcu)) {
14253 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
14250 return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
1425414251 rhs_elem.fmtValueSema(pt, sema),
1425514252 i,
1425614253 });
1425714254 }
1425814255 }
1425914256 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
14260 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
14257 return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
1426114258 rhs_val.fmtValueSema(pt, sema),
1426214259 });
1426314260 }
......@@ -14543,11 +14540,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1454314540
1454414541 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {
1454514542 if (lhs_is_tuple) break :lhs_info undefined;
14546 return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)});
14543 return sema.fail(block, lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
1454714544 };
1454814545 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {
1454914546 assert(!rhs_is_tuple);
14550 return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(pt)});
14547 return sema.fail(block, rhs_src, "expected indexable; found '{f}'", .{rhs_ty.fmt(pt)});
1455114548 };
1455214549
1455314550 const resolved_elem_ty = t: {
......@@ -15000,7 +14997,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1500014997 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
1500114998 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
1500214999 const msg = msg: {
15003 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)});
15000 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
1500415001 errdefer msg.destroy(sema.gpa);
1500515002 switch (lhs_ty.zigTypeTag(zcu)) {
1500615003 .int, .float, .comptime_float, .comptime_int, .vector => {
......@@ -15132,7 +15129,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1513215129 .int, .comptime_int, .float, .comptime_float => false,
1513315130 else => true,
1513415131 }) {
15135 return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(pt)});
15132 return sema.fail(block, src, "negation of type '{f}'", .{rhs_ty.fmt(pt)});
1513615133 }
1513715134
1513815135 if (rhs_scalar_ty.isAnyFloat()) {
......@@ -15163,7 +15160,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1516315160
1516415161 switch (rhs_scalar_ty.zigTypeTag(zcu)) {
1516515162 .int, .comptime_int, .float, .comptime_float => {},
15166 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(pt)}),
15163 else => return sema.fail(block, src, "negation of type '{f}'", .{rhs_ty.fmt(pt)}),
1516715164 }
1516815165
1516915166 const lhs = Air.internedToRef((try sema.splat(rhs_ty, try pt.intValue(rhs_scalar_ty, 0))).toIntern());
......@@ -15237,7 +15234,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1523715234 return sema.fail(
1523815235 block,
1523915236 src,
15240 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",
15237 "ambiguous coercion of division operands '{f}' and '{f}'; non-zero remainder '{f}'",
1524115238 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), rem.fmtValueSema(pt, sema) },
1524215239 );
1524315240 }
......@@ -15289,7 +15286,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1528915286 return sema.fail(
1529015287 block,
1529115288 src,
15292 "division with '{}' and '{}': signed integers must use @divTrunc, @divFloor, or @divExact",
15289 "division with '{f}' and '{f}': signed integers must use @divTrunc, @divFloor, or @divExact",
1529315290 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },
1529415291 );
1529515292 }
......@@ -15951,7 +15948,7 @@ fn zirOverflowArithmetic(
1595115948 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);
1595215949
1595315950 if (dest_ty.scalarType(zcu).zigTypeTag(zcu) != .int) {
15954 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(pt)});
15951 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{f}'", .{dest_ty.fmt(pt)});
1595515952 }
1595615953
1595715954 const maybe_lhs_val = try sema.resolveValue(lhs);
......@@ -16157,14 +16154,14 @@ fn analyzeArithmetic(
1615716154 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");
1615816155 }
1615916156 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {
16160 return sema.fail(block, src, "incompatible pointer arithmetic operands '{}' and '{}'", .{
16157 return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{
1616116158 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
1616216159 });
1616316160 }
1616416161
1616516162 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
1616616163 if (elem_size == 0) {
16167 return sema.fail(block, src, "pointer arithmetic requires element type '{}' to have runtime bits", .{
16164 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
1616816165 lhs_ty.elemType2(zcu).fmt(pt),
1616916166 });
1617016167 }
......@@ -16215,7 +16212,7 @@ fn analyzeArithmetic(
1621516212 };
1621616213
1621716214 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {
16218 return sema.fail(block, src, "pointer arithmetic requires element type '{}' to have runtime bits", .{
16215 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
1621916216 lhs_ty.elemType2(zcu).fmt(pt),
1622016217 });
1622116218 }
......@@ -16619,7 +16616,7 @@ fn zirCmpEq(
1661916616
1662016617 if (lhs_ty_tag == .null or rhs_ty_tag == .null) {
1662116618 const non_null_type = if (lhs_ty_tag == .null) rhs_ty else lhs_ty;
16622 return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type.fmt(pt)});
16619 return sema.fail(block, src, "comparison of '{f}' with null", .{non_null_type.fmt(pt)});
1662316620 }
1662416621
1662516622 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {
......@@ -16676,7 +16673,7 @@ fn analyzeCmpUnionTag(
1667616673 const msg = msg: {
1667716674 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
1667816675 errdefer msg.destroy(sema.gpa);
16679 try sema.errNote(union_ty.srcLoc(zcu), msg, "union '{}' is not a tagged union", .{union_ty.fmt(pt)});
16676 try sema.errNote(union_ty.srcLoc(zcu), msg, "union '{f}' is not a tagged union", .{union_ty.fmt(pt)});
1668016677 break :msg msg;
1668116678 };
1668216679 return sema.failWithOwnedErrorMsg(block, msg);
......@@ -16762,7 +16759,7 @@ fn analyzeCmp(
1676216759 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1676316760 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
1676416761 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {
16765 return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{
16762 return sema.fail(block, src, "operator {s} not allowed for type '{f}'", .{
1676616763 compareOperatorName(op), resolved_type.fmt(pt),
1676716764 });
1676816765 }
......@@ -16871,7 +16868,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1687116868 .undefined,
1687216869 .null,
1687316870 .@"opaque",
16874 => return sema.fail(block, operand_src, "no size available for type '{}'", .{ty.fmt(pt)}),
16871 => return sema.fail(block, operand_src, "no size available for type '{f}'", .{ty.fmt(pt)}),
1687516872
1687616873 .type,
1687716874 .enum_literal,
......@@ -16912,7 +16909,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1691216909 .undefined,
1691316910 .null,
1691416911 .@"opaque",
16915 => return sema.fail(block, operand_src, "no size available for type '{}'", .{operand_ty.fmt(pt)}),
16912 => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}),
1691616913
1691716914 .type,
1691816915 .enum_literal,
......@@ -18212,7 +18209,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
1821218209 return sema.fail(
1821318210 block,
1821418211 src,
18215 "bit shifting operation expected integer type, found '{}'",
18212 "bit shifting operation expected integer type, found '{f}'",
1821618213 .{operand.fmt(pt)},
1821718214 );
1821818215}
......@@ -18451,7 +18448,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi
1845118448 const pt = sema.pt;
1845218449 const zcu = pt.zcu;
1845318450 if (!ty.isSelfComparable(zcu, true)) {
18454 return sema.fail(block, src, "non-scalar sentinel type '{}'", .{ty.fmt(pt)});
18451 return sema.fail(block, src, "non-scalar sentinel type '{f}'", .{ty.fmt(pt)});
1845518452 }
1845618453}
1845718454
......@@ -18501,7 +18498,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
1850118498 const zcu = pt.zcu;
1850218499 switch (ty.zigTypeTag(zcu)) {
1850318500 .error_set, .error_union, .undefined => return,
18504 else => return sema.fail(block, src, "expected error union type, found '{}'", .{
18501 else => return sema.fail(block, src, "expected error union type, found '{f}'", .{
1850518502 ty.fmt(pt),
1850618503 }),
1850718504 }
......@@ -18645,7 +18642,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1864518642 const pt = sema.pt;
1864618643 const zcu = pt.zcu;
1864718644 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
18648 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{
18645 return sema.fail(parent_block, operand_src, "expected error union type, found '{f}'", .{
1864918646 err_union_ty.fmt(pt),
1865018647 });
1865118648 }
......@@ -18705,7 +18702,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1870518702 const pt = sema.pt;
1870618703 const zcu = pt.zcu;
1870718704 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
18708 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{
18705 return sema.fail(parent_block, operand_src, "expected error union type, found '{f}'", .{
1870918706 err_union_ty.fmt(pt),
1871018707 });
1871118708 }
......@@ -18903,7 +18900,7 @@ fn zirRetImplicit(
1890318900 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
1890418901 if (base_tag == .noreturn) {
1890518902 const msg = msg: {
18906 const msg = try sema.errMsg(ret_ty_src, "function declared '{}' implicitly returns", .{
18903 const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{
1890718904 sema.fn_ret_ty.fmt(pt),
1890818905 });
1890918906 errdefer msg.destroy(sema.gpa);
......@@ -18913,7 +18910,7 @@ fn zirRetImplicit(
1891318910 return sema.failWithOwnedErrorMsg(block, msg);
1891418911 } else if (base_tag != .void) {
1891518912 const msg = msg: {
18916 const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{}' implicitly returns", .{
18913 const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{f}' implicitly returns", .{
1891718914 sema.fn_ret_ty.fmt(pt),
1891818915 });
1891918916 errdefer msg.destroy(sema.gpa);
......@@ -19302,13 +19299,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1930219299
1930319300 if (host_size != 0) {
1930419301 if (bit_offset >= host_size * 8) {
19305 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} starts {} bits after the end of a {} byte host integer", .{
19302 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {} starts {} bits after the end of a {} byte host integer", .{
1930619303 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,
1930719304 });
1930819305 }
1930919306 const elem_bit_size = try elem_ty.bitSizeSema(pt);
1931019307 if (elem_bit_size > host_size * 8 - bit_offset) {
19311 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{
19308 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{
1931219309 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
1931319310 });
1931419311 }
......@@ -19323,7 +19320,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1932319320 } else if (inst_data.size == .c) {
1932419321 if (!try sema.validateExternType(elem_ty, .other)) {
1932519322 const msg = msg: {
19326 const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(pt)});
19323 const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
1932719324 errdefer msg.destroy(sema.gpa);
1932819325
1932919326 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);
......@@ -19340,7 +19337,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1934019337
1934119338 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {
1934219339 return sema.failWithOwnedErrorMsg(block, msg: {
19343 const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{}'", .{elem_ty.fmt(pt)});
19340 const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)});
1934419341 errdefer msg.destroy(sema.gpa);
1934519342 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);
1934619343 break :msg msg;
......@@ -19509,7 +19506,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1950919506 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
1951019507 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);
1951119508 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {
19512 return sema.fail(block, ty_src, "expected union type, found '{}'", .{union_ty.fmt(pt)});
19509 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});
1951319510 }
1951419511 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });
1951519512 const init = try sema.resolveInst(extra.init);
......@@ -19672,7 +19669,7 @@ fn zirStructInit(
1967219669 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
1967319670 errdefer msg.destroy(sema.gpa);
1967419671
19675 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{}' declared here", .{
19672 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{f}' declared here", .{
1967619673 field_name.fmt(ip),
1967719674 });
1967819675 try sema.addDeclaredHereNote(msg, resolved_ty);
......@@ -19791,7 +19788,7 @@ fn finishStructInit(
1979119788 const field_init = struct_type.fieldInit(ip, i);
1979219789 if (field_init == .none) {
1979319790 const field_name = struct_type.field_names.get(ip)[i];
19794 const template = "missing struct field: {}";
19791 const template = "missing struct field: {f}";
1979519792 const args = .{field_name.fmt(ip)};
1979619793 if (root_msg) |msg| {
1979719794 try sema.errNote(init_src, msg, template, args);
......@@ -20406,7 +20403,7 @@ fn fieldType(
2040620403 },
2040720404 else => {},
2040820405 }
20409 return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{
20406 return sema.fail(block, ty_src, "expected struct or union; found '{f}'", .{
2041020407 cur_ty.fmt(pt),
2041120408 });
2041220409 }
......@@ -20453,7 +20450,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2045320450 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
2045420451 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
2045520452 if (ty.isNoReturn(zcu)) {
20456 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.pt)});
20453 return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)});
2045720454 }
2045820455 const val = try ty.lazyAbiAlignment(sema.pt);
2045920456 return Air.internedToRef(val.toIntern());
......@@ -20531,7 +20528,7 @@ fn zirAbs(
2053120528 else => return sema.fail(
2053220529 block,
2053320530 operand_src,
20534 "expected integer, float, or vector of either integers or floats, found '{}'",
20531 "expected integer, float, or vector of either integers or floats, found '{f}'",
2053520532 .{operand_ty.fmt(pt)},
2053620533 ),
2053720534 };
......@@ -20600,7 +20597,7 @@ fn zirUnaryMath(
2060020597 else => return sema.fail(
2060120598 block,
2060220599 operand_src,
20603 "expected vector of floats or float type, found '{}'",
20600 "expected vector of floats or float type, found '{f}'",
2060420601 .{operand_ty.fmt(pt)},
2060520602 ),
2060620603 }
......@@ -20629,8 +20626,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2062920626 },
2063020627 .@"enum" => operand_ty,
2063120628 .@"union" => operand_ty.unionTagType(zcu) orelse
20632 return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(pt)}),
20633 else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{
20629 return sema.fail(block, src, "union '{f}' is untagged", .{operand_ty.fmt(pt)}),
20630 else => return sema.fail(block, operand_src, "expected enum or union; found '{f}'", .{
2063420631 operand_ty.fmt(pt),
2063520632 }),
2063620633 };
......@@ -20638,7 +20635,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2063820635 // TODO I don't think this is the correct way to handle this but
2063920636 // it prevents a crash.
2064020637 // https://github.com/ziglang/zig/issues/15909
20641 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{
20638 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{f}'", .{
2064220639 enum_ty.fmt(pt),
2064320640 });
2064420641 }
......@@ -20646,7 +20643,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2064620643 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
2064720644 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {
2064820645 const msg = msg: {
20649 const msg = try sema.errMsg(src, "no field with value '{}' in enum '{}'", .{
20646 const msg = try sema.errMsg(src, "no field with value '{f}' in enum '{f}'", .{
2065020647 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),
2065120648 });
2065220649 errdefer msg.destroy(sema.gpa);
......@@ -20833,7 +20830,7 @@ fn zirReify(
2083320830 } else if (ptr_size == .c) {
2083420831 if (!try sema.validateExternType(elem_ty, .other)) {
2083520832 const msg = msg: {
20836 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(pt)});
20833 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
2083720834 errdefer msg.destroy(gpa);
2083820835
2083920836 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);
......@@ -20946,7 +20943,7 @@ fn zirReify(
2094620943 _ = try pt.getErrorValue(name);
2094720944 const gop = names.getOrPutAssumeCapacity(name);
2094820945 if (gop.found_existing) {
20949 return sema.fail(block, src, "duplicate error '{}'", .{
20946 return sema.fail(block, src, "duplicate error '{f}'", .{
2095020947 name.fmt(ip),
2095120948 });
2095220949 }
......@@ -21294,7 +21291,7 @@ fn reifyEnum(
2129421291
2129521292 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {
2129621293 // TODO: better source location
21297 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{
21294 return sema.fail(block, src, "field '{f}' with enumeration value '{f}' is too large for backing int type '{f}'", .{
2129821295 field_name.fmt(ip),
2129921296 field_value_val.fmtValueSema(pt, sema),
2130021297 tag_ty.fmt(pt),
......@@ -21305,14 +21302,14 @@ fn reifyEnum(
2130521302 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {
2130621303 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
2130721304 .name => msg: {
21308 const msg = try sema.errMsg(src, "duplicate enum field '{}'", .{field_name.fmt(ip)});
21305 const msg = try sema.errMsg(src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
2130921306 errdefer msg.destroy(gpa);
2131021307 _ = conflict.prev_field_idx; // TODO: this note is incorrect
2131121308 try sema.errNote(src, msg, "other field here", .{});
2131221309 break :msg msg;
2131321310 },
2131421311 .value => msg: {
21315 const msg = try sema.errMsg(src, "enum tag value {} already taken", .{field_value_val.fmtValueSema(pt, sema)});
21312 const msg = try sema.errMsg(src, "enum tag value {f} already taken", .{field_value_val.fmtValueSema(pt, sema)});
2131621313 errdefer msg.destroy(gpa);
2131721314 _ = conflict.prev_field_idx; // TODO: this note is incorrect
2131821315 try sema.errNote(src, msg, "other enum tag value here", .{});
......@@ -21460,13 +21457,13 @@ fn reifyUnion(
2146021457
2146121458 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {
2146221459 // TODO: better source location
21463 return sema.fail(block, src, "no field named '{}' in enum '{}'", .{
21460 return sema.fail(block, src, "no field named '{f}' in enum '{f}'", .{
2146421461 field_name.fmt(ip), enum_tag_ty.fmt(pt),
2146521462 });
2146621463 };
2146721464 if (seen_tags.isSet(enum_index)) {
2146821465 // TODO: better source location
21469 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});
21466 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
2147021467 }
2147121468 seen_tags.set(enum_index);
2147221469
......@@ -21487,7 +21484,7 @@ fn reifyUnion(
2148721484 var it = seen_tags.iterator(.{ .kind = .unset });
2148821485 while (it.next()) |enum_index| {
2148921486 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);
21490 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{}' missing, declared here", .{
21487 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{f}' missing, declared here", .{
2149121488 field_name.fmt(ip),
2149221489 });
2149321490 }
......@@ -21512,7 +21509,7 @@ fn reifyUnion(
2151221509 const gop = field_names.getOrPutAssumeCapacity(field_name);
2151321510 if (gop.found_existing) {
2151421511 // TODO: better source location
21515 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});
21512 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
2151621513 }
2151721514
2151821515 field_ty.* = field_type_val.toIntern();
......@@ -21544,7 +21541,7 @@ fn reifyUnion(
2154421541 }
2154521542 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
2154621543 return sema.failWithOwnedErrorMsg(block, msg: {
21547 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
21544 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2154821545 errdefer msg.destroy(gpa);
2154921546
2155021547 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);
......@@ -21554,7 +21551,7 @@ fn reifyUnion(
2155421551 });
2155521552 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
2155621553 return sema.failWithOwnedErrorMsg(block, msg: {
21557 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
21554 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2155821555 errdefer msg.destroy(gpa);
2155921556
2156021557 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
......@@ -21636,7 +21633,7 @@ fn reifyTuple(
2163621633 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
2163721634 block,
2163821635 src,
21639 "tuple cannot have non-numeric field '{}'",
21636 "tuple cannot have non-numeric field '{f}'",
2164021637 .{field_name.fmt(ip)},
2164121638 );
2164221639 if (field_name_index != field_idx) {
......@@ -21814,7 +21811,7 @@ fn reifyStruct(
2181421811 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
2181521812 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
2181621813 _ = prev_index; // TODO: better source location
21817 return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)});
21814 return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
2181821815 }
2181921816
2182021817 if (any_aligned_fields) {
......@@ -21883,7 +21880,7 @@ fn reifyStruct(
2188321880 }
2188421881 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
2188521882 return sema.failWithOwnedErrorMsg(block, msg: {
21886 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
21883 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2188721884 errdefer msg.destroy(gpa);
2188821885
2188921886 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);
......@@ -21893,7 +21890,7 @@ fn reifyStruct(
2189321890 });
2189421891 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
2189521892 return sema.failWithOwnedErrorMsg(block, msg: {
21896 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
21893 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2189721894 errdefer msg.destroy(gpa);
2189821895
2189921896 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
......@@ -21970,7 +21967,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2197021967
2197121968 if (!try sema.validateExternType(arg_ty, .param_ty)) {
2197221969 const msg = msg: {
21973 const msg = try sema.errMsg(ty_src, "cannot get '{}' from variadic argument", .{arg_ty.fmt(sema.pt)});
21970 const msg = try sema.errMsg(ty_src, "cannot get '{f}' from variadic argument", .{arg_ty.fmt(sema.pt)});
2197421971 errdefer msg.destroy(sema.gpa);
2197521972
2197621973 try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty);
......@@ -22029,7 +22026,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2202922026 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
2203022027 const ty = try sema.resolveType(block, ty_src, inst_data.operand);
2203122028
22032 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{}", .{ty.fmt(pt)}, .no_embedded_nulls);
22029 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls);
2203322030 return sema.addNullTerminatedStrLit(type_name);
2203422031}
2203522032
......@@ -22157,7 +22154,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2215722154
2215822155 if (ptr_ty.isSlice(zcu)) {
2215922156 const msg = msg: {
22160 const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(pt)});
22157 const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{f}'", .{ptr_ty.fmt(pt)});
2216122158 errdefer msg.destroy(sema.gpa);
2216222159 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});
2216322160 break :msg msg;
......@@ -22184,7 +22181,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2218422181 }
2218522182 if (try ptr_ty.comptimeOnlySema(pt)) {
2218622183 return sema.failWithOwnedErrorMsg(block, msg: {
22187 const msg = try sema.errMsg(src, "pointer to comptime-only type '{}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)});
22184 const msg = try sema.errMsg(src, "pointer to comptime-only type '{f}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)});
2218822185 errdefer msg.destroy(sema.gpa);
2218922186
2219022187 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);
......@@ -22241,7 +22238,7 @@ fn ptrFromIntVal(
2224122238 }
2224222239 const addr = try operand_val.toUnsignedIntSema(pt);
2224322240 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)
22244 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(pt)});
22241 return sema.fail(block, operand_src, "pointer type '{f}' does not allow address zero", .{ptr_ty.fmt(pt)});
2224522242 if (addr != 0 and ptr_align != .none) {
2224622243 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|
2224722244 addr & mask
......@@ -22249,7 +22246,7 @@ fn ptrFromIntVal(
2224922246 addr;
2225022247
2225122248 if (!ptr_align.check(masked_addr)) {
22252 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(pt)});
22249 return sema.fail(block, operand_src, "pointer type '{f}' requires aligned address", .{ptr_ty.fmt(pt)});
2225322250 }
2225422251 }
2225522252
......@@ -22294,8 +22291,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2229422291 errdefer msg.destroy(sema.gpa);
2229522292 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);
2229622293 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);
22297 try sema.errNote(src, msg, "destination payload is '{}'", .{dest_payload_ty.fmt(pt)});
22298 try sema.errNote(src, msg, "operand payload is '{}'", .{operand_payload_ty.fmt(pt)});
22294 try sema.errNote(src, msg, "destination payload is '{f}'", .{dest_payload_ty.fmt(pt)});
22295 try sema.errNote(src, msg, "operand payload is '{f}'", .{operand_payload_ty.fmt(pt)});
2229922296 try addDeclaredHereNote(sema, msg, dest_ty);
2230022297 try addDeclaredHereNote(sema, msg, operand_ty);
2230122298 break :msg msg;
......@@ -22340,7 +22337,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2234022337 break :disjoint true;
2234122338 };
2234222339 if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) {
22343 return sema.fail(block, src, "error sets '{}' and '{}' have no common errors", .{
22340 return sema.fail(block, src, "error sets '{f}' and '{f}' have no common errors", .{
2234422341 operand_err_ty.fmt(pt), dest_err_ty.fmt(pt),
2234522342 });
2234622343 }
......@@ -22360,7 +22357,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2236022357 };
2236122358
2236222359 if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) {
22363 return sema.fail(block, src, "'error.{}' not a member of error set '{}'", .{
22360 return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{
2236422361 err_name.fmt(ip), dest_err_ty.fmt(pt),
2236522362 });
2236622363 }
......@@ -22520,13 +22517,15 @@ fn ptrCastFull(
2252022517 const src_elem_size = src_elem_ty.abiSize(zcu);
2252122518 const dest_elem_size = dest_elem_ty.abiSize(zcu);
2252222519 if (dest_elem_size == 0) {
22523 return sema.fail(block, src, "cannot infer length of slice of zero-bit '{}' from '{}'", .{ dest_elem_ty.fmt(pt), operand_ty.fmt(pt) });
22520 return sema.fail(block, src, "cannot infer length of slice of zero-bit '{f}' from '{f}'", .{
22521 dest_elem_ty.fmt(pt), operand_ty.fmt(pt),
22522 });
2252422523 }
2252522524 if (opt_src_len) |src_len| {
2252622525 const bytes = src_len * src_elem_size;
2252722526 const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) {
2252822527 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),
22529 .one => return sema.fail(block, src, "type '{}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
22528 .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
2253022529 else => unreachable,
2253122530 };
2253222531 break :len .{ .constant = dest_len };
......@@ -22544,7 +22543,9 @@ fn ptrCastFull(
2254422543 // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`.
2254522544 // The result value will have `dest_len * dest_base_per_elem` values of type `dest_base_ty`.
2254622545 if (dest_base_ty.toIntern() != src_base_ty.toIntern()) {
22547 return sema.fail(block, src, "cannot infer length of comptime-only '{}' from incompatible '{}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });
22546 return sema.fail(block, src, "cannot infer length of comptime-only '{f}' from incompatible '{f}'", .{
22547 dest_ty.fmt(pt), operand_ty.fmt(pt),
22548 });
2254822549 }
2254922550 // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is
2255022551 // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`.
......@@ -22552,7 +22553,7 @@ fn ptrCastFull(
2255222553 const base_len = src_len * src_base_per_elem;
2255322554 const dest_len = std.math.divExact(u64, base_len, dest_base_per_elem) catch switch (src_info.flags.size) {
2255422555 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),
22555 .one => return sema.fail(block, src, "type '{}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
22556 .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
2255622557 else => unreachable,
2255722558 };
2255822559 break :len .{ .constant = dest_len };
......@@ -22613,7 +22614,7 @@ fn ptrCastFull(
2261322614 );
2261422615 if (imc_res == .ok) break :check_child;
2261522616 return sema.failWithOwnedErrorMsg(block, msg: {
22616 const msg = try sema.errMsg(src, "pointer element type '{}' cannot coerce into element type '{}'", .{
22617 const msg = try sema.errMsg(src, "pointer element type '{f}' cannot coerce into element type '{f}'", .{
2261722618 src_child.fmt(pt), dest_child.fmt(pt),
2261822619 });
2261922620 errdefer msg.destroy(sema.gpa);
......@@ -22640,11 +22641,11 @@ fn ptrCastFull(
2264022641 }
2264122642 return sema.failWithOwnedErrorMsg(block, msg: {
2264222643 const msg = if (src_info.sentinel == .none) blk: {
22643 break :blk try sema.errMsg(src, "destination pointer requires '{}' sentinel", .{
22644 break :blk try sema.errMsg(src, "destination pointer requires '{f}' sentinel", .{
2264422645 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
2264522646 });
2264622647 } else blk: {
22647 break :blk try sema.errMsg(src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{
22648 break :blk try sema.errMsg(src, "pointer sentinel '{f}' cannot coerce into pointer sentinel '{f}'", .{
2264822649 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),
2264922650 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
2265022651 });
......@@ -22686,7 +22687,7 @@ fn ptrCastFull(
2268622687 if (dest_allows_zero) break :check_allowzero;
2268722688
2268822689 return sema.failWithOwnedErrorMsg(block, msg: {
22689 const msg = try sema.errMsg(src, "'{}' could have null values which are illegal in type '{}'", .{
22690 const msg = try sema.errMsg(src, "'{f}' could have null values which are illegal in type '{f}'", .{
2269022691 operand_ty.fmt(pt),
2269122692 dest_ty.fmt(pt),
2269222693 });
......@@ -22714,10 +22715,10 @@ fn ptrCastFull(
2271422715 return sema.failWithOwnedErrorMsg(block, msg: {
2271522716 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});
2271622717 errdefer msg.destroy(sema.gpa);
22717 try sema.errNote(operand_src, msg, "'{}' has alignment '{d}'", .{
22718 try sema.errNote(operand_src, msg, "'{f}' has alignment '{d}'", .{
2271822719 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,
2271922720 });
22720 try sema.errNote(src, msg, "'{}' has alignment '{d}'", .{
22721 try sema.errNote(src, msg, "'{f}' has alignment '{d}'", .{
2272122722 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,
2272222723 });
2272322724 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});
......@@ -22731,10 +22732,10 @@ fn ptrCastFull(
2273122732 return sema.failWithOwnedErrorMsg(block, msg: {
2273222733 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});
2273322734 errdefer msg.destroy(sema.gpa);
22734 try sema.errNote(operand_src, msg, "'{}' has address space '{s}'", .{
22735 try sema.errNote(operand_src, msg, "'{f}' has address space '{s}'", .{
2273522736 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),
2273622737 });
22737 try sema.errNote(src, msg, "'{}' has address space '{s}'", .{
22738 try sema.errNote(src, msg, "'{f}' has address space '{s}'", .{
2273822739 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),
2273922740 });
2274022741 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});
......@@ -22801,7 +22802,7 @@ fn ptrCastFull(
2280122802
2280222803 if (operand_val.isNull(zcu)) {
2280322804 if (!dest_ty.ptrAllowsZero(zcu)) {
22804 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(pt)});
22805 return sema.fail(block, operand_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)});
2280522806 }
2280622807 if (dest_ty.zigTypeTag(zcu) == .optional) {
2280722808 return Air.internedToRef((try pt.nullValue(dest_ty)).toIntern());
......@@ -23092,7 +23093,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2309223093 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;
2309323094 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;
2309423095 if (operand_is_vector != dest_is_vector) {
23095 return sema.fail(block, operand_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });
23096 return sema.fail(block, operand_src, "expected type '{f}', found '{f}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });
2309623097 }
2309723098
2309823099 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {
......@@ -23112,7 +23113,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2311223113 }
2311323114
2311423115 if (operand_info.signedness != dest_info.signedness) {
23115 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{
23116 return sema.fail(block, operand_src, "expected {s} integer type, found '{f}'", .{
2311623117 @tagName(dest_info.signedness), operand_ty.fmt(pt),
2311723118 });
2311823119 }
......@@ -23121,7 +23122,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2312123122 const msg = msg: {
2312223123 const msg = try sema.errMsg(
2312323124 src,
23124 "destination type '{}' has more bits than source type '{}'",
23125 "destination type '{f}' has more bits than source type '{f}'",
2312523126 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },
2312623127 );
2312723128 errdefer msg.destroy(sema.gpa);
......@@ -23239,7 +23240,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2323923240 return sema.fail(
2324023241 block,
2324123242 operand_src,
23242 "@byteSwap requires the number of bits to be evenly divisible by 8, but {} has {} bits",
23243 "@byteSwap requires the number of bits to be evenly divisible by 8, but {f} has {} bits",
2324323244 .{ scalar_ty.fmt(pt), bits },
2324423245 );
2324523246 }
......@@ -23359,7 +23360,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2335923360 try ty.resolveLayout(pt);
2336023361 switch (ty.zigTypeTag(zcu)) {
2336123362 .@"struct" => {},
23362 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
23363 else => return sema.fail(block, ty_src, "expected struct type, found '{f}'", .{ty.fmt(pt)}),
2336323364 }
2336423365
2336523366 const field_index = if (ty.isTuple(zcu)) blk: {
......@@ -23394,7 +23395,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com
2339423395 const zcu = pt.zcu;
2339523396 switch (ty.zigTypeTag(zcu)) {
2339623397 .@"struct", .@"enum", .@"union", .@"opaque" => return,
23397 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(pt)}),
23398 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{f}'", .{ty.fmt(pt)}),
2339823399 }
2339923400}
2340023401
......@@ -23405,7 +23406,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr
2340523406 switch (ty.zigTypeTag(zcu)) {
2340623407 .comptime_int => return true,
2340723408 .int => return false,
23408 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(pt)}),
23409 else => return sema.fail(block, src, "expected integer type, found '{f}'", .{ty.fmt(pt)}),
2340923410 }
2341023411}
2341123412
......@@ -23459,7 +23460,7 @@ fn checkPtrOperand(
2345923460 const msg = msg: {
2346023461 const msg = try sema.errMsg(
2346123462 ty_src,
23462 "expected pointer, found '{}'",
23463 "expected pointer, found '{f}'",
2346323464 .{ty.fmt(pt)},
2346423465 );
2346523466 errdefer msg.destroy(sema.gpa);
......@@ -23473,7 +23474,7 @@ fn checkPtrOperand(
2347323474 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
2347423475 else => {},
2347523476 }
23476 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});
23477 return sema.fail(block, ty_src, "expected pointer type, found '{f}'", .{ty.fmt(pt)});
2347723478}
2347823479
2347923480fn checkPtrType(
......@@ -23491,7 +23492,7 @@ fn checkPtrType(
2349123492 const msg = msg: {
2349223493 const msg = try sema.errMsg(
2349323494 ty_src,
23494 "expected pointer type, found '{}'",
23495 "expected pointer type, found '{f}'",
2349523496 .{ty.fmt(pt)},
2349623497 );
2349723498 errdefer msg.destroy(sema.gpa);
......@@ -23505,7 +23506,7 @@ fn checkPtrType(
2350523506 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
2350623507 else => {},
2350723508 }
23508 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});
23509 return sema.fail(block, ty_src, "expected pointer type, found '{f}'", .{ty.fmt(pt)});
2350923510}
2351023511
2351123512fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
......@@ -23516,7 +23517,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
2351623517 const as = ty.ptrAddressSpace(zcu);
2351723518 if (target_util.arePointersLogical(target, as)) {
2351823519 return sema.failWithOwnedErrorMsg(block, msg: {
23519 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{}'", .{ty.fmt(pt)});
23520 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{f}'", .{ty.fmt(pt)});
2352023521 errdefer msg.destroy(sema.gpa);
2352123522 try sema.errNote(
2352223523 src,
......@@ -23547,7 +23548,7 @@ fn checkVectorElemType(
2354723548 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,
2354823549 else => {},
2354923550 }
23550 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(pt)});
23551 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{f}'", .{ty.fmt(pt)});
2355123552}
2355223553
2355323554fn checkFloatType(
......@@ -23560,7 +23561,7 @@ fn checkFloatType(
2356023561 const zcu = pt.zcu;
2356123562 switch (ty.zigTypeTag(zcu)) {
2356223563 .comptime_int, .comptime_float, .float => {},
23563 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(pt)}),
23564 else => return sema.fail(block, ty_src, "expected float type, found '{f}'", .{ty.fmt(pt)}),
2356423565 }
2356523566}
2356623567
......@@ -23578,7 +23579,7 @@ fn checkNumericType(
2357823579 .comptime_float, .float, .comptime_int, .int => {},
2357923580 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),
2358023581 },
23581 else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(pt)}),
23582 else => return sema.fail(block, ty_src, "expected number, found '{f}'", .{ty.fmt(pt)}),
2358223583 }
2358323584}
2358423585
......@@ -23612,7 +23613,7 @@ fn checkAtomicPtrOperand(
2361223613 error.BadType => return sema.fail(
2361323614 block,
2361423615 elem_ty_src,
23615 "expected bool, integer, float, enum, packed struct, or pointer type; found '{}'",
23616 "expected bool, integer, float, enum, packed struct, or pointer type; found '{f}'",
2361623617 .{elem_ty.fmt(pt)},
2361723618 ),
2361823619 };
......@@ -23673,12 +23674,12 @@ fn checkIntOrVector(
2367323674 const elem_ty = operand_ty.childType(zcu);
2367423675 switch (elem_ty.zigTypeTag(zcu)) {
2367523676 .int => return elem_ty,
23676 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
23677 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{f}'", .{
2367723678 elem_ty.fmt(pt),
2367823679 }),
2367923680 }
2368023681 },
23681 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{
23682 else => return sema.fail(block, operand_src, "expected integer or vector, found '{f}'", .{
2368223683 operand_ty.fmt(pt),
2368323684 }),
2368423685 }
......@@ -23698,12 +23699,12 @@ fn checkIntOrVectorAllowComptime(
2369823699 const elem_ty = operand_ty.childType(zcu);
2369923700 switch (elem_ty.zigTypeTag(zcu)) {
2370023701 .int, .comptime_int => return elem_ty,
23701 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
23702 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{f}'", .{
2370223703 elem_ty.fmt(pt),
2370323704 }),
2370423705 }
2370523706 },
23706 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{
23707 else => return sema.fail(block, operand_src, "expected integer or vector, found '{f}'", .{
2370723708 operand_ty.fmt(pt),
2370823709 }),
2370923710 }
......@@ -23794,7 +23795,7 @@ fn checkVectorizableBinaryOperands(
2379423795 }
2379523796 } else {
2379623797 const msg = msg: {
23797 const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{}' and '{}'", .{
23798 const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{f}' and '{f}'", .{
2379823799 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
2379923800 });
2380023801 errdefer msg.destroy(sema.gpa);
......@@ -23928,7 +23929,7 @@ fn zirCmpxchg(
2392823929 return sema.fail(
2392923930 block,
2393023931 elem_ty_src,
23931 "expected bool, integer, enum, packed struct, or pointer type; found '{}'",
23932 "expected bool, integer, enum, packed struct, or pointer type; found '{f}'",
2393223933 .{elem_ty.fmt(pt)},
2393323934 );
2393423935 }
......@@ -24012,7 +24013,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2401224013
2401324014 switch (dest_ty.zigTypeTag(zcu)) {
2401424015 .array, .vector => {},
24015 else => return sema.fail(block, src, "expected array or vector type, found '{}'", .{dest_ty.fmt(pt)}),
24016 else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(pt)}),
2401624017 }
2401724018
2401824019 const operand = try sema.resolveInst(extra.rhs);
......@@ -24088,7 +24089,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2408824089 const zcu = pt.zcu;
2408924090
2409024091 if (operand_ty.zigTypeTag(zcu) != .vector) {
24091 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(pt)});
24092 return sema.fail(block, operand_src, "expected vector, found '{f}'", .{operand_ty.fmt(pt)});
2409224093 }
2409324094
2409424095 const scalar_ty = operand_ty.childType(zcu);
......@@ -24097,13 +24098,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2409724098 switch (operation) {
2409824099 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
2409924100 .int, .bool => {},
24100 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{
24101 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{f}'", .{
2410124102 @tagName(operation), operand_ty.fmt(pt),
2410224103 }),
2410324104 },
2410424105 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
2410524106 .int, .float => {},
24106 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{
24107 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{f}'", .{
2410724108 @tagName(operation), operand_ty.fmt(pt),
2410824109 }),
2410924110 },
......@@ -24157,7 +24158,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2415724158
2415824159 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {
2415924160 .array, .vector => sema.typeOf(mask).arrayLen(zcu),
24160 else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(pt)}),
24161 else => return sema.fail(block, mask_src, "expected vector or array, found '{f}'", .{sema.typeOf(mask).fmt(pt)}),
2416124162 };
2416224163 mask_ty = try pt.vectorType(.{
2416324164 .len = @intCast(mask_len),
......@@ -24184,11 +24185,14 @@ fn analyzeShuffle(
2418424185 const b_src = block.builtinCallArgSrc(src_node, 2);
2418524186 const mask_src = block.builtinCallArgSrc(src_node, 3);
2418624187
24187 // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped, this is 0, because it is an error to index into this vector.
24188 // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped,
24189 // this is 0, because it is an error to index into this vector.
2418824190 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {
2418924191 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),
2419024192 .undefined => 0,
24191 else => return sema.fail(block, a_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt) }),
24193 else => return sema.fail(block, a_src, "expected vector of '{f}', found '{f}'", .{
24194 elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt),
24195 }),
2419224196 };
2419324197 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });
2419424198 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);
......@@ -24197,7 +24201,9 @@ fn analyzeShuffle(
2419724201 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {
2419824202 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),
2419924203 .undefined => 0,
24200 else => return sema.fail(block, b_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt) }),
24204 else => return sema.fail(block, b_src, "expected vector of '{f}', found '{f}'", .{
24205 elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt),
24206 }),
2420124207 };
2420224208 const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() });
2420324209 const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src);
......@@ -24235,7 +24241,7 @@ fn analyzeShuffle(
2423524241 if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: {
2423624242 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});
2423724243 errdefer msg.destroy(sema.gpa);
24238 try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{}' given here", .{ idx, a_ty.fmt(pt) });
24244 try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{f}' given here", .{ idx, a_ty.fmt(pt) });
2423924245 if (idx < b_len) {
2424024246 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});
2424124247 }
......@@ -24351,7 +24357,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2435124357
2435224358 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {
2435324359 .vector, .array => pred_ty.arrayLen(zcu),
24354 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(pt)}),
24360 else => return sema.fail(block, pred_src, "expected vector or array, found '{f}'", .{pred_ty.fmt(pt)}),
2435524361 };
2435624362 const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64));
2435724363
......@@ -24611,7 +24617,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2461124617
2461224618 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
2461324619 .comptime_float, .float => {},
24614 else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(pt)}),
24620 else => return sema.fail(block, src, "expected vector of floats or float type, found '{f}'", .{ty.fmt(pt)}),
2461524621 }
2461624622
2461724623 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
......@@ -24712,7 +24718,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2471224718
2471324719 const args_ty = sema.typeOf(args);
2471424720 if (!args_ty.isTuple(zcu)) {
24715 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(pt)});
24721 return sema.fail(block, args_src, "expected a tuple, found '{f}'", .{args_ty.fmt(pt)});
2471624722 }
2471724723
2471824724 const resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(zcu));
......@@ -24757,12 +24763,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2475724763 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);
2475824764 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
2475924765 if (parent_ptr_info.flags.size != .one) {
24760 return sema.fail(block, inst_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(pt)});
24766 return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)});
2476124767 }
2476224768 const parent_ty: Type = .fromInterned(parent_ptr_info.child);
2476324769 switch (parent_ty.zigTypeTag(zcu)) {
2476424770 .@"struct", .@"union" => {},
24765 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(pt)}),
24771 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}),
2476624772 }
2476724773 try parent_ty.resolveLayout(pt);
2476824774
......@@ -24912,7 +24918,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2491224918 }
2491324919
2491424920 if (field.index != field_index) {
24915 return sema.fail(block, inst_src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{
24921 return sema.fail(block, inst_src, "field '{f}' has index '{d}' but pointer value is index '{d}' of struct '{f}'", .{
2491624922 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt),
2491724923 });
2491824924 }
......@@ -25371,10 +25377,10 @@ fn zirMemcpy(
2537125377 const msg = msg: {
2537225378 const msg = try sema.errMsg(src, "unknown copy length", .{});
2537325379 errdefer msg.destroy(sema.gpa);
25374 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{
25380 try sema.errNote(dest_src, msg, "destination type '{f}' provides no length", .{
2537525381 dest_ty.fmt(pt),
2537625382 });
25377 try sema.errNote(src_src, msg, "source type '{}' provides no length", .{
25383 try sema.errNote(src_src, msg, "source type '{f}' provides no length", .{
2537825384 src_ty.fmt(pt),
2537925385 });
2538025386 break :msg msg;
......@@ -25398,7 +25404,7 @@ fn zirMemcpy(
2539825404 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {
2539925405 const msg = try sema.errMsg(
2540025406 src,
25401 "pointer element type '{}' cannot coerce into element type '{}'",
25407 "pointer element type '{f}' cannot coerce into element type '{f}'",
2540225408 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },
2540325409 );
2540425410 errdefer msg.destroy(sema.gpa);
......@@ -25417,10 +25423,10 @@ fn zirMemcpy(
2541725423 const msg = msg: {
2541825424 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});
2541925425 errdefer msg.destroy(sema.gpa);
25420 try sema.errNote(dest_src, msg, "length {} here", .{
25426 try sema.errNote(dest_src, msg, "length {f} here", .{
2542125427 dest_len_val.fmtValueSema(pt, sema),
2542225428 });
25423 try sema.errNote(src_src, msg, "length {} here", .{
25429 try sema.errNote(src_src, msg, "length {f} here", .{
2542425430 src_len_val.fmtValueSema(pt, sema),
2542525431 });
2542625432 break :msg msg;
......@@ -25635,7 +25641,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2563525641 return sema.failWithOwnedErrorMsg(block, msg: {
2563625642 const msg = try sema.errMsg(src, "unknown @memset length", .{});
2563725643 errdefer msg.destroy(sema.gpa);
25638 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{
25644 try sema.errNote(dest_src, msg, "destination type '{f}' provides no length", .{
2563925645 dest_ptr_ty.fmt(pt),
2564025646 });
2564125647 break :msg msg;
......@@ -25815,7 +25821,7 @@ fn zirCUndef(
2581525821 const src = block.builtinCallArgSrc(extra.node, 0);
2581625822
2581725823 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cUndef_macro_name });
25818 try block.c_import_buf.?.writer().print("#undef {s}\n", .{name});
25824 try block.c_import_buf.?.print("#undef {s}\n", .{name});
2581925825 return .void_value;
2582025826}
2582125827
......@@ -25828,7 +25834,7 @@ fn zirCInclude(
2582825834 const src = block.builtinCallArgSrc(extra.node, 0);
2582925835
2583025836 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cInclude_file_name });
25831 try block.c_import_buf.?.writer().print("#include <{s}>\n", .{name});
25837 try block.c_import_buf.?.print("#include <{s}>\n", .{name});
2583225838 return .void_value;
2583325839}
2583425840
......@@ -25847,9 +25853,9 @@ fn zirCDefine(
2584725853 const rhs = try sema.resolveInst(extra.rhs);
2584825854 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {
2584925855 const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value });
25850 try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });
25856 try block.c_import_buf.?.print("#define {s} {s}\n", .{ name, value });
2585125857 } else {
25852 try block.c_import_buf.?.writer().print("#define {s}\n", .{name});
25858 try block.c_import_buf.?.print("#define {s}\n", .{name});
2585325859 }
2585425860 return .void_value;
2585525861}
......@@ -26067,7 +26073,7 @@ fn zirBuiltinExtern(
2606726073 }
2606826074 if (!try sema.validateExternType(ty, .other)) {
2606926075 const msg = msg: {
26070 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(pt)});
26076 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)});
2607126077 errdefer msg.destroy(sema.gpa);
2607226078 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);
2607326079 break :msg msg;
......@@ -26307,7 +26313,7 @@ pub fn validateVarType(
2630726313 if (is_extern) {
2630826314 if (!try sema.validateExternType(var_ty, .other)) {
2630926315 const msg = msg: {
26310 const msg = try sema.errMsg(src, "extern variable cannot have type '{}'", .{var_ty.fmt(pt)});
26316 const msg = try sema.errMsg(src, "extern variable cannot have type '{f}'", .{var_ty.fmt(pt)});
2631126317 errdefer msg.destroy(sema.gpa);
2631226318 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);
2631326319 break :msg msg;
......@@ -26319,7 +26325,7 @@ pub fn validateVarType(
2631926325 return sema.fail(
2632026326 block,
2632126327 src,
26322 "non-extern variable with opaque type '{}'",
26328 "non-extern variable with opaque type '{f}'",
2632326329 .{var_ty.fmt(pt)},
2632426330 );
2632526331 }
......@@ -26328,7 +26334,7 @@ pub fn validateVarType(
2632826334 if (!try var_ty.comptimeOnlySema(pt)) return;
2632926335
2633026336 const msg = msg: {
26331 const msg = try sema.errMsg(src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(pt)});
26337 const msg = try sema.errMsg(src, "variable of type '{f}' must be const or comptime", .{var_ty.fmt(pt)});
2633226338 errdefer msg.destroy(sema.gpa);
2633326339
2633426340 try sema.explainWhyTypeIsComptime(msg, src, var_ty);
......@@ -26378,7 +26384,7 @@ fn explainWhyTypeIsComptimeInner(
2637826384 => return,
2637926385
2638026386 .@"fn" => {
26381 try sema.errNote(src_loc, msg, "use '*const {}' for a function pointer type", .{ty.fmt(pt)});
26387 try sema.errNote(src_loc, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)});
2638226388 },
2638326389
2638426390 .type => {
......@@ -26394,7 +26400,7 @@ fn explainWhyTypeIsComptimeInner(
2639426400 => return,
2639526401
2639626402 .@"opaque" => {
26397 try sema.errNote(src_loc, msg, "opaque type '{}' has undefined size", .{ty.fmt(pt)});
26403 try sema.errNote(src_loc, msg, "opaque type '{f}' has undefined size", .{ty.fmt(pt)});
2639826404 },
2639926405
2640026406 .array, .vector => {
......@@ -26581,7 +26587,7 @@ fn explainWhyTypeIsNotExtern(
2658126587 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {
2658226588 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});
2658326589 } else if (try ty.comptimeOnlySema(pt)) {
26584 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(pt)});
26590 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{f}'", .{pointee_ty.fmt(pt)});
2658526591 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);
2658626592 }
2658726593 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);
......@@ -26609,7 +26615,7 @@ fn explainWhyTypeIsNotExtern(
2660926615 },
2661026616 .@"enum" => {
2661126617 const tag_ty = ty.intTagType(zcu);
26612 try sema.errNote(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(pt)});
26618 try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});
2661326619 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
2661426620 },
2661526621 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
......@@ -27045,7 +27051,7 @@ fn fieldVal(
2704527051 return sema.fail(
2704627052 block,
2704727053 field_name_src,
27048 "no member named '{}' in '{}'",
27054 "no member named '{f}' in '{f}'",
2704927055 .{ field_name.fmt(ip), object_ty.fmt(pt) },
2705027056 );
2705127057 }
......@@ -27069,7 +27075,7 @@ fn fieldVal(
2706927075 return sema.fail(
2707027076 block,
2707127077 field_name_src,
27072 "no member named '{}' in '{}'",
27078 "no member named '{f}' in '{f}'",
2707327079 .{ field_name.fmt(ip), object_ty.fmt(pt) },
2707427080 );
2707527081 }
......@@ -27089,7 +27095,7 @@ fn fieldVal(
2708927095 switch (ip.indexToKey(child_type.toIntern())) {
2709027096 .error_set_type => |error_set_type| blk: {
2709127097 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;
27092 return sema.fail(block, src, "no error named '{}' in '{}'", .{
27098 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
2709327099 field_name.fmt(ip), child_type.fmt(pt),
2709427100 });
2709527101 },
......@@ -27144,7 +27150,7 @@ fn fieldVal(
2714427150 return sema.failWithBadMemberAccess(block, child_type, src, field_name);
2714527151 },
2714627152 else => return sema.failWithOwnedErrorMsg(block, msg: {
27147 const msg = try sema.errMsg(src, "type '{}' has no members", .{child_type.fmt(pt)});
27153 const msg = try sema.errMsg(src, "type '{f}' has no members", .{child_type.fmt(pt)});
2714827154 errdefer msg.destroy(sema.gpa);
2714927155 if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{});
2715027156 if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{});
......@@ -27190,7 +27196,7 @@ fn fieldPtr(
2719027196 const object_ptr_ty = sema.typeOf(object_ptr);
2719127197 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {
2719227198 .pointer => object_ptr_ty.childType(zcu),
27193 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(pt)}),
27199 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{f}'", .{object_ptr_ty.fmt(pt)}),
2719427200 };
2719527201
2719627202 // Zig allows dereferencing a single pointer during field lookup. Note that
......@@ -27243,7 +27249,7 @@ fn fieldPtr(
2724327249 return sema.fail(
2724427250 block,
2724527251 field_name_src,
27246 "no member named '{}' in '{}'",
27252 "no member named '{f}' in '{f}'",
2724727253 .{ field_name.fmt(ip), object_ty.fmt(pt) },
2724827254 );
2724927255 }
......@@ -27298,7 +27304,7 @@ fn fieldPtr(
2729827304 return sema.fail(
2729927305 block,
2730027306 field_name_src,
27301 "no member named '{}' in '{}'",
27307 "no member named '{f}' in '{f}'",
2730227308 .{ field_name.fmt(ip), object_ty.fmt(pt) },
2730327309 );
2730427310 }
......@@ -27321,7 +27327,7 @@ fn fieldPtr(
2732127327 if (error_set_type.nameIndex(ip, field_name) != null) {
2732227328 break :blk;
2732327329 }
27324 return sema.fail(block, src, "no error named '{}' in '{}'", .{
27330 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
2732527331 field_name.fmt(ip), child_type.fmt(pt),
2732627332 });
2732727333 },
......@@ -27375,7 +27381,7 @@ fn fieldPtr(
2737527381 }
2737627382 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
2737727383 },
27378 else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(pt)}),
27384 else => return sema.fail(block, src, "type '{f}' has no members", .{child_type.fmt(pt)}),
2737927385 }
2738027386 },
2738127387 .@"struct" => {
......@@ -27430,7 +27436,7 @@ fn fieldCallBind(
2743027436 const inner_ty = if (raw_ptr_ty.zigTypeTag(zcu) == .pointer and (raw_ptr_ty.ptrSize(zcu) == .one or raw_ptr_ty.ptrSize(zcu) == .c))
2743127437 raw_ptr_ty.childType(zcu)
2743227438 else
27433 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(pt)});
27439 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{f}'", .{raw_ptr_ty.fmt(pt)});
2743427440
2743527441 // Optionally dereference a second pointer to get the concrete type.
2743627442 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;
......@@ -27549,7 +27555,7 @@ fn fieldCallBind(
2754927555 };
2755027556
2755127557 const msg = msg: {
27552 const msg = try sema.errMsg(src, "no field or member function named '{}' in '{}'", .{
27558 const msg = try sema.errMsg(src, "no field or member function named '{f}' in '{f}'", .{
2755327559 field_name.fmt(ip),
2755427560 concrete_ty.fmt(pt),
2755527561 });
......@@ -27559,7 +27565,7 @@ fn fieldCallBind(
2755927565 try sema.errNote(
2756027566 zcu.navSrcLoc(nav_index),
2756127567 msg,
27562 "'{}' is not a member function",
27568 "'{f}' is not a member function",
2756327569 .{field_name.fmt(ip)},
2756427570 );
2756527571 }
......@@ -27627,7 +27633,7 @@ fn namespaceLookup(
2762727633 if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {
2762827634 if (!lookup.accessible) {
2762927635 return sema.failWithOwnedErrorMsg(block, msg: {
27630 const msg = try sema.errMsg(src, "'{}' is not marked 'pub'", .{
27636 const msg = try sema.errMsg(src, "'{f}' is not marked 'pub'", .{
2763127637 decl_name.fmt(&zcu.intern_pool),
2763227638 });
2763327639 errdefer msg.destroy(gpa);
......@@ -27865,12 +27871,12 @@ fn tupleFieldIndex(
2786527871 assert(!field_name.eqlSlice("len", ip));
2786627872 if (field_name.toUnsigned(ip)) |field_index| {
2786727873 if (field_index < tuple_ty.structFieldCount(pt.zcu)) return field_index;
27868 return sema.fail(block, field_name_src, "index '{}' out of bounds of tuple '{}'", .{
27874 return sema.fail(block, field_name_src, "index '{f}' out of bounds of tuple '{f}'", .{
2786927875 field_name.fmt(ip), tuple_ty.fmt(pt),
2787027876 });
2787127877 }
2787227878
27873 return sema.fail(block, field_name_src, "no field named '{}' in tuple '{}'", .{
27879 return sema.fail(block, field_name_src, "no field named '{f}' in tuple '{f}'", .{
2787427880 field_name.fmt(ip), tuple_ty.fmt(pt),
2787527881 });
2787627882}
......@@ -27957,7 +27963,7 @@ fn unionFieldPtr(
2795727963 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
2795827964 errdefer msg.destroy(sema.gpa);
2795927965
27960 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
27966 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
2796127967 field_name.fmt(ip),
2796227968 });
2796327969 try sema.addDeclaredHereNote(msg, union_ty);
......@@ -27991,7 +27997,7 @@ fn unionFieldPtr(
2799127997 const msg = msg: {
2799227998 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
2799327999 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);
27994 const msg = try sema.errMsg(src, "access of union field '{}' while field '{}' is active", .{
28000 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
2799528001 field_name.fmt(ip),
2799628002 active_field_name.fmt(ip),
2799728003 });
......@@ -28059,7 +28065,7 @@ fn unionFieldVal(
2805928065 const msg = msg: {
2806028066 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
2806128067 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);
28062 const msg = try sema.errMsg(src, "access of union field '{}' while field '{}' is active", .{
28068 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
2806328069 field_name.fmt(ip), active_field_name.fmt(ip),
2806428070 });
2806528071 errdefer msg.destroy(sema.gpa);
......@@ -28117,7 +28123,7 @@ fn elemPtr(
2811728123
2811828124 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {
2811928125 .pointer => indexable_ptr_ty.childType(zcu),
28120 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(pt)}),
28126 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}),
2812128127 };
2812228128 try sema.checkIndexable(block, src, indexable_ty);
2812328129
......@@ -28288,7 +28294,7 @@ fn validateRuntimeElemAccess(
2828828294 const msg = msg: {
2828928295 const msg = try sema.errMsg(
2829028296 elem_index_src,
28291 "values of type '{}' must be comptime-known, but index value is runtime-known",
28297 "values of type '{f}' must be comptime-known, but index value is runtime-known",
2829228298 .{parent_ty.fmt(sema.pt)},
2829328299 );
2829428300 errdefer msg.destroy(sema.gpa);
......@@ -28304,7 +28310,7 @@ fn validateRuntimeElemAccess(
2830428310 const target = zcu.getTarget();
2830528311 const as = parent_ty.ptrAddressSpace(zcu);
2830628312 if (target_util.arePointersLogical(target, as)) {
28307 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{}'", .{parent_ty.fmt(pt)});
28313 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{f}'", .{parent_ty.fmt(pt)});
2830828314 }
2830928315 }
2831028316}
......@@ -29000,7 +29006,7 @@ fn coerceExtra(
2900029006 return sema.fail(
2900129007 block,
2900229008 inst_src,
29003 "array literal requires address-of operator (&) to coerce to slice type '{}'",
29009 "array literal requires address-of operator (&) to coerce to slice type '{f}'",
2900429010 .{dest_ty.fmt(pt)},
2900529011 );
2900629012 }
......@@ -29027,7 +29033,7 @@ fn coerceExtra(
2902729033 // pointer to tuple to slice
2902829034 if (!dest_info.flags.is_const) {
2902929035 const err_msg = err_msg: {
29030 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(pt)});
29036 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)});
2903129037 errdefer err_msg.destroy(sema.gpa);
2903229038 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
2903329039 break :err_msg err_msg;
......@@ -29082,7 +29088,7 @@ fn coerceExtra(
2908229088 // comptime-known integer to other number
2908329089 if (!(try sema.intFitsInType(val, dest_ty, null))) {
2908429090 if (!opts.report_err) return error.NotCoercible;
29085 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) });
29091 return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) });
2908629092 }
2908729093 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
2908829094 .undef => try pt.undefRef(dest_ty),
......@@ -29124,7 +29130,7 @@ fn coerceExtra(
2912429130 return sema.fail(
2912529131 block,
2912629132 inst_src,
29127 "type '{}' cannot represent float value '{}'",
29133 "type '{f}' cannot represent float value '{f}'",
2912829134 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },
2912929135 );
2913029136 }
......@@ -29157,7 +29163,7 @@ fn coerceExtra(
2915729163 // return sema.fail(
2915829164 // block,
2915929165 // inst_src,
29160 // "type '{}' cannot represent integer value '{}'",
29166 // "type '{f}' cannot represent integer value '{}'",
2916129167 // .{ dest_ty.fmt(pt), val },
2916229168 // );
2916329169 //}
......@@ -29171,7 +29177,7 @@ fn coerceExtra(
2917129177 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
2917229178 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
2917329179 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {
29174 return sema.fail(block, inst_src, "no field named '{}' in enum '{}'", .{
29180 return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{
2917529181 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
2917629182 });
2917729183 };
......@@ -29320,11 +29326,11 @@ fn coerceExtra(
2932029326 }
2932129327
2932229328 const msg = msg: {
29323 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(pt), inst_ty.fmt(pt) });
29329 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{ dest_ty.fmt(pt), inst_ty.fmt(pt) });
2932429330 errdefer msg.destroy(sema.gpa);
2932529331
2932629332 if (!can_coerce_to) {
29327 try sema.errNote(inst_src, msg, "cannot coerce to '{}'", .{dest_ty.fmt(pt)});
29333 try sema.errNote(inst_src, msg, "cannot coerce to '{f}'", .{dest_ty.fmt(pt)});
2932829334 }
2932929335
2933029336 // E!T to T
......@@ -29513,13 +29519,13 @@ const InMemoryCoercionResult = union(enum) {
2951329519 break;
2951429520 },
2951529521 .comptime_int_not_coercible => |int| {
29516 try sema.errNote(src, msg, "type '{}' cannot represent value '{}'", .{
29522 try sema.errNote(src, msg, "type '{f}' cannot represent value '{f}'", .{
2951729523 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),
2951829524 });
2951929525 break;
2952029526 },
2952129527 .error_union_payload => |pair| {
29522 try sema.errNote(src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{
29528 try sema.errNote(src, msg, "error union payload '{f}' cannot cast into error union payload '{f}'", .{
2952329529 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2952429530 });
2952529531 cur = pair.child;
......@@ -29532,18 +29538,18 @@ const InMemoryCoercionResult = union(enum) {
2953229538 },
2953329539 .array_sentinel => |sentinel| {
2953429540 if (sentinel.actual.toIntern() != .unreachable_value) {
29535 try sema.errNote(src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{
29541 try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{
2953629542 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
2953729543 });
2953829544 } else {
29539 try sema.errNote(src, msg, "destination array requires '{}' sentinel", .{
29545 try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
2954029546 sentinel.wanted.fmtValueSema(pt, sema),
2954129547 });
2954229548 }
2954329549 break;
2954429550 },
2954529551 .array_elem => |pair| {
29546 try sema.errNote(src, msg, "array element type '{}' cannot cast into array element type '{}'", .{
29552 try sema.errNote(src, msg, "array element type '{f}' cannot cast into array element type '{f}'", .{
2954729553 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2954829554 });
2954929555 cur = pair.child;
......@@ -29555,19 +29561,19 @@ const InMemoryCoercionResult = union(enum) {
2955529561 break;
2955629562 },
2955729563 .vector_elem => |pair| {
29558 try sema.errNote(src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{
29564 try sema.errNote(src, msg, "vector element type '{f}' cannot cast into vector element type '{f}'", .{
2955929565 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2956029566 });
2956129567 cur = pair.child;
2956229568 },
2956329569 .optional_shape => |pair| {
29564 try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{
29570 try sema.errNote(src, msg, "optional type child '{f}' cannot cast into optional type child '{f}'", .{
2956529571 pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt),
2956629572 });
2956729573 break;
2956829574 },
2956929575 .optional_child => |pair| {
29570 try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{
29576 try sema.errNote(src, msg, "optional type child '{f}' cannot cast into optional type child '{f}'", .{
2957129577 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2957229578 });
2957329579 cur = pair.child;
......@@ -29578,7 +29584,7 @@ const InMemoryCoercionResult = union(enum) {
2957829584 },
2957929585 .missing_error => |missing_errors| {
2958029586 for (missing_errors) |err| {
29581 try sema.errNote(src, msg, "'error.{}' not a member of destination error set", .{err.fmt(&pt.zcu.intern_pool)});
29587 try sema.errNote(src, msg, "'error.{f}' not a member of destination error set", .{err.fmt(&pt.zcu.intern_pool)});
2958229588 }
2958329589 break;
2958429590 },
......@@ -29631,7 +29637,7 @@ const InMemoryCoercionResult = union(enum) {
2963129637 break;
2963229638 },
2963329639 .fn_param => |param| {
29634 try sema.errNote(src, msg, "parameter {d} '{}' cannot cast into '{}'", .{
29640 try sema.errNote(src, msg, "parameter {d} '{f}' cannot cast into '{f}'", .{
2963529641 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),
2963629642 });
2963729643 cur = param.child;
......@@ -29641,13 +29647,13 @@ const InMemoryCoercionResult = union(enum) {
2964129647 break;
2964229648 },
2964329649 .fn_return_type => |pair| {
29644 try sema.errNote(src, msg, "return type '{}' cannot cast into return type '{}'", .{
29650 try sema.errNote(src, msg, "return type '{f}' cannot cast into return type '{f}'", .{
2964529651 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2964629652 });
2964729653 cur = pair.child;
2964829654 },
2964929655 .ptr_child => |pair| {
29650 try sema.errNote(src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{
29656 try sema.errNote(src, msg, "pointer type child '{f}' cannot cast into pointer type child '{f}'", .{
2965129657 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2965229658 });
2965329659 cur = pair.child;
......@@ -29658,11 +29664,11 @@ const InMemoryCoercionResult = union(enum) {
2965829664 },
2965929665 .ptr_sentinel => |sentinel| {
2966029666 if (sentinel.actual.toIntern() != .unreachable_value) {
29661 try sema.errNote(src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{
29667 try sema.errNote(src, msg, "pointer sentinel '{f}' cannot cast into pointer sentinel '{f}'", .{
2966229668 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
2966329669 });
2966429670 } else {
29665 try sema.errNote(src, msg, "destination pointer requires '{}' sentinel", .{
29671 try sema.errNote(src, msg, "destination pointer requires '{f}' sentinel", .{
2966629672 sentinel.wanted.fmtValueSema(pt, sema),
2966729673 });
2966829674 }
......@@ -29676,11 +29682,11 @@ const InMemoryCoercionResult = union(enum) {
2967629682 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);
2967729683 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);
2967829684 if (actual_allow_zero and !wanted_allow_zero) {
29679 try sema.errNote(src, msg, "'{}' could have null values which are illegal in type '{}'", .{
29685 try sema.errNote(src, msg, "'{f}' could have null values which are illegal in type '{f}'", .{
2968029686 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2968129687 });
2968229688 } else {
29683 try sema.errNote(src, msg, "mutable '{}' would allow illegal null values stored to type '{}'", .{
29689 try sema.errNote(src, msg, "mutable '{f}' would allow illegal null values stored to type '{f}'", .{
2968429690 pair.wanted.fmt(pt), pair.actual.fmt(pt),
2968529691 });
2968629692 }
......@@ -29692,7 +29698,7 @@ const InMemoryCoercionResult = union(enum) {
2969229698 if (actual_const and !wanted_const) {
2969329699 try sema.errNote(src, msg, "cast discards const qualifier", .{});
2969429700 } else {
29695 try sema.errNote(src, msg, "mutable '{}' would allow illegal const pointers stored to type '{}'", .{
29701 try sema.errNote(src, msg, "mutable '{f}' would allow illegal const pointers stored to type '{f}'", .{
2969629702 pair.wanted.fmt(pt), pair.actual.fmt(pt),
2969729703 });
2969829704 }
......@@ -29704,7 +29710,7 @@ const InMemoryCoercionResult = union(enum) {
2970429710 if (actual_volatile and !wanted_volatile) {
2970529711 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});
2970629712 } else {
29707 try sema.errNote(src, msg, "mutable '{}' would allow illegal volatile pointers stored to type '{}'", .{
29713 try sema.errNote(src, msg, "mutable '{f}' would allow illegal volatile pointers stored to type '{f}'", .{
2970829714 pair.wanted.fmt(pt), pair.actual.fmt(pt),
2970929715 });
2971029716 }
......@@ -29730,13 +29736,13 @@ const InMemoryCoercionResult = union(enum) {
2973029736 break;
2973129737 },
2973229738 .double_ptr_to_anyopaque => |pair| {
29733 try sema.errNote(src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{
29739 try sema.errNote(src, msg, "cannot implicitly cast double pointer '{f}' to anyopaque pointer '{f}'", .{
2973429740 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2973529741 });
2973629742 break;
2973729743 },
2973829744 .slice_to_anyopaque => |pair| {
29739 try sema.errNote(src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{
29745 try sema.errNote(src, msg, "cannot implicitly cast slice '{f}' to anyopaque pointer '{f}'", .{
2974029746 pair.actual.fmt(pt), pair.wanted.fmt(pt),
2974129747 });
2974229748 try sema.errNote(src, msg, "consider using '.ptr'", .{});
......@@ -30510,7 +30516,7 @@ fn coerceVarArgParam(
3051030516 const coerced_ty = sema.typeOf(coerced);
3051130517 if (!try sema.validateExternType(coerced_ty, .param_ty)) {
3051230518 const msg = msg: {
30513 const msg = try sema.errMsg(inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(pt)});
30519 const msg = try sema.errMsg(inst_src, "cannot pass '{f}' to variadic function", .{coerced_ty.fmt(pt)});
3051430520 errdefer msg.destroy(sema.gpa);
3051530521
3051630522 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);
......@@ -30613,7 +30619,7 @@ fn storePtr2(
3061330619 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.
3061430620 if (try elem_ty.comptimeOnlySema(pt)) {
3061530621 return sema.failWithOwnedErrorMsg(block, msg: {
30616 const msg = try sema.errMsg(src, "cannot store comptime-only type '{}' at runtime", .{elem_ty.fmt(pt)});
30622 const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)});
3061730623 errdefer msg.destroy(sema.gpa);
3061830624 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});
3061930625 break :msg msg;
......@@ -30646,7 +30652,7 @@ fn storePtr2(
3064630652 });
3064730653 return;
3064830654 }
30649 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{
30655 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
3065030656 ptr_ty.fmt(pt),
3065130657 });
3065230658 }
......@@ -30815,19 +30821,19 @@ fn storePtrVal(
3081530821 .{},
3081630822 ),
3081730823 .undef => return sema.failWithUseOfUndef(block, src),
30818 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {}", .{err_name.fmt(ip)}),
30824 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}),
3081930825 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),
3082030826 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
3082130827 .needed_well_defined => |ty| return sema.fail(
3082230828 block,
3082330829 src,
30824 "comptime dereference requires '{}' to have a well-defined layout",
30830 "comptime dereference requires '{f}' to have a well-defined layout",
3082530831 .{ty.fmt(pt)},
3082630832 ),
3082730833 .out_of_bounds => |ty| return sema.fail(
3082830834 block,
3082930835 src,
30830 "dereference of '{}' exceeds bounds of containing decl of type '{}'",
30836 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
3083130837 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
3083230838 ),
3083330839 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),
......@@ -30853,7 +30859,7 @@ fn bitCast(
3085330859 const old_bits = old_ty.bitSize(zcu);
3085430860
3085530861 if (old_bits != dest_bits) {
30856 return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{
30862 return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{f}' has {d} bits but source type '{f}' has {d} bits", .{
3085730863 dest_ty.fmt(pt),
3085830864 dest_bits,
3085930865 old_ty.fmt(pt),
......@@ -30971,7 +30977,7 @@ fn coerceCompatiblePtrs(
3097130977 const inst_ty = sema.typeOf(inst);
3097230978 if (try sema.resolveValue(inst)) |val| {
3097330979 if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) {
30974 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(pt)});
30980 return sema.fail(block, inst_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)});
3097530981 }
3097630982 // The comptime Value representation is compatible with both types.
3097730983 return Air.internedToRef(
......@@ -31017,7 +31023,7 @@ fn coerceEnumToUnion(
3101731023
3101831024 const tag_ty = union_ty.unionTagType(zcu) orelse {
3101931025 const msg = msg: {
31020 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{
31026 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
3102131027 union_ty.fmt(pt), inst_ty.fmt(pt),
3102231028 });
3102331029 errdefer msg.destroy(sema.gpa);
......@@ -31031,7 +31037,7 @@ fn coerceEnumToUnion(
3103131037 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);
3103231038 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {
3103331039 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {
31034 return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{
31040 return sema.fail(block, inst_src, "union '{f}' has no tag with value '{f}'", .{
3103531041 union_ty.fmt(pt), val.fmtValueSema(pt, sema),
3103631042 });
3103731043 };
......@@ -31045,7 +31051,7 @@ fn coerceEnumToUnion(
3104531051 errdefer msg.destroy(sema.gpa);
3104631052
3104731053 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31048 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
31054 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
3104931055 field_name.fmt(ip),
3105031056 });
3105131057 try sema.addDeclaredHereNote(msg, union_ty);
......@@ -31056,13 +31062,13 @@ fn coerceEnumToUnion(
3105631062 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
3105731063 const msg = msg: {
3105831064 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31059 const msg = try sema.errMsg(inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{
31065 const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{
3106031066 inst_ty.fmt(pt), union_ty.fmt(pt),
3106131067 field_ty.fmt(pt), field_name.fmt(ip),
3106231068 });
3106331069 errdefer msg.destroy(sema.gpa);
3106431070
31065 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
31071 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
3106631072 field_name.fmt(ip),
3106731073 });
3106831074 try sema.addDeclaredHereNote(msg, union_ty);
......@@ -31078,7 +31084,7 @@ fn coerceEnumToUnion(
3107831084
3107931085 if (tag_ty.isNonexhaustiveEnum(zcu)) {
3108031086 const msg = msg: {
31081 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{
31087 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{f}' from non-exhaustive enum", .{
3108231088 union_ty.fmt(pt),
3108331089 });
3108431090 errdefer msg.destroy(sema.gpa);
......@@ -31097,7 +31103,7 @@ fn coerceEnumToUnion(
3109731103 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {
3109831104 const err_msg = msg orelse try sema.errMsg(
3109931105 inst_src,
31100 "runtime coercion from enum '{}' to union '{}' which has a 'noreturn' field",
31106 "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field",
3110131107 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
3110231108 );
3110331109 msg = err_msg;
......@@ -31120,7 +31126,7 @@ fn coerceEnumToUnion(
3112031126 const msg = msg: {
3112131127 const msg = try sema.errMsg(
3112231128 inst_src,
31123 "runtime coercion from enum '{}' to union '{}' which has non-void fields",
31129 "runtime coercion from enum '{f}' to union '{f}' which has non-void fields",
3112431130 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
3112531131 );
3112631132 errdefer msg.destroy(sema.gpa);
......@@ -31129,7 +31135,7 @@ fn coerceEnumToUnion(
3112931135 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
3113031136 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
3113131137 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;
31132 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{
31138 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{
3113331139 field_name.fmt(ip),
3113431140 field_ty.fmt(pt),
3113531141 });
......@@ -31170,7 +31176,7 @@ fn coerceArrayLike(
3117031176 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));
3117131177 if (dest_len != inst_len) {
3117231178 const msg = msg: {
31173 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{
31179 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
3117431180 dest_ty.fmt(pt), inst_ty.fmt(pt),
3117531181 });
3117631182 errdefer msg.destroy(sema.gpa);
......@@ -31258,7 +31264,7 @@ fn coerceTupleToArray(
3125831264
3125931265 if (dest_len != inst_len) {
3126031266 const msg = msg: {
31261 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{
31267 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
3126231268 dest_ty.fmt(pt), inst_ty.fmt(pt),
3126331269 });
3126431270 errdefer msg.destroy(sema.gpa);
......@@ -31734,10 +31740,10 @@ fn analyzeLoad(
3173431740 const ptr_ty = sema.typeOf(ptr);
3173531741 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {
3173631742 .pointer => ptr_ty.childType(zcu),
31737 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(pt)}),
31743 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}),
3173831744 };
3173931745 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {
31740 return sema.fail(block, ptr_src, "cannot load opaque type '{}'", .{elem_ty.fmt(pt)});
31746 return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)});
3174131747 }
3174231748
3174331749 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {
......@@ -31758,7 +31764,7 @@ fn analyzeLoad(
3175831764 const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
3175931765 return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
3176031766 }
31761 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{
31767 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
3176231768 ptr_ty.fmt(pt),
3176331769 });
3176431770 }
......@@ -32046,7 +32052,7 @@ fn analyzeSlice(
3204632052 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
3204732053 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {
3204832054 .pointer => ptr_ptr_ty.childType(zcu),
32049 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(pt)}),
32055 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ptr_ty.fmt(pt)}),
3205032056 };
3205132057
3205232058 var array_ty = ptr_ptr_child_ty;
......@@ -32095,7 +32101,7 @@ fn analyzeSlice(
3209532101 try sema.errNote(
3209632102 start_src,
3209732103 msg,
32098 "expected '{}', found '{}'",
32104 "expected '{f}', found '{f}'",
3209932105 .{
3210032106 Value.zero_comptime_int.fmtValueSema(pt, sema),
3210132107 start_value.fmtValueSema(pt, sema),
......@@ -32111,7 +32117,7 @@ fn analyzeSlice(
3211132117 try sema.errNote(
3211232118 end_src,
3211332119 msg,
32114 "expected '{}', found '{}'",
32120 "expected '{f}', found '{f}'",
3211532121 .{
3211632122 Value.one_comptime_int.fmtValueSema(pt, sema),
3211732123 end_value.fmtValueSema(pt, sema),
......@@ -32126,7 +32132,7 @@ fn analyzeSlice(
3212632132 return sema.fail(
3212732133 block,
3212832134 end_src,
32129 "end index {} out of bounds for slice of single-item pointer",
32135 "end index {f} out of bounds for slice of single-item pointer",
3213032136 .{end_value.fmtValueSema(pt, sema)},
3213132137 );
3213232138 }
......@@ -32173,7 +32179,7 @@ fn analyzeSlice(
3217332179 elem_ty = ptr_ptr_child_ty.childType(zcu);
3217432180 },
3217532181 },
32176 else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(pt)}),
32182 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}),
3217732183 }
3217832184
3217932185 const ptr = if (slice_ty.isSlice(zcu))
......@@ -32220,7 +32226,7 @@ fn analyzeSlice(
3222032226 return sema.fail(
3222132227 block,
3222232228 end_src,
32223 "end index {} out of bounds for array of length {}{s}",
32229 "end index {f} out of bounds for array of length {f}{s}",
3222432230 .{
3222532231 end_val.fmtValueSema(pt, sema),
3222632232 len_val.fmtValueSema(pt, sema),
......@@ -32265,7 +32271,7 @@ fn analyzeSlice(
3226532271 return sema.fail(
3226632272 block,
3226732273 end_src,
32268 "end index {} out of bounds for slice of length {d}{s}",
32274 "end index {f} out of bounds for slice of length {d}{s}",
3226932275 .{
3227032276 end_val.fmtValueSema(pt, sema),
3227132277 try slice_val.sliceLen(pt),
......@@ -32324,7 +32330,7 @@ fn analyzeSlice(
3232432330 return sema.fail(
3232532331 block,
3232632332 start_src,
32327 "start index {} is larger than end index {}",
32333 "start index {f} is larger than end index {f}",
3232832334 .{
3232932335 start_val.fmtValueSema(pt, sema),
3233032336 end_val.fmtValueSema(pt, sema),
......@@ -32348,13 +32354,13 @@ fn analyzeSlice(
3234832354 .needed_well_defined => |ty| return sema.fail(
3234932355 block,
3235032356 src,
32351 "comptime dereference requires '{}' to have a well-defined layout",
32357 "comptime dereference requires '{f}' to have a well-defined layout",
3235232358 .{ty.fmt(pt)},
3235332359 ),
3235432360 .out_of_bounds => |ty| return sema.fail(
3235532361 block,
3235632362 end_src,
32357 "slice end index {d} exceeds bounds of containing decl of type '{}'",
32363 "slice end index {d} exceeds bounds of containing decl of type '{f}'",
3235832364 .{ end_int, ty.fmt(pt) },
3235932365 ),
3236032366 };
......@@ -32363,7 +32369,7 @@ fn analyzeSlice(
3236332369 const msg = msg: {
3236432370 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});
3236532371 errdefer msg.destroy(sema.gpa);
32366 try sema.errNote(src, msg, "expected '{}', found '{}'", .{
32372 try sema.errNote(src, msg, "expected '{f}', found '{f}'", .{
3236732373 expected_sentinel.fmtValueSema(pt, sema),
3236832374 actual_sentinel.fmtValueSema(pt, sema),
3236932375 });
......@@ -33251,7 +33257,7 @@ const PeerResolveResult = union(enum) {
3325133257 };
3325233258 },
3325333259 .field_error => |field_error| {
33254 const fmt = "struct field '{}' has conflicting types";
33260 const fmt = "struct field '{f}' has conflicting types";
3325533261 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};
3325633262 if (opt_msg) |msg| {
3325733263 try sema.errNote(src, msg, fmt, args);
......@@ -33282,7 +33288,7 @@ const PeerResolveResult = union(enum) {
3328233288 candidate_srcs.resolve(block, conflict_idx[1]),
3328333289 };
3328433290
33285 const fmt = "incompatible types: '{}' and '{}'";
33291 const fmt = "incompatible types: '{f}' and '{f}'";
3328633292 const args = .{
3328733293 conflict_tys[0].fmt(pt),
3328833294 conflict_tys[1].fmt(pt),
......@@ -33296,8 +33302,8 @@ const PeerResolveResult = union(enum) {
3329633302 break :msg msg;
3329733303 };
3329833304
33299 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(pt)});
33300 if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[1].fmt(pt)});
33305 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[0].fmt(pt)});
33306 if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[1].fmt(pt)});
3330133307
3330233308 // No child error
3330333309 break;
......@@ -34609,7 +34615,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
3460934615 if (struct_type.setLayoutWip(ip)) {
3461034616 const msg = try sema.errMsg(
3461134617 ty.srcLoc(zcu),
34612 "struct '{}' depends on itself",
34618 "struct '{f}' depends on itself",
3461334619 .{ty.fmt(pt)},
3461434620 );
3461534621 return sema.failWithOwnedErrorMsg(null, msg);
......@@ -34828,13 +34834,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_
3482834834 const zcu = pt.zcu;
3482934835
3483034836 if (!backing_int_ty.isInt(zcu)) {
34831 return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(pt)});
34837 return sema.fail(block, src, "expected backing integer type, found '{f}'", .{backing_int_ty.fmt(pt)});
3483234838 }
3483334839 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {
3483434840 return sema.fail(
3483534841 block,
3483634842 src,
34837 "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}",
34843 "backing integer type '{f}' has bit size {} but the struct fields have a total bit size of {}",
3483834844 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },
3483934845 );
3484034846 }
......@@ -34844,7 +34850,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
3484434850 const pt = sema.pt;
3484534851 if (!ty.isIndexable(pt.zcu)) {
3484634852 const msg = msg: {
34847 const msg = try sema.errMsg(src, "type '{}' does not support indexing", .{ty.fmt(pt)});
34853 const msg = try sema.errMsg(src, "type '{f}' does not support indexing", .{ty.fmt(pt)});
3484834854 errdefer msg.destroy(sema.gpa);
3484934855 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});
3485034856 break :msg msg;
......@@ -34868,7 +34874,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
3486834874 }
3486934875 }
3487034876 const msg = msg: {
34871 const msg = try sema.errMsg(src, "type '{}' is not an indexable pointer", .{ty.fmt(pt)});
34877 const msg = try sema.errMsg(src, "type '{f}' is not an indexable pointer", .{ty.fmt(pt)});
3487234878 errdefer msg.destroy(sema.gpa);
3487334879 try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});
3487434880 break :msg msg;
......@@ -34936,7 +34942,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
3493634942 .field_types_wip, .layout_wip => {
3493734943 const msg = try sema.errMsg(
3493834944 ty.srcLoc(pt.zcu),
34939 "union '{}' depends on itself",
34945 "union '{f}' depends on itself",
3494034946 .{ty.fmt(pt)},
3494134947 );
3494234948 return sema.failWithOwnedErrorMsg(null, msg);
......@@ -35124,7 +35130,7 @@ pub fn resolveStructFieldTypes(
3512435130 if (struct_type.setFieldTypesWip(ip)) {
3512535131 const msg = try sema.errMsg(
3512635132 Type.fromInterned(ty).srcLoc(zcu),
35127 "struct '{}' depends on itself",
35133 "struct '{f}' depends on itself",
3512835134 .{Type.fromInterned(ty).fmt(pt)},
3512935135 );
3513035136 return sema.failWithOwnedErrorMsg(null, msg);
......@@ -35153,7 +35159,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
3515335159 if (struct_type.setInitsWip(ip)) {
3515435160 const msg = try sema.errMsg(
3515535161 ty.srcLoc(zcu),
35156 "struct '{}' depends on itself",
35162 "struct '{f}' depends on itself",
3515735163 .{ty.fmt(pt)},
3515835164 );
3515935165 return sema.failWithOwnedErrorMsg(null, msg);
......@@ -35179,7 +35185,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
3517935185 .field_types_wip => {
3518035186 const msg = try sema.errMsg(
3518135187 ty.srcLoc(zcu),
35182 "union '{}' depends on itself",
35188 "union '{f}' depends on itself",
3518335189 .{ty.fmt(pt)},
3518435190 );
3518535191 return sema.failWithOwnedErrorMsg(null, msg);
......@@ -35549,7 +35555,7 @@ fn structFields(
3554935555 switch (struct_type.layout) {
3555035556 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
3555135557 const msg = msg: {
35552 const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
35558 const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
3555335559 errdefer msg.destroy(sema.gpa);
3555435560
3555535561 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);
......@@ -35561,7 +35567,7 @@ fn structFields(
3556135567 },
3556235568 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
3556335569 const msg = msg: {
35564 const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
35570 const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
3556535571 errdefer msg.destroy(sema.gpa);
3556635572
3556735573 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
......@@ -35808,7 +35814,7 @@ fn unionFields(
3580835814 // The provided type is an integer type and we must construct the enum tag type here.
3580935815 int_tag_ty = provided_ty;
3581035816 if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) {
35811 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(pt)});
35817 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{f}'", .{int_tag_ty.fmt(pt)});
3581235818 }
3581335819
3581435820 if (fields_len > 0) {
......@@ -35817,7 +35823,7 @@ fn unionFields(
3581735823 const msg = msg: {
3581835824 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});
3581935825 errdefer msg.destroy(sema.gpa);
35820 try sema.errNote(tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{
35826 try sema.errNote(tag_ty_src, msg, "type '{f}' cannot fit values in range 0...{d}", .{
3582135827 int_tag_ty.fmt(pt),
3582235828 fields_len - 1,
3582335829 });
......@@ -35832,7 +35838,7 @@ fn unionFields(
3583235838 // The provided type is the enum tag type.
3583335839 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
3583435840 .enum_type => ip.loadEnumType(provided_ty.toIntern()),
35835 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(pt)}),
35841 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}),
3583635842 };
3583735843 union_type.setTagType(ip, provided_ty.toIntern());
3583835844 // The fields of the union must match the enum exactly.
......@@ -35929,7 +35935,7 @@ fn unionFields(
3592935935 if (result.overflow) return sema.fail(
3593035936 &block_scope,
3593135937 value_src,
35932 "enumeration value '{}' too large for type '{}'",
35938 "enumeration value '{f}' too large for type '{f}'",
3593335939 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
3593435940 );
3593535941 last_tag_val = result.val;
......@@ -35947,7 +35953,7 @@ fn unionFields(
3594735953 const msg = msg: {
3594835954 const msg = try sema.errMsg(
3594935955 value_src,
35950 "enum tag value {} already taken",
35956 "enum tag value {f} already taken",
3595135957 .{enum_tag_val.fmtValueSema(pt, sema)},
3595235958 );
3595335959 errdefer msg.destroy(gpa);
......@@ -35975,7 +35981,7 @@ fn unionFields(
3597535981 const tag_ty = union_type.tagTypeUnordered(ip);
3597635982 const tag_info = ip.loadEnumType(tag_ty);
3597735983 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
35978 return sema.fail(&block_scope, name_src, "no field named '{}' in enum '{}'", .{
35984 return sema.fail(&block_scope, name_src, "no field named '{f}' in enum '{f}'", .{
3597935985 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),
3598035986 });
3598135987 };
......@@ -35992,7 +35998,7 @@ fn unionFields(
3599235998 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,
3599335999 .offset = .{ .container_field_name = enum_index },
3599436000 };
35995 const msg = try sema.errMsg(name_src, "union field '{}' ordered differently than corresponding enum field", .{
36001 const msg = try sema.errMsg(name_src, "union field '{f}' ordered differently than corresponding enum field", .{
3599636002 field_name.fmt(ip),
3599736003 });
3599836004 errdefer msg.destroy(sema.gpa);
......@@ -36018,7 +36024,7 @@ fn unionFields(
3601836024 !try sema.validateExternType(field_ty, .union_field))
3601936025 {
3602036026 const msg = msg: {
36021 const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
36027 const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
3602236028 errdefer msg.destroy(sema.gpa);
3602336029
3602436030 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);
......@@ -36029,7 +36035,7 @@ fn unionFields(
3602936035 return sema.failWithOwnedErrorMsg(&block_scope, msg);
3603036036 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
3603136037 const msg = msg: {
36032 const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});
36038 const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
3603336039 errdefer msg.destroy(sema.gpa);
3603436040
3603536041 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);
......@@ -36065,7 +36071,7 @@ fn unionFields(
3606536071
3606636072 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
3606736073 if (explicit_tags_seen[field_index]) continue;
36068 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{}' missing, declared here", .{
36074 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{f}' missing, declared here", .{
3606936075 field_name.fmt(ip),
3607036076 });
3607136077 }
......@@ -36101,7 +36107,7 @@ fn generateUnionTagTypeNumbered(
3610136107 const name = try ip.getOrPutStringFmt(
3610236108 gpa,
3610336109 pt.tid,
36104 "@typeInfo({}).@\"union\".tag_type.?",
36110 "@typeInfo({f}).@\"union\".tag_type.?",
3610536111 .{union_name.fmt(ip)},
3610636112 .no_embedded_nulls,
3610736113 );
......@@ -36137,7 +36143,7 @@ fn generateUnionTagTypeSimple(
3613736143 const name = try ip.getOrPutStringFmt(
3613836144 gpa,
3613936145 pt.tid,
36140 "@typeInfo({}).@\"union\".tag_type.?",
36146 "@typeInfo({f}).@\"union\".tag_type.?",
3614136147 .{union_name.fmt(ip)},
3614236148 .no_embedded_nulls,
3614336149 );
......@@ -36671,13 +36677,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
3667136677 .needed_well_defined => |ty| return sema.fail(
3667236678 block,
3667336679 src,
36674 "comptime dereference requires '{}' to have a well-defined layout",
36680 "comptime dereference requires '{f}' to have a well-defined layout",
3667536681 .{ty.fmt(pt)},
3667636682 ),
3667736683 .out_of_bounds => |ty| return sema.fail(
3667836684 block,
3667936685 src,
36680 "dereference of '{}' exceeds bounds of containing decl of type '{}'",
36686 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
3668136687 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
3668236688 ),
3668336689 }
......@@ -36697,7 +36703,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
3669736703 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },
3669836704 .runtime_load => return .runtime_load,
3669936705 .undef => return sema.failWithUseOfUndef(block, src),
36700 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {}", .{err_name.fmt(ip)}),
36706 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}),
3670136707 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),
3670236708 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
3670336709 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },
......@@ -36822,12 +36828,12 @@ fn intFromFloatScalar(
3682236828
3682336829 const float = val.toFloat(f128, zcu);
3682436830 if (std.math.isNan(float)) {
36825 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{
36831 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{f}'", .{
3682636832 int_ty.fmt(pt),
3682736833 });
3682836834 }
3682936835 if (std.math.isInf(float)) {
36830 return sema.fail(block, src, "float value Inf cannot be stored in integer type '{}'", .{
36836 return sema.fail(block, src, "float value Inf cannot be stored in integer type '{f}'", .{
3683136837 int_ty.fmt(pt),
3683236838 });
3683336839 }
......@@ -36842,7 +36848,7 @@ fn intFromFloatScalar(
3684236848 .exact => return sema.fail(
3684336849 block,
3684436850 src,
36845 "fractional component prevents float value '{}' from coercion to type '{}'",
36851 "fractional component prevents float value '{f}' from coercion to type '{f}'",
3684636852 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },
3684736853 ),
3684836854 .truncate => {},
......@@ -36854,7 +36860,7 @@ fn intFromFloatScalar(
3685436860
3685536861 const int_info = int_ty.intInfo(zcu);
3685636862 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {
36857 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
36863 return sema.fail(block, src, "float value '{f}' cannot be stored in integer type '{f}'", .{
3685836864 val.fmtValueSema(pt, sema), int_ty.fmt(pt),
3685936865 });
3686036866 }
......@@ -37186,9 +37192,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3718637192
3718737193 var first_path: std.ArrayListUnmanaged(u8) = .empty;
3718837194 if (intermediate_value_count == 0) {
37189 try first_path.writer(arena).print("{i}", .{start_value_name.fmt(ip)});
37195 try first_path.print(arena, "{fi}", .{start_value_name.fmt(ip)});
3719037196 } else {
37191 try first_path.writer(arena).print("v{}", .{intermediate_value_count - 1});
37197 try first_path.print(arena, "v{}", .{intermediate_value_count - 1});
3719237198 }
3719337199
3719437200 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);
......@@ -37213,30 +37219,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3721337219 error.AnalysisFail => unreachable,
3721437220 };
3721537221
37216 var second_path: std.ArrayListUnmanaged(u8) = .empty;
37222 var second_path_aw: std.io.Writer.Allocating = .init(arena);
37223 defer second_path_aw.deinit();
3721737224 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});
3721837225 const deriv_start = @import("print_value.zig").printPtrDerivation(
3721937226 derivation,
37220 second_path.writer(arena),
37227 &second_path_aw.interface,
3722137228 pt,
3722237229 .lvalue,
3722337230 .{ .str = inter_name },
3722437231 20,
37225 ) catch |err| switch (err) {
37226 error.OutOfMemory => |e| return e,
37227 error.AnalysisFail => unreachable,
37228 error.ComptimeReturn => unreachable,
37229 error.ComptimeBreak => unreachable,
37230 };
37232 ) catch return error.OutOfMemory;
3723137233
3723237234 switch (deriv_start) {
3723337235 .int, .nav_ptr => unreachable,
3723437236 .uav_ptr => |uav| {
37235 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });
37237 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
3723637238 return .{ .new_val = .fromInterned(uav.val) };
3723737239 },
3723837240 .comptime_alloc_ptr => |cta_info| {
37239 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });
37241 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
3724037242 const cta = sema.getComptimeAlloc(cta_info.idx);
3724137243 if (cta.is_const) {
3724237244 return .{ .new_val = cta_info.val };
......@@ -37246,7 +37248,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3724637248 }
3724737249 },
3724837250 .comptime_field_ptr => {
37249 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });
37251 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
3725037252 try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name});
3725137253 return .done;
3725237254 },
......@@ -37286,7 +37288,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
3728637288 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);
3728737289 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;
3728837290 const field_name = backing_enum.enumFieldName(field_idx, zcu);
37289 try path.writer(arena).print(".{i}", .{field_name.fmt(ip)});
37291 try path.print(arena, ".{fi}", .{field_name.fmt(ip)});
3729037292 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);
3729137293 },
3729237294 .aggregate => |agg| {
......@@ -37301,17 +37303,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
3730137303 };
3730237304 const agg_ty: Type = .fromInterned(agg.ty);
3730337305 switch (agg_ty.zigTypeTag(zcu)) {
37304 .array, .vector => try path.writer(arena).print("[{d}]", .{elem_idx}),
37306 .array, .vector => try path.print(arena, "[{d}]", .{elem_idx}),
3730537307 .pointer => switch (elem_idx) {
3730637308 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),
3730737309 Value.slice_len_index => try path.appendSlice(arena, ".len"),
3730837310 else => unreachable,
3730937311 },
3731037312 .@"struct" => if (agg_ty.isTuple(zcu)) {
37311 try path.writer(arena).print("[{d}]", .{elem_idx});
37313 try path.print(arena, "[{d}]", .{elem_idx});
3731237314 } else {
3731337315 const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;
37314 try path.writer(arena).print(".{i}", .{name.fmt(ip)});
37316 try path.print(arena, ".{fi}", .{name.fmt(ip)});
3731537317 },
3731637318 else => unreachable,
3731737319 }
......@@ -37588,7 +37590,7 @@ fn resolveDeclaredEnumInner(
3758837590 if (tag_type_ref != .none) {
3758937591 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
3759037592 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {
37591 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(pt)});
37593 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{f}'", .{ty.fmt(pt)});
3759237594 }
3759337595 break :ty ty;
3759437596 } else if (fields_len == 0) {
......@@ -37642,7 +37644,7 @@ fn resolveDeclaredEnumInner(
3764237644 .offset = .{ .container_field_value = conflict.prev_field_idx },
3764337645 };
3764437646 const msg = msg: {
37645 const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37647 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
3764637648 errdefer msg.destroy(gpa);
3764737649 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
3764837650 break :msg msg;
......@@ -37665,7 +37667,7 @@ fn resolveDeclaredEnumInner(
3766537667 .offset = .{ .container_field_value = conflict.prev_field_idx },
3766637668 };
3766737669 const msg = msg: {
37668 const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37670 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
3766937671 errdefer msg.destroy(gpa);
3767037672 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
3767137673 break :msg msg;
......@@ -37682,7 +37684,7 @@ fn resolveDeclaredEnumInner(
3768237684 };
3768337685
3768437686 if (tag_overflow) {
37685 const msg = try sema.errMsg(value_src, "enumeration value '{}' too large for type '{}'", .{
37687 const msg = try sema.errMsg(value_src, "enumeration value '{f}' too large for type '{f}'", .{
3768637688 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),
3768737689 });
3768837690 return sema.failWithOwnedErrorMsg(block, msg);
src/Sema/LowerZon.zig+1-1
......@@ -661,7 +661,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I
661661 const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse {
662662 return self.fail(
663663 node,
664 "enum {} has no member named '{}'",
664 "enum {f} has no member named '{f}'",
665665 .{
666666 res_ty.fmt(self.sema.pt),
667667 std.zig.fmtId(field_name.get(self.file.zoir.?)),
src/Type.zig+3-1
......@@ -382,7 +382,9 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
382382 }
383383 }
384384 switch (fn_info.cc) {
385 .auto, .async, .naked, .@"inline" => try writer.print("callconv(.{}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),
385 .auto, .async, .naked, .@"inline" => try writer.print("callconv(.{f}) ", .{
386 std.zig.fmtId(@tagName(fn_info.cc)),
387 }),
386388 else => try writer.print("callconv({any}) ", .{fn_info.cc}),
387389 }
388390 }
src/Zcu.zig+1-1
......@@ -2811,7 +2811,7 @@ comptime {
28112811}
28122812
28132813pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
2814 return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file);
2814 return loadZirCacheBody(gpa, try cache_file.deprecatedReader().readStruct(Zir.Header), cache_file);
28152815}
28162816
28172817pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {
src/Zcu/PerThread.zig+5-5
......@@ -341,7 +341,7 @@ fn loadZirZoirCache(
341341 };
342342
343343 // First we read the header to determine the lengths of arrays.
344 const header = cache_file.reader().readStruct(Header) catch |err| switch (err) {
344 const header = cache_file.deprecatedReader().readStruct(Header) catch |err| switch (err) {
345345 // This can happen if Zig bails out of this function between creating
346346 // the cached file and writing it.
347347 error.EndOfStream => return .invalid,
......@@ -477,11 +477,11 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
477477 if (std.zig.srcHashEql(old_hash, new_hash)) {
478478 break :hash_changed;
479479 }
480 log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{
480 log.debug("hash for (%{d} -> %{d}) changed: {x} -> {x}", .{
481481 old_inst,
482482 new_inst,
483 std.fmt.fmtSliceHexLower(&old_hash),
484 std.fmt.fmtSliceHexLower(&new_hash),
483 &old_hash,
484 &new_hash,
485485 });
486486 }
487487 // The source hash associated with this instruction changed - invalidate relevant dependencies.
......@@ -4378,7 +4378,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
43784378 if (build_options.enable_debug_extensions and comp.verbose_air) {
43794379 std.debug.lockStdErr();
43804380 defer std.debug.unlockStdErr();
4381 const stderr = std.fs.File.stderr().writer();
4381 const stderr = std.fs.File.stderr().deprecatedWriter();
43824382 stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {};
43834383 air.write(stderr, pt, liveness);
43844384 stderr.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}) catch {};
src/arch/x86_64/Encoding.zig+1-1
......@@ -187,7 +187,7 @@ pub fn format(
187187 },
188188 }
189189
190 try writer.print(".{}", .{std.fmt.fmtSliceHexUpper(opc[0 .. opc.len - 1])});
190 try writer.print(".{X}", .{opc[0 .. opc.len - 1]});
191191 opc = opc[opc.len - 1 ..];
192192
193193 try writer.writeAll(".W");
src/arch/x86_64/encoder.zig+2-2
......@@ -1205,9 +1205,9 @@ pub const Vex = struct {
12051205fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {
12061206 assert(expected.len > 0);
12071207 if (std.mem.eql(u8, expected, given)) return;
1208 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(expected)});
1208 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{expected});
12091209 defer testing.allocator.free(expected_fmt);
1210 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(given)});
1210 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
12111211 defer testing.allocator.free(given_fmt);
12121212 const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
12131213 const padding = try testing.allocator.alloc(u8, idx + 5);
src/codegen/llvm.zig+1-1
......@@ -2486,7 +2486,7 @@ pub const Object = struct {
24862486 var union_name_buf: ?[:0]const u8 = null;
24872487 defer if (union_name_buf) |buf| gpa.free(buf);
24882488 const union_name = if (layout.tag_size == 0) name else name: {
2489 union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name});
2489 union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0);
24902490 break :name union_name_buf.?;
24912491 };
24922492
src/crash_report.zig+7-7
......@@ -80,7 +80,7 @@ fn dumpStatusReport() !void {
8080 var fba = std.heap.FixedBufferAllocator.init(&crash_heap);
8181 const allocator = fba.allocator();
8282
83 const stderr = std.fs.File.stderr().writer();
83 const stderr = std.fs.File.stderr().deprecatedWriter();
8484 const block: *Sema.Block = anal.block;
8585 const zcu = anal.sema.pt.zcu;
8686
......@@ -271,7 +271,7 @@ const StackContext = union(enum) {
271271 debug.dumpStackTraceFromBase(context);
272272 },
273273 .not_supported => {
274 const stderr = std.fs.File.stderr().writer();
274 const stderr = std.fs.File.stderr().deprecatedWriter();
275275 stderr.writeAll("Stack trace not supported on this platform.\n") catch {};
276276 },
277277 }
......@@ -379,7 +379,7 @@ const PanicSwitch = struct {
379379
380380 state.recover_stage = .release_mutex;
381381
382 const stderr = std.fs.File.stderr().writer();
382 const stderr = std.fs.File.stderr().deprecatedWriter();
383383 if (builtin.single_threaded) {
384384 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});
385385 } else {
......@@ -406,7 +406,7 @@ const PanicSwitch = struct {
406406 recover(state, trace, stack, msg);
407407
408408 state.recover_stage = .release_mutex;
409 const stderr = std.fs.File.stderr().writer();
409 const stderr = std.fs.File.stderr().deprecatedWriter();
410410 stderr.writeAll("\nOriginal Error:\n") catch {};
411411 goTo(reportStack, .{state});
412412 }
......@@ -477,7 +477,7 @@ const PanicSwitch = struct {
477477 recover(state, trace, stack, msg);
478478
479479 state.recover_stage = .silent_abort;
480 const stderr = std.fs.File.stderr().writer();
480 const stderr = std.fs.File.stderr().deprecatedWriter();
481481 stderr.writeAll("Aborting...\n") catch {};
482482 goTo(abort, .{});
483483 }
......@@ -505,7 +505,7 @@ const PanicSwitch = struct {
505505 // lower the verbosity, and restore it at the end if we don't panic.
506506 state.recover_verbosity = .message_only;
507507
508 const stderr = std.fs.File.stderr().writer();
508 const stderr = std.fs.File.stderr().deprecatedWriter();
509509 stderr.writeAll("\nPanicked during a panic: ") catch {};
510510 stderr.writeAll(msg) catch {};
511511 stderr.writeAll("\nInner panic stack:\n") catch {};
......@@ -519,7 +519,7 @@ const PanicSwitch = struct {
519519 .message_only => {
520520 state.recover_verbosity = .silent;
521521
522 const stderr = std.fs.File.stderr().writer();
522 const stderr = std.fs.File.stderr().deprecatedWriter();
523523 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
524524 stderr.writeAll(msg) catch {};
525525 stderr.writeAll("\n") catch {};
src/fmt.zig+3-3
......@@ -60,7 +60,7 @@ pub fn run(
6060 const arg = args[i];
6161 if (mem.startsWith(u8, arg, "-")) {
6262 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
63 const stdout = std.fs.File.stdout().writer();
63 const stdout = std.fs.File.stdout().deprecatedWriter();
6464 try stdout.writeAll(usage_fmt);
6565 return process.cleanExit();
6666 } else if (mem.eql(u8, arg, "--color")) {
......@@ -371,7 +371,7 @@ fn fmtPathFile(
371371 return;
372372
373373 if (check_mode) {
374 const stdout = std.fs.File.stdout().writer();
374 const stdout = std.fs.File.stdout().deprecatedWriter();
375375 try stdout.print("{s}\n", .{file_path});
376376 fmt.any_error = true;
377377 } else {
......@@ -380,7 +380,7 @@ fn fmtPathFile(
380380
381381 try af.file.writeAll(fmt.out_buffer.items);
382382 try af.finish();
383 const stdout = std.fs.File.stdout().writer();
383 const stdout = std.fs.File.stdout().deprecatedWriter();
384384 try stdout.print("{s}\n", .{file_path});
385385 }
386386}
src/libs/libtsan.zig+1-1
......@@ -268,7 +268,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
268268 const skip_linker_dependencies = !target.os.tag.isDarwin();
269269 const linker_allow_shlib_undefined = target.os.tag.isDarwin();
270270 const install_name = if (target.os.tag.isDarwin())
271 try std.fmt.allocPrintZ(arena, "@rpath/{s}", .{basename})
271 try std.fmt.allocPrintSentinel(arena, "@rpath/{s}", .{basename}, 0)
272272 else
273273 null;
274274 // Workaround for https://github.com/llvm/llvm-project/issues/97627
src/libs/mingw.zig+2-2
......@@ -306,7 +306,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
306306 if (comp.verbose_cc) print: {
307307 std.debug.lockStdErr();
308308 defer std.debug.unlockStdErr();
309 const stderr = std.fs.File.stderr().writer();
309 const stderr = std.fs.File.stderr().deprecatedWriter();
310310 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;
311311 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
312312 nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print;
......@@ -335,7 +335,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
335335 // new scope to ensure definition file is written before passing the path to WriteImportLibrary
336336 const def_final_file = try o_dir.createFile(final_def_basename, .{ .truncate = true });
337337 defer def_final_file.close();
338 try pp.prettyPrintTokens(def_final_file.writer(), .result_only);
338 try pp.prettyPrintTokens(def_final_file.deprecatedWriter(), .result_only);
339339 }
340340
341341 const lib_final_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
src/link/Coff.zig+2-2
......@@ -830,8 +830,8 @@ fn debugMem(allocator: Allocator, handle: std.process.Child.Id, pvaddr: std.os.w
830830 const buffer = try allocator.alloc(u8, code.len);
831831 defer allocator.free(buffer);
832832 const memread = try std.os.windows.ReadProcessMemory(handle, pvaddr, buffer);
833 log.debug("to write: {x}", .{std.fmt.fmtSliceHexLower(code)});
834 log.debug("in memory: {x}", .{std.fmt.fmtSliceHexLower(memread)});
833 log.debug("to write: {x}", .{code});
834 log.debug("in memory: {x}", .{memread});
835835}
836836
837837fn writeMemProtected(handle: std.process.Child.Id, pvaddr: std.os.windows.LPVOID, code: []const u8) !void {
src/link/Elf/Archive.zig+3-3
......@@ -44,8 +44,8 @@ pub fn parse(
4444 pos += @sizeOf(elf.ar_hdr);
4545
4646 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) {
47 return diags.failParse(path, "invalid archive header delimiter: {s}", .{
48 std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),
47 return diags.failParse(path, "invalid archive header delimiter: {f}", .{
48 std.ascii.hexEscape(&hdr.ar_fmag, .lower),
4949 });
5050 }
5151
......@@ -288,7 +288,7 @@ pub const ArStrtab = struct {
288288 ) !void {
289289 _ = unused_fmt_string;
290290 _ = options;
291 try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});
291 try writer.print("{f}", .{std.ascii.hexEscape(ar.buffer.items, .lower)});
292292 }
293293};
294294
src/link/Elf/LinkerDefined.zig+2-2
......@@ -147,9 +147,9 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
147147 for (slice.items(.shdr)) |shdr| {
148148 // TODO use getOrPut for incremental so that we don't create duplicates
149149 if (elf_file.getStartStopBasename(shdr)) |name| {
150 const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
150 const start_name = try std.fmt.allocPrintSentinel(gpa, "__start_{s}", .{name}, 0);
151151 defer gpa.free(start_name);
152 const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
152 const stop_name = try std.fmt.allocPrintSentinel(gpa, "__stop_{s}", .{name}, 0);
153153 defer gpa.free(stop_name);
154154
155155 for (&[_][]const u8{ start_name, stop_name }) |nn| {
src/link/Elf/ZigObject.zig+4-4
......@@ -803,9 +803,9 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void {
803803 const out_shndx = atom_ptr.output_section_index;
804804 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];
805805 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;
806 const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{
806 const rela_sect_name = try std.fmt.allocPrintSentinel(gpa, ".rela{s}", .{
807807 elf_file.getShString(out_shdr.sh_name),
808 });
808 }, 0);
809809 defer gpa.free(rela_sect_name);
810810 _ = elf_file.sectionByName(rela_sect_name) orelse
811811 try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), out_shndx);
......@@ -824,9 +824,9 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
824824 const out_shndx = atom_ptr.output_section_index;
825825 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];
826826 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;
827 const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{
827 const rela_sect_name = try std.fmt.allocPrintSentinel(gpa, ".rela{s}", .{
828828 elf_file.getShString(out_shdr.sh_name),
829 });
829 }, 0);
830830 defer gpa.free(rela_sect_name);
831831 const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?;
832832 const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx];
src/link/Elf/gc.zig+1-1
......@@ -163,7 +163,7 @@ fn prune(elf_file: *Elf) void {
163163}
164164
165165pub fn dumpPrunedAtoms(elf_file: *Elf) !void {
166 const stderr = std.fs.File.stderr().writer();
166 const stderr = std.fs.File.stderr().deprecatedWriter();
167167 for (elf_file.objects.items) |index| {
168168 const file = elf_file.file(index).?;
169169 for (file.atoms()) |atom_index| {
src/link/LdScript.zig+2-2
......@@ -41,8 +41,8 @@ pub fn parse(
4141 try line_col.append(gpa, .{ .line = line, .column = column });
4242 switch (tok.id) {
4343 .invalid => {
44 return diags.failParse(path, "invalid token in LD script: '{s}' ({d}:{d})", .{
45 std.fmt.fmtSliceEscapeLower(tok.get(data)), line, column,
44 return diags.failParse(path, "invalid token in LD script: '{f}' ({d}:{d})", .{
45 std.ascii.hexEscape(tok.get(data), .lower), line, column,
4646 });
4747 },
4848 .new_line => {
src/link/Lld.zig+3-7
......@@ -933,9 +933,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
933933 .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
934934 @tagName(base.build_id),
935935 })),
936 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
937 std.fmt.fmtSliceHexLower(hs.toSlice()),
938 })),
936 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()})),
939937 }
940938
941939 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{elf.image_base}));
......@@ -1511,9 +1509,7 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
15111509 .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
15121510 @tagName(base.build_id),
15131511 })),
1514 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
1515 std.fmt.fmtSliceHexLower(hs.toSlice()),
1516 })),
1512 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()})),
15171513 .md5 => {},
15181514 }
15191515
......@@ -1667,7 +1663,7 @@ fn spawnLld(
16671663 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
16681664 {
16691665 defer rsp_file.close();
1670 var rsp_buf = std.io.bufferedWriter(rsp_file.writer());
1666 var rsp_buf = std.io.bufferedWriter(rsp_file.deprecatedWriter());
16711667 const rsp_writer = rsp_buf.writer();
16721668 for (argv[2..]) |arg| {
16731669 try rsp_writer.writeByte('"');
src/link/MachO/Archive.zig+2-2
......@@ -29,8 +29,8 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
2929 pos += @sizeOf(ar_hdr);
3030
3131 if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) {
32 return diags.failParse(path, "invalid header delimiter: expected '{s}', found '{s}'", .{
33 std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),
32 return diags.failParse(path, "invalid header delimiter: expected '{f}', found '{f}'", .{
33 std.ascii.hexEscape(ARFMAG, .lower), std.ascii.hexEscape(&hdr.ar_fmag, .lower),
3434 });
3535 }
3636
src/link/MachO/Object.zig+7-7
......@@ -308,7 +308,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {
308308 } else nlists.len;
309309
310310 if (nlist_start == nlist_end or nlists[nlist_start].nlist.n_value > sect.addr) {
311 const name = try std.fmt.allocPrintZ(allocator, "{s}${s}$begin", .{ sect.segName(), sect.sectName() });
311 const name = try std.fmt.allocPrintSentinel(allocator, "{s}${s}$begin", .{ sect.segName(), sect.sectName() }, 0);
312312 defer allocator.free(name);
313313 const size = if (nlist_start == nlist_end) sect.size else nlists[nlist_start].nlist.n_value - sect.addr;
314314 const atom_index = try self.addAtom(allocator, .{
......@@ -364,7 +364,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {
364364 // which cannot be contained in any non-zero atom (since then this atom
365365 // would exceed section boundaries). In order to facilitate this behaviour,
366366 // we create a dummy zero-sized atom at section end (addr + size).
367 const name = try std.fmt.allocPrintZ(allocator, "{s}${s}$end", .{ sect.segName(), sect.sectName() });
367 const name = try std.fmt.allocPrintSentinel(allocator, "{s}${s}$end", .{ sect.segName(), sect.sectName() }, 0);
368368 defer allocator.free(name);
369369 const atom_index = try self.addAtom(allocator, .{
370370 .name = try self.addString(allocator, name),
......@@ -394,7 +394,7 @@ fn initSections(self: *Object, allocator: Allocator, nlists: anytype) !void {
394394 if (isFixedSizeLiteral(sect)) continue;
395395 if (isPtrLiteral(sect)) continue;
396396
397 const name = try std.fmt.allocPrintZ(allocator, "{s}${s}", .{ sect.segName(), sect.sectName() });
397 const name = try std.fmt.allocPrintSentinel(allocator, "{s}${s}", .{ sect.segName(), sect.sectName() }, 0);
398398 defer allocator.free(name);
399399
400400 const atom_index = try self.addAtom(allocator, .{
......@@ -462,7 +462,7 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m
462462 }
463463 end += 1;
464464
465 const name = try std.fmt.allocPrintZ(allocator, "l._str{d}", .{count});
465 const name = try std.fmt.allocPrintSentinel(allocator, "l._str{d}", .{count}, 0);
466466 defer allocator.free(name);
467467 const name_str = try self.addString(allocator, name);
468468
......@@ -529,7 +529,7 @@ fn initFixedSizeLiterals(self: *Object, allocator: Allocator, macho_file: *MachO
529529 pos += rec_size;
530530 count += 1;
531531 }) {
532 const name = try std.fmt.allocPrintZ(allocator, "l._literal{d}", .{count});
532 const name = try std.fmt.allocPrintSentinel(allocator, "l._literal{d}", .{count}, 0);
533533 defer allocator.free(name);
534534 const name_str = try self.addString(allocator, name);
535535
......@@ -587,7 +587,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO)
587587 for (0..num_ptrs) |i| {
588588 const pos: u32 = @as(u32, @intCast(i)) * rec_size;
589589
590 const name = try std.fmt.allocPrintZ(allocator, "l._ptr{d}", .{i});
590 const name = try std.fmt.allocPrintSentinel(allocator, "l._ptr{d}", .{i}, 0);
591591 defer allocator.free(name);
592592 const name_str = try self.addString(allocator, name);
593593
......@@ -1558,7 +1558,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {
15581558 const nlist = &self.symtab.items(.nlist)[nlist_idx];
15591559 const nlist_atom = &self.symtab.items(.atom)[nlist_idx];
15601560
1561 const name = try std.fmt.allocPrintZ(gpa, "__DATA$__common${s}", .{sym.getName(macho_file)});
1561 const name = try std.fmt.allocPrintSentinel(gpa, "__DATA$__common${s}", .{sym.getName(macho_file)}, 0);
15621562 defer gpa.free(name);
15631563
15641564 const alignment = (nlist.n_desc >> 8) & 0x0f;
src/link/MachO/ZigObject.zig+1-1
......@@ -959,7 +959,7 @@ fn updateNavCode(
959959 sym.out_n_sect = sect_index;
960960 atom.out_n_sect = sect_index;
961961
962 const sym_name = try std.fmt.allocPrintZ(gpa, "_{s}", .{nav.fqn.toSlice(ip)});
962 const sym_name = try std.fmt.allocPrintSentinel(gpa, "_{s}", .{nav.fqn.toSlice(ip)}, 0);
963963 defer gpa.free(sym_name);
964964 sym.name = try self.addString(gpa, sym_name);
965965 atom.setAlive(true);
src/link/MachO/dyld_info/Trie.zig+2-2
......@@ -336,9 +336,9 @@ const Edge = struct {
336336fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
337337 assert(expected.len > 0);
338338 if (mem.eql(u8, expected, given)) return;
339 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(expected)});
339 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{expected});
340340 defer testing.allocator.free(expected_fmt);
341 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(given)});
341 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
342342 defer testing.allocator.free(given_fmt);
343343 const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
344344 const padding = try testing.allocator.alloc(u8, idx + 5);
src/link/Wasm/Flush.zig+3-9
......@@ -1035,20 +1035,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
10351035 var id: [16]u8 = undefined;
10361036 std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
10371037 var uuid: [36]u8 = undefined;
1038 _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{
1039 std.fmt.fmtSliceHexLower(id[0..4]),
1040 std.fmt.fmtSliceHexLower(id[4..6]),
1041 std.fmt.fmtSliceHexLower(id[6..8]),
1042 std.fmt.fmtSliceHexLower(id[8..10]),
1043 std.fmt.fmtSliceHexLower(id[10..]),
1038 _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{
1039 id[0..4], id[4..6], id[6..8], id[8..10], id[10..],
10441040 });
10451041 try emitBuildIdSection(gpa, binary_bytes, &uuid);
10461042 },
10471043 .hexstring => |hs| {
10481044 var buffer: [32 * 2]u8 = undefined;
1049 const str = std.fmt.bufPrint(&buffer, "{s}", .{
1050 std.fmt.fmtSliceHexLower(hs.toSlice()),
1051 }) catch unreachable;
1045 const str = std.fmt.bufPrint(&buffer, "{x}", .{hs.toSlice()}) catch unreachable;
10521046 try emitBuildIdSection(gpa, binary_bytes, str);
10531047 },
10541048 else => |mode| {
src/link/tapi/parse.zig+10-39
......@@ -57,14 +57,9 @@ pub const Node = struct {
5757 }
5858 }
5959
60 pub fn format(
61 self: *const Node,
62 comptime fmt: []const u8,
63 options: std.fmt.FormatOptions,
64 writer: anytype,
65 ) !void {
60 pub fn format(self: *const Node, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
6661 switch (self.tag) {
67 inline else => |tag| return @as(*tag.Type(), @fieldParentPtr("base", self)).format(fmt, options, writer),
62 inline else => |tag| return @as(*tag.Type(), @fieldParentPtr("base", self)).format(writer, fmt),
6863 }
6964 }
7065
......@@ -86,14 +81,8 @@ pub const Node = struct {
8681 }
8782 }
8883
89 pub fn format(
90 self: *const Doc,
91 comptime fmt: []const u8,
92 options: std.fmt.FormatOptions,
93 writer: anytype,
94 ) !void {
95 _ = options;
96 _ = fmt;
84 pub fn format(self: *const Doc, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
85 comptime assert(fmt.len == 0);
9786 if (self.directive) |id| {
9887 try std.fmt.format(writer, "{{ ", .{});
9988 const directive = self.base.tree.getRaw(id, id);
......@@ -133,14 +122,8 @@ pub const Node = struct {
133122 self.values.deinit(allocator);
134123 }
135124
136 pub fn format(
137 self: *const Map,
138 comptime fmt: []const u8,
139 options: std.fmt.FormatOptions,
140 writer: anytype,
141 ) !void {
142 _ = options;
143 _ = fmt;
125 pub fn format(self: *const Map, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
126 comptime assert(fmt.len == 0);
144127 try std.fmt.format(writer, "{{ ", .{});
145128 for (self.values.items) |entry| {
146129 const key = self.base.tree.getRaw(entry.key, entry.key);
......@@ -172,14 +155,8 @@ pub const Node = struct {
172155 self.values.deinit(allocator);
173156 }
174157
175 pub fn format(
176 self: *const List,
177 comptime fmt: []const u8,
178 options: std.fmt.FormatOptions,
179 writer: anytype,
180 ) !void {
181 _ = options;
182 _ = fmt;
158 pub fn format(self: *const List, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
159 comptime assert(fmt.len == 0);
183160 try std.fmt.format(writer, "[ ", .{});
184161 for (self.values.items) |node| {
185162 try std.fmt.format(writer, "{}, ", .{node});
......@@ -203,14 +180,8 @@ pub const Node = struct {
203180 self.string_value.deinit(allocator);
204181 }
205182
206 pub fn format(
207 self: *const Value,
208 comptime fmt: []const u8,
209 options: std.fmt.FormatOptions,
210 writer: anytype,
211 ) !void {
212 _ = options;
213 _ = fmt;
183 pub fn format(self: *const Value, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
184 comptime assert(fmt.len == 0);
214185 const raw = self.base.tree.getRaw(self.base.start, self.base.end);
215186 return std.fmt.format(writer, "{s}", .{raw});
216187 }
src/main.zig+22-23
......@@ -340,7 +340,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
340340 } else if (mem.eql(u8, cmd, "targets")) {
341341 dev.check(.targets_command);
342342 const host = std.zig.resolveTargetQueryOrFatal(.{});
343 const stdout = fs.File.stdout().writer();
343 const stdout = fs.File.stdout().deprecatedWriter();
344344 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host);
345345 } else if (mem.eql(u8, cmd, "version")) {
346346 dev.check(.version_command);
......@@ -352,7 +352,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
352352 } else if (mem.eql(u8, cmd, "env")) {
353353 dev.check(.env_command);
354354 verifyLibcxxCorrectlyLinked();
355 return @import("print_env.zig").cmdEnv(arena, cmd_args, fs.File.stdout().writer());
355 return @import("print_env.zig").cmdEnv(arena, cmd_args, fs.File.stdout().deprecatedWriter());
356356 } else if (mem.eql(u8, cmd, "reduce")) {
357357 return jitCmd(gpa, arena, cmd_args, .{
358358 .cmd_name = "reduce",
......@@ -3333,9 +3333,8 @@ fn buildOutputType(
33333333 var bin_digest: Cache.BinDigest = undefined;
33343334 hasher.final(&bin_digest);
33353335
3336 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{s}-stdin{s}", .{
3337 std.fmt.fmtSliceHexLower(&bin_digest),
3338 ext.canonicalName(target),
3336 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
3337 &bin_digest, ext.canonicalName(target),
33393338 });
33403339 try dirs.local_cache.handle.rename(dump_path, sub_path);
33413340
......@@ -6110,7 +6109,7 @@ fn cmdAstCheck(
61106109 const stdout = fs.File.stdout();
61116110 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
61126111 // zig fmt: off
6113 try stdout.writer().print(
6112 try stdout.deprecatedWriter().print(
61146113 \\# Source bytes: {}
61156114 \\# Tokens: {} ({})
61166115 \\# AST Nodes: {} ({})
......@@ -6186,7 +6185,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {
61866185 const arg = args[i];
61876186 if (mem.startsWith(u8, arg, "-")) {
61886187 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6189 const stdout = fs.File.stdout().writer();
6188 const stdout = fs.File.stdout().deprecatedWriter();
61906189 try stdout.writeAll(detect_cpu_usage);
61916190 return cleanExit();
61926191 } else if (mem.eql(u8, arg, "--llvm")) {
......@@ -6279,7 +6278,7 @@ fn detectNativeCpuWithLLVM(
62796278}
62806279
62816280fn printCpu(cpu: std.Target.Cpu) !void {
6282 var bw = io.bufferedWriter(fs.File.stdout().writer());
6281 var bw = io.bufferedWriter(fs.File.stdout().deprecatedWriter());
62836282 const stdout = bw.writer();
62846283
62856284 if (cpu.model.llvm_name) |llvm_name| {
......@@ -6328,7 +6327,7 @@ fn cmdDumpLlvmInts(
63286327 const dl = tm.createTargetDataLayout();
63296328 const context = llvm.Context.create();
63306329
6331 var bw = io.bufferedWriter(fs.File.stdout().writer());
6330 var bw = io.bufferedWriter(fs.File.stdout().deprecatedWriter());
63326331 const stdout = bw.writer();
63336332
63346333 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
......@@ -6371,7 +6370,7 @@ fn cmdDumpZir(
63716370 const stdout = fs.File.stdout();
63726371 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
63736372 // zig fmt: off
6374 try stdout.writer().print(
6373 try stdout.deprecatedWriter().print(
63756374 \\# Total ZIR bytes: {}
63766375 \\# Instructions: {d} ({})
63776376 \\# String Table Bytes: {}
......@@ -6444,7 +6443,7 @@ fn cmdChangelist(
64446443 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
64456444 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
64466445
6447 var bw = io.bufferedWriter(fs.File.stdout().writer());
6446 var bw = io.bufferedWriter(fs.File.stdout().deprecatedWriter());
64486447 const stdout = bw.writer();
64496448 {
64506449 try stdout.print("Instruction mappings:\n", .{});
......@@ -6794,7 +6793,7 @@ fn cmdFetch(
67946793 const arg = args[i];
67956794 if (mem.startsWith(u8, arg, "-")) {
67966795 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6797 const stdout = fs.File.stdout().writer();
6796 const stdout = fs.File.stdout().deprecatedWriter();
67986797 try stdout.writeAll(usage_fetch);
67996798 return cleanExit();
68006799 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
......@@ -6908,7 +6907,7 @@ fn cmdFetch(
69086907
69096908 const name = switch (save) {
69106909 .no => {
6911 try fs.File.stdout().writer().print("{s}\n", .{package_hash_slice});
6910 try fs.File.stdout().deprecatedWriter().print("{s}\n", .{package_hash_slice});
69126911 return cleanExit();
69136912 },
69146913 .yes, .exact => |name| name: {
......@@ -6973,16 +6972,16 @@ fn cmdFetch(
69736972
69746973 const new_node_init = try std.fmt.allocPrint(arena,
69756974 \\.{{
6976 \\ .url = "{}",
6977 \\ .hash = "{}",
6975 \\ .url = "{f}",
6976 \\ .hash = "{f}",
69786977 \\ }}
69796978 , .{
6980 std.zig.fmtEscapes(saved_path_or_url),
6981 std.zig.fmtEscapes(package_hash_slice),
6979 std.zig.fmtString(saved_path_or_url),
6980 std.zig.fmtString(package_hash_slice),
69826981 });
69836982
6984 const new_node_text = try std.fmt.allocPrint(arena, ".{p_} = {s},\n", .{
6985 std.zig.fmtId(name), new_node_init,
6983 const new_node_text = try std.fmt.allocPrint(arena, ".{f} = {s},\n", .{
6984 std.zig.fmtIdPU(name), new_node_init,
69866985 });
69876986
69886987 const dependencies_init = try std.fmt.allocPrint(arena, ".{{\n {s} }}", .{
......@@ -7008,13 +7007,13 @@ fn cmdFetch(
70087007
70097008 const location_replace = try std.fmt.allocPrint(
70107009 arena,
7011 "\"{}\"",
7012 .{std.zig.fmtEscapes(saved_path_or_url)},
7010 "\"{f}\"",
7011 .{std.zig.fmtString(saved_path_or_url)},
70137012 );
70147013 const hash_replace = try std.fmt.allocPrint(
70157014 arena,
7016 "\"{}\"",
7017 .{std.zig.fmtEscapes(package_hash_slice)},
7015 "\"{f}\"",
7016 .{std.zig.fmtString(package_hash_slice)},
70187017 );
70197018
70207019 warn("overwriting existing dependency named '{s}'", .{name});
src/print_value.zig+2-2
......@@ -232,7 +232,7 @@ fn printAggregate(
232232 const len = ty.arrayLenIncludingSentinel(zcu);
233233 if (len == 0) break :string;
234234 const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip);
235 try writer.print("\"{}\"", .{std.zig.fmtEscapes(slice)});
235 try writer.print("\"{f}\"", .{std.zig.fmtString(slice)});
236236 if (!is_ref) try writer.writeAll(".*");
237237 return;
238238 },
......@@ -249,7 +249,7 @@ fn printAggregate(
249249 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);
250250 if (elem_val.isUndef(zcu)) break :one_byte_str;
251251 const byte = elem_val.toUnsignedInt(zcu);
252 try writer.print("\"{}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})});
252 try writer.print("\"{f}\"", .{std.zig.fmtString(&.{@intCast(byte)})});
253253 if (!is_ref) try writer.writeAll(".*");
254254 return;
255255 },
src/print_zir.zig+29-33
......@@ -30,7 +30,7 @@ pub fn renderAsTextToFile(
3030 .recurse_blocks = true,
3131 };
3232
33 var raw_stream = std.io.bufferedWriter(fs_file.writer());
33 var raw_stream = std.io.bufferedWriter(fs_file.deprecatedWriter());
3434 const stream = raw_stream.writer();
3535
3636 const main_struct_inst: Zir.Inst.Index = .main_struct_inst;
......@@ -49,8 +49,8 @@ pub fn renderAsTextToFile(
4949 extra_index = item.end;
5050
5151 const import_path = zir.nullTerminatedString(item.data.name);
52 try stream.print(" @import(\"{}\") ", .{
53 std.zig.fmtEscapes(import_path),
52 try stream.print(" @import(\"{f}\") ", .{
53 std.zig.fmtString(import_path),
5454 });
5555 try writer.writeSrcTokAbs(stream, item.data.token);
5656 try stream.writeAll("\n");
......@@ -789,7 +789,7 @@ const Writer = struct {
789789 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
790790 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
791791 const str = inst_data.get(self.code);
792 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
792 try stream.print("\"{f}\")", .{std.zig.fmtString(str)});
793793 }
794794
795795 fn writeSliceStart(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
......@@ -932,8 +932,8 @@ const Writer = struct {
932932 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
933933 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
934934 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
935 try stream.print("\"{}\", ", .{
936 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),
935 try stream.print("\"{f}\", ", .{
936 std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)),
937937 });
938938
939939 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
......@@ -1203,7 +1203,7 @@ const Writer = struct {
12031203 try stream.writeAll(", ");
12041204 } else {
12051205 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
1206 try stream.print("\"{}\", ", .{std.zig.fmtEscapes(asm_source)});
1206 try stream.print("\"{f}\", ", .{std.zig.fmtString(asm_source)});
12071207 }
12081208 try stream.writeAll(", ");
12091209
......@@ -1220,8 +1220,8 @@ const Writer = struct {
12201220
12211221 const name = self.code.nullTerminatedString(output.data.name);
12221222 const constraint = self.code.nullTerminatedString(output.data.constraint);
1223 try stream.print("output({p}, \"{}\", ", .{
1224 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
1223 try stream.print("output({f}, \"{f}\", ", .{
1224 std.zig.fmtIdFlags(name, .{ .allow_primitive = true }), std.zig.fmtString(constraint),
12251225 });
12261226 try self.writeFlag(stream, "->", is_type);
12271227 try self.writeInstRef(stream, output.data.operand);
......@@ -1239,8 +1239,8 @@ const Writer = struct {
12391239
12401240 const name = self.code.nullTerminatedString(input.data.name);
12411241 const constraint = self.code.nullTerminatedString(input.data.constraint);
1242 try stream.print("input({p}, \"{}\", ", .{
1243 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
1242 try stream.print("input({f}, \"{f}\", ", .{
1243 std.zig.fmtIdFlags(name, .{ .allow_primitive = true }), std.zig.fmtString(constraint),
12441244 });
12451245 try self.writeInstRef(stream, input.data.operand);
12461246 try stream.writeAll(")");
......@@ -1255,7 +1255,7 @@ const Writer = struct {
12551255 const str_index = self.code.extra[extra_i];
12561256 extra_i += 1;
12571257 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));
1258 try stream.print("{p}", .{std.zig.fmtId(clobber)});
1258 try stream.print("{f}", .{std.zig.fmtIdFlags(clobber, .{ .allow_primitive = true })});
12591259 if (i + 1 < clobbers_len) {
12601260 try stream.writeAll(", ");
12611261 }
......@@ -1299,7 +1299,7 @@ const Writer = struct {
12991299 .field => {
13001300 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
13011301 try self.writeInstRef(stream, extra.data.obj_ptr);
1302 try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)});
1302 try stream.print(", \"{f}\"", .{std.zig.fmtString(field_name)});
13031303 },
13041304 }
13051305 try stream.writeAll(", [");
......@@ -1388,7 +1388,7 @@ const Writer = struct {
13881388 extra.data.fields_hash_3,
13891389 });
13901390
1391 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});
1391 try stream.print("hash({x}) ", .{&fields_hash});
13921392
13931393 var extra_index: usize = extra.end;
13941394
......@@ -1519,7 +1519,7 @@ const Writer = struct {
15191519 try self.writeFlag(stream, "comptime ", field.is_comptime);
15201520 if (field.name != .empty) {
15211521 const field_name = self.code.nullTerminatedString(field.name);
1522 try stream.print("{p}: ", .{std.zig.fmtId(field_name)});
1522 try stream.print("{f}: ", .{std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true })});
15231523 } else {
15241524 try stream.print("@\"{d}\": ", .{i});
15251525 }
......@@ -1580,7 +1580,7 @@ const Writer = struct {
15801580 extra.data.fields_hash_3,
15811581 });
15821582
1583 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});
1583 try stream.print("hash({x}) ", .{&fields_hash});
15841584
15851585 var extra_index: usize = extra.end;
15861586
......@@ -1682,7 +1682,7 @@ const Writer = struct {
16821682 extra_index += 1;
16831683
16841684 try stream.writeByteNTimes(' ', self.indent);
1685 try stream.print("{p}", .{std.zig.fmtId(field_name)});
1685 try stream.print("{f}", .{std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true })});
16861686
16871687 if (has_type) {
16881688 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
......@@ -1731,7 +1731,7 @@ const Writer = struct {
17311731 extra.data.fields_hash_3,
17321732 });
17331733
1734 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});
1734 try stream.print("hash({x}) ", .{&fields_hash});
17351735
17361736 var extra_index: usize = extra.end;
17371737
......@@ -1816,7 +1816,7 @@ const Writer = struct {
18161816 extra_index += 1;
18171817
18181818 try stream.writeByteNTimes(' ', self.indent);
1819 try stream.print("{p}", .{std.zig.fmtId(field_name)});
1819 try stream.print("{f}", .{std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true })});
18201820
18211821 if (has_tag_value) {
18221822 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
......@@ -1921,7 +1921,7 @@ const Writer = struct {
19211921 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
19221922 const name = self.code.nullTerminatedString(name_index);
19231923 try stream.writeByteNTimes(' ', self.indent);
1924 try stream.print("{p},\n", .{std.zig.fmtId(name)});
1924 try stream.print("{f},\n", .{std.zig.fmtIdFlags(name, .{ .allow_primitive = true })});
19251925 }
19261926
19271927 self.indent -= 2;
......@@ -2203,7 +2203,7 @@ const Writer = struct {
22032203 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
22042204 const name = self.code.nullTerminatedString(extra.field_name_start);
22052205 try self.writeInstRef(stream, extra.lhs);
2206 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});
2206 try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)});
22072207 try self.writeSrcNode(stream, inst_data.src_node);
22082208 }
22092209
......@@ -2244,7 +2244,7 @@ const Writer = struct {
22442244 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
22452245 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
22462246 const str = inst_data.get(self.code);
2247 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});
2247 try stream.print("\"{f}\") ", .{std.zig.fmtString(str)});
22482248 try self.writeSrcTok(stream, inst_data.src_tok);
22492249 }
22502250
......@@ -2252,7 +2252,7 @@ const Writer = struct {
22522252 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
22532253 const str = inst_data.getStr(self.code);
22542254 try self.writeInstRef(stream, inst_data.operand);
2255 try stream.print(", \"{}\")", .{std.zig.fmtEscapes(str)});
2255 try stream.print(", \"{f}\")", .{std.zig.fmtString(str)});
22562256 }
22572257
22582258 fn writeFunc(
......@@ -2594,11 +2594,7 @@ const Writer = struct {
25942594 },
25952595 }
25962596 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2597 try stream.print(" line({d}) column({d}) hash({})", .{
2598 decl.src_line,
2599 decl.src_column,
2600 std.fmt.fmtSliceHexLower(&src_hash),
2601 });
2597 try stream.print(" line({d}) column({d}) hash({x})", .{ decl.src_line, decl.src_column, &src_hash });
26022598
26032599 {
26042600 if (decl.type_body) |b| {
......@@ -2694,11 +2690,11 @@ const Writer = struct {
26942690 try stream.writeAll("load ");
26952691 try self.writeInstIndex(stream, ptr_inst);
26962692 },
2697 .decl_val => |str| try stream.print("decl_val \"{}\"", .{
2698 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),
2693 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{
2694 std.zig.fmtString(self.code.nullTerminatedString(str)),
26992695 }),
2700 .decl_ref => |str| try stream.print("decl_ref \"{}\"", .{
2701 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),
2696 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
2697 std.zig.fmtString(self.code.nullTerminatedString(str)),
27022698 }),
27032699 }
27042700 }
......@@ -2831,7 +2827,7 @@ const Writer = struct {
28312827 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
28322828 try self.writeInstRef(stream, extra.res_ty);
28332829 const import_path = self.code.nullTerminatedString(extra.path);
2834 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(import_path)});
2830 try stream.print(", \"{f}\") ", .{std.zig.fmtString(import_path)});
28352831 try self.writeSrcTok(stream, inst_data.src_tok);
28362832 }
28372833};
src/print_zoir.zig+3-3
......@@ -77,8 +77,8 @@ const PrintZon = struct {
7777 },
7878 .float_literal => |x| try pz.w.print("float({d})", .{x}),
7979 .char_literal => |x| try pz.w.print("char({d})", .{x}),
80 .enum_literal => |x| try pz.w.print("enum_literal({p})", .{std.zig.fmtId(x.get(zoir))}),
81 .string_literal => |x| try pz.w.print("str(\"{}\")", .{std.zig.fmtEscapes(x)}),
80 .enum_literal => |x| try pz.w.print("enum_literal({f})", .{std.zig.fmtIdP(x.get(zoir))}),
81 .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtString(x)}),
8282 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),
8383 .array_literal => |vals| {
8484 try pz.w.writeAll("array_literal({");
......@@ -97,7 +97,7 @@ const PrintZon = struct {
9797 pz.indent += 1;
9898 for (s.names, 0..s.vals.len) |name, idx| {
9999 try pz.newline();
100 try pz.w.print("[{p}] ", .{std.zig.fmtId(name.get(zoir))});
100 try pz.w.print("[{f}] ", .{std.zig.fmtIdP(name.get(zoir))});
101101 try pz.renderNode(s.vals.at(@intCast(idx)));
102102 try pz.w.writeByte(',');
103103 }
src/translate_c.zig+11-11
......@@ -357,7 +357,7 @@ fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.Fi
357357 var len: usize = undefined;
358358 const bytes_ptr = asm_string.getString_bytes_begin_size(&len);
359359
360 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});
360 const str = try std.fmt.allocPrint(c.arena, "\"{f}\"", .{std.zig.fmtString(bytes_ptr[0..len])});
361361 const str_node = try Tag.string_literal.create(c.arena, str);
362362
363363 const asm_node = try Tag.asm_simple.create(c.arena, str_node);
......@@ -2276,7 +2276,7 @@ fn transNarrowStringLiteral(
22762276 var len: usize = undefined;
22772277 const bytes_ptr = stmt.getString_bytes_begin_size(&len);
22782278
2279 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});
2279 const str = try std.fmt.allocPrint(c.arena, "\"{f}\"", .{std.zig.fmtString(bytes_ptr[0..len])});
22802280 const node = try Tag.string_literal.create(c.arena, str);
22812281 return maybeSuppressResult(c, result_used, node);
22822282}
......@@ -3338,7 +3338,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined
33383338
33393339fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
33403340 return Tag.char_literal.create(c.arena, if (narrow)
3341 try std.fmt.allocPrint(c.arena, "'{'}'", .{std.zig.fmtEscapes(&.{@as(u8, @intCast(val))})})
3341 try std.fmt.allocPrint(c.arena, "'{f}'", .{std.zig.fmtChar(&.{@as(u8, @intCast(val))})})
33423342 else
33433343 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
33443344}
......@@ -5832,7 +5832,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
58325832 num += c - 'A' + 10;
58335833 },
58345834 else => {
5835 i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
5835 i += std.fmt.printInt(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
58365836 num = 0;
58375837 if (c == '\\')
58385838 state = .escape
......@@ -5858,7 +5858,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
58585858 };
58595859 num += c - '0';
58605860 } else {
5861 i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
5861 i += std.fmt.printInt(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
58625862 num = 0;
58635863 count = 0;
58645864 if (c == '\\')
......@@ -5872,21 +5872,21 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
58725872 }
58735873 }
58745874 if (state == .hex or state == .octal)
5875 i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
5875 i += std.fmt.printInt(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
58765876 return bytes[0..i];
58775877}
58785878
5879/// non-ASCII characters (c > 127) are also treated as non-printable by fmtSliceEscapeLower.
5879/// non-ASCII characters (c > 127) are also treated as non-printable by ascii.hexEscape.
58805880/// If a C string literal or char literal in a macro is not valid UTF-8, we need to escape
58815881/// non-ASCII characters so that the Zig source we output will itself be UTF-8.
58825882fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 {
58835883 const zigified = try zigifyEscapeSequences(ctx, m);
58845884 if (std.unicode.utf8ValidateSlice(zigified)) return zigified;
58855885
5886 const formatter = std.fmt.fmtSliceEscapeLower(zigified);
5887 const encoded_size = @as(usize, @intCast(std.fmt.count("{s}", .{formatter})));
5886 const formatter = std.ascii.hexEscape(zigified, .lower);
5887 const encoded_size = @as(usize, @intCast(std.fmt.count("{fs}", .{formatter})));
58885888 const output = try ctx.arena.alloc(u8, encoded_size);
5889 return std.fmt.bufPrint(output, "{s}", .{formatter}) catch |err| switch (err) {
5889 return std.fmt.bufPrint(output, "{fs}", .{formatter}) catch |err| switch (err) {
58905890 error.NoSpaceLeft => unreachable,
58915891 else => |e| return e,
58925892 };
......@@ -5905,7 +5905,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
59055905 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
59065906 return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m));
59075907 } else {
5908 const str = try std.fmt.allocPrint(c.arena, "0x{s}", .{std.fmt.fmtSliceHexLower(slice[1 .. slice.len - 1])});
5908 const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
59095909 return Tag.integer_literal.create(c.arena, str);
59105910 }
59115911 },
test/behavior/union_with_members.zig+2-2
......@@ -10,8 +10,8 @@ const ET = union(enum) {
1010
1111 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
1212 return switch (a.*) {
13 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}),
14 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}),
13 ET.SINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}),
14 ET.UINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}),
1515 };
1616 }
1717};
test/link/elf.zig+2-2
......@@ -1316,7 +1316,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {
13161316 \\extern fn live_fn2() void;
13171317 \\pub fn main() void {
13181318 \\ const stdout = std.io.getStdOut();
1319 \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable;
1319 \\ stdout.deprecatedWriter().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable;
13201320 \\ live_fn2();
13211321 \\}
13221322 ,
......@@ -1358,7 +1358,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {
13581358 \\extern fn live_fn2() void;
13591359 \\pub fn main() void {
13601360 \\ const stdout = std.io.getStdOut();
1361 \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable;
1361 \\ stdout.deprecatedWriter().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable;
13621362 \\ live_fn2();
13631363 \\}
13641364 ,
test/standalone/run_output_paths/create_file.zig+1-1
......@@ -10,7 +10,7 @@ pub fn main() !void {
1010 dir_name, .{});
1111 const file_name = args.next().?;
1212 const file = try dir.createFile(file_name, .{});
13 try file.writer().print(
13 try file.deprecatedWriter().print(
1414 \\{s}
1515 \\{s}
1616 \\Hello, world!
test/standalone/simple/brace_expansion.zig+1-1
......@@ -228,7 +228,7 @@ pub fn main() !void {
228228 const stdin_file = io.getStdIn();
229229 const stdout_file = io.getStdOut();
230230
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
231 const stdin = try stdin_file.deprecatedReader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232232 defer global_allocator.free(stdin);
233233
234234 var result_buf = ArrayList(u8).init(global_allocator);
test/standalone/windows_argv/fuzz.zig+1-1
......@@ -58,7 +58,7 @@ pub fn main() !void {
5858 std.debug.print(">>> found discrepancy <<<\n", .{});
5959 const cmd_line_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, cmd_line_w);
6060 defer allocator.free(cmd_line_wtf8);
61 std.debug.print("\"{}\"\n\n", .{std.zig.fmtEscapes(cmd_line_wtf8)});
61 std.debug.print("\"{f}\"\n\n", .{std.zig.fmtString(cmd_line_wtf8)});
6262
6363 errors += 1;
6464 }
test/standalone/windows_argv/lib.zig+6-6
......@@ -27,8 +27,8 @@ fn testArgv(expected_args: []const [*:0]const u16) !void {
2727 wtf8_buf.clearRetainingCapacity();
2828 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(expected_arg));
2929 if (!std.mem.eql(u8, wtf8_buf.items, arg_wtf8)) {
30 std.debug.print("{}: expected: \"{}\"\n", .{ i, std.zig.fmtEscapes(wtf8_buf.items) });
31 std.debug.print("{}: actual: \"{}\"\n", .{ i, std.zig.fmtEscapes(arg_wtf8) });
30 std.debug.print("{}: expected: \"{f}\"\n", .{ i, std.zig.fmtString(wtf8_buf.items) });
31 std.debug.print("{}: actual: \"{f}\"\n", .{ i, std.zig.fmtString(arg_wtf8) });
3232 eql = false;
3333 }
3434 }
......@@ -36,22 +36,22 @@ fn testArgv(expected_args: []const [*:0]const u16) !void {
3636 for (expected_args[min_len..], min_len..) |arg, i| {
3737 wtf8_buf.clearRetainingCapacity();
3838 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(arg));
39 std.debug.print("{}: expected: \"{}\"\n", .{ i, std.zig.fmtEscapes(wtf8_buf.items) });
39 std.debug.print("{}: expected: \"{f}\"\n", .{ i, std.zig.fmtString(wtf8_buf.items) });
4040 }
4141 for (args[min_len..], min_len..) |arg, i| {
42 std.debug.print("{}: actual: \"{}\"\n", .{ i, std.zig.fmtEscapes(arg) });
42 std.debug.print("{}: actual: \"{f}\"\n", .{ i, std.zig.fmtString(arg) });
4343 }
4444 const peb = std.os.windows.peb();
4545 const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer);
4646 wtf8_buf.clearRetainingCapacity();
4747 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(lpCmdLine));
48 std.debug.print("command line: \"{}\"\n", .{std.zig.fmtEscapes(wtf8_buf.items)});
48 std.debug.print("command line: \"{f}\"\n", .{std.zig.fmtString(wtf8_buf.items)});
4949 std.debug.print("expected argv:\n", .{});
5050 std.debug.print("&.{{\n", .{});
5151 for (expected_args) |arg| {
5252 wtf8_buf.clearRetainingCapacity();
5353 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(arg));
54 std.debug.print(" \"{}\",\n", .{std.zig.fmtEscapes(wtf8_buf.items)});
54 std.debug.print(" \"{f}\",\n", .{std.zig.fmtString(wtf8_buf.items)});
5555 }
5656 std.debug.print("}}\n", .{});
5757 return error.ArgvMismatch;
test/tests.zig+1-1
......@@ -2753,7 +2753,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
27532753
27542754 run.addArg(b.graph.zig_exe);
27552755 run.addFileArg(b.path("test/incremental/").path(b, entry.path));
2756 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });
2756 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
27572757
27582758 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
27592759