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...@@ -436,7 +436,6 @@ set(ZIG_STAGE2_SOURCES
436 lib/std/elf.zig436 lib/std/elf.zig
437 lib/std/fifo.zig437 lib/std/fifo.zig
438 lib/std/fmt.zig438 lib/std/fmt.zig
439 lib/std/fmt/format_float.zig
440 lib/std/fmt/parse_float.zig439 lib/std/fmt/parse_float.zig
441 lib/std/fs.zig440 lib/std/fs.zig
442 lib/std/fs/AtomicFile.zig441 lib/std/fs/AtomicFile.zig
build.zig+3-3
...@@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void {...@@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void {
279279
280 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);280 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
281 if (zig_version.order(ancestor_ver) != .gt) {281 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 });
283 std.process.exit(1);283 std.process.exit(1);
284 }284 }
285285
...@@ -1449,7 +1449,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {...@@ -1449,7 +1449,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
1449 }1449 }
14501450
1451 var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {1451 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}", .{
1453 b.build_root, @errorName(err),1453 b.build_root, @errorName(err),
1454 });1454 });
1455 };1455 };
...@@ -1470,7 +1470,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {...@@ -1470,7 +1470,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
1470 // in a temporary directory1470 // in a temporary directory
1471 "--cache-root", b.cache_root.path orelse ".",1471 "--cache-root", b.cache_root.path orelse ".",
1472 });1472 });
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}) });
1474 cmd.addArgs(&.{"-i"});1474 cmd.addArgs(&.{"-i"});
1475 cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name})));1475 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...@@ -1432,7 +1432,7 @@ fn getFileContents(comp: *Compilation, path: []const u8, limit: ?u32) ![]const u
1432 defer buf.deinit();1432 defer buf.deinit();
14331433
1434 const max = limit orelse std.math.maxInt(u32);1434 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) {
1436 error.StreamTooLong => if (limit == null) return e,1436 error.StreamTooLong => if (limit == null) return e,
1437 else => return e,1437 else => return e,
1438 };1438 };
lib/compiler/aro/aro/Diagnostics.zig+8-18
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;
2const Allocator = mem.Allocator;3const Allocator = mem.Allocator;
3const mem = std.mem;4const mem = std.mem;
4const Source = @import("Source.zig");5const Source = @import("Source.zig");
...@@ -443,18 +444,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {...@@ -443,18 +444,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
443 printRt(m, prop.msg, .{"{s}"}, .{&str});444 printRt(m, prop.msg, .{"{s}"}, .{&str});
444 } else {445 } else {
445 var buf: [3]u8 = undefined;446 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;
447 printRt(m, prop.msg, .{"{s}"}, .{str});448 printRt(m, prop.msg, .{"{s}"}, .{str});
448 }449 }
449 },450 },
450 .normalized => {451 .normalized => {
451 const f = struct {452 const f = struct {
452 pub fn f(453 pub fn f(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
453 bytes: []const u8,
454 comptime _: []const u8,
455 _: std.fmt.FormatOptions,
456 writer: anytype,
457 ) !void {
458 var it: std.unicode.Utf8Iterator = .{454 var it: std.unicode.Utf8Iterator = .{
459 .bytes = bytes,455 .bytes = bytes,
460 .i = 0,456 .i = 0,
...@@ -464,22 +460,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {...@@ -464,22 +460,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
464 try writer.writeByte(@intCast(codepoint));460 try writer.writeByte(@intCast(codepoint));
465 } else if (codepoint < 0xFFFF) {461 } else if (codepoint < 0xFFFF) {
466 try writer.writeAll("\\u");462 try writer.writeAll("\\u");
467 try std.fmt.formatInt(codepoint, 16, .upper, .{463 try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 4 });
468 .fill = '0',
469 .width = 4,
470 }, writer);
471 } else {464 } else {
472 try writer.writeAll("\\U");465 try writer.writeAll("\\U");
473 try std.fmt.formatInt(codepoint, 16, .upper, .{466 try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 8 });
474 .fill = '0',
475 .width = 8,
476 }, writer);
477 }467 }
478 }468 }
479 }469 }
480 }.f;470 }.f;
481 printRt(m, prop.msg, .{"{s}"}, .{471 printRt(m, prop.msg, .{"{f}"}, .{
482 std.fmt.Formatter(f){ .data = msg.extra.normalized },472 std.fmt.Formatter([]const u8, f){ .data = msg.extra.normalized },
483 });473 });
484 },474 },
485 .none, .offset => m.write(prop.msg),475 .none, .offset => m.write(prop.msg),
...@@ -541,7 +531,7 @@ const MsgWriter = struct {...@@ -541,7 +531,7 @@ const MsgWriter = struct {
541 fn init(config: std.io.tty.Config) MsgWriter {531 fn init(config: std.io.tty.Config) MsgWriter {
542 std.debug.lockStdErr();532 std.debug.lockStdErr();
543 return .{533 return .{
544 .w = std.io.bufferedWriter(std.fs.File.stderr().writer()),534 .w = std.io.bufferedWriter(std.fs.File.stderr().deprecatedWriter()),
545 .config = config,535 .config = config,
546 };536 };
547 }537 }
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_...@@ -591,7 +591,7 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_
591 var macro_buf = std.ArrayList(u8).init(d.comp.gpa);591 var macro_buf = std.ArrayList(u8).init(d.comp.gpa);
592 defer macro_buf.deinit();592 defer macro_buf.deinit();
593593
594 const std_out = std.fs.File.stdout().writer();594 const std_out = std.fs.File.stdout().deprecatedWriter();
595 if (try parseArgs(d, std_out, macro_buf.writer(), args)) return;595 if (try parseArgs(d, std_out, macro_buf.writer(), args)) return;
596596
597 const linking = !(d.only_preprocess or d.only_syntax or d.only_compile or d.only_preprocess_and_compile);597 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(...@@ -689,7 +689,7 @@ fn processSource(
689 std.fs.File.stdout();689 std.fs.File.stdout();
690 defer if (d.output_name != null) file.close();690 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
694 pp.prettyPrintTokens(buf_w.writer(), dump_mode) catch |er|694 pp.prettyPrintTokens(buf_w.writer(), dump_mode) catch |er|
695 return d.fatal("unable to write result: {s}", .{errorDescription(er)});695 return d.fatal("unable to write result: {s}", .{errorDescription(er)});
...@@ -705,7 +705,7 @@ fn processSource(...@@ -705,7 +705,7 @@ fn processSource(
705705
706 if (d.verbose_ast) {706 if (d.verbose_ast) {
707 const stdout = std.fs.File.stdout();707 const stdout = std.fs.File.stdout();
708 var buf_writer = std.io.bufferedWriter(stdout.writer());708 var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter());
709 tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {};709 tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {};
710 buf_writer.flush() catch {};710 buf_writer.flush() catch {};
711 }711 }
...@@ -735,7 +735,7 @@ fn processSource(...@@ -735,7 +735,7 @@ fn processSource(
735735
736 if (d.verbose_ir) {736 if (d.verbose_ir) {
737 const stdout = std.fs.File.stdout();737 const stdout = std.fs.File.stdout();
738 var buf_writer = std.io.bufferedWriter(stdout.writer());738 var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter());
739 ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {};739 ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {};
740 buf_writer.flush() catch {};740 buf_writer.flush() catch {};
741 }741 }
...@@ -806,10 +806,10 @@ fn processSource(...@@ -806,10 +806,10 @@ fn processSource(
806}806}
807807
808fn dumpLinkerArgs(items: []const []const u8) !void {808fn dumpLinkerArgs(items: []const []const u8) !void {
809 const stdout = std.fs.File.stdout().writer();809 const stdout = std.fs.File.stdout().deprecatedWriter();
810 for (items, 0..) |item, i| {810 for (items, 0..) |item, i| {
811 if (i > 0) try stdout.writeByte(' ');811 if (i > 0) try stdout.writeByte(' ');
812 try stdout.print("\"{}\"", .{std.zig.fmtEscapes(item)});812 try stdout.print("\"{f}\"", .{std.zig.fmtString(item)});
813 }813 }
814 try stdout.writeByte('\n');814 try stdout.writeByte('\n');
815}815}
lib/compiler/aro/aro/Parser.zig+5-5
...@@ -500,8 +500,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_...@@ -500,8 +500,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_
500500
501 const w = p.strings.writer();501 const w = p.strings.writer();
502 const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes;502 const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes;
503 try w.print("call to '{s}' declared with attribute error: {}", .{503 try w.print("call to '{s}' declared with attribute error: {f}", .{
504 p.tokSlice(@"error".__name_tok), std.zig.fmtEscapes(msg_str),504 p.tokSlice(@"error".__name_tok), std.zig.fmtString(msg_str),
505 });505 });
506 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);506 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
507 try p.errStr(.error_attribute, usage_tok, str);507 try p.errStr(.error_attribute, usage_tok, str);
...@@ -512,8 +512,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_...@@ -512,8 +512,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_
512512
513 const w = p.strings.writer();513 const w = p.strings.writer();
514 const msg_str = p.comp.interner.get(warning.msg.ref()).bytes;514 const msg_str = p.comp.interner.get(warning.msg.ref()).bytes;
515 try w.print("call to '{s}' declared with attribute warning: {}", .{515 try w.print("call to '{s}' declared with attribute warning: {f}", .{
516 p.tokSlice(warning.__name_tok), std.zig.fmtEscapes(msg_str),516 p.tokSlice(warning.__name_tok), std.zig.fmtString(msg_str),
517 });517 });
518 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);518 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
519 try p.errStr(.warning_attribute, usage_tok, str);519 try p.errStr(.warning_attribute, usage_tok, str);
...@@ -542,7 +542,7 @@ fn errDeprecated(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, msg: ?Valu...@@ -542,7 +542,7 @@ fn errDeprecated(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, msg: ?Valu
542 try w.writeAll(reason);542 try w.writeAll(reason);
543 if (msg) |m| {543 if (msg) |m| {
544 const str = p.comp.interner.get(m.ref()).bytes;544 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)});
546 }546 }
547 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);547 const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
548 return p.errStr(tag, tok_i, str);548 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:...@@ -811,7 +811,7 @@ fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args:
811 const source = pp.comp.getSource(raw.source);811 const source = pp.comp.getSource(raw.source);
812 const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start });812 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();
815 var buf_writer = std.io.bufferedWriter(stderr);815 var buf_writer = std.io.bufferedWriter(stderr);
816 const writer = buf_writer.writer();816 const writer = buf_writer.writer();
817 defer buf_writer.flush() catch {};817 defer buf_writer.flush() catch {};
...@@ -3262,7 +3262,8 @@ fn printLinemarker(...@@ -3262,7 +3262,8 @@ fn printLinemarker(
3262 // containing the same bytes as the input regardless of encoding.3262 // containing the same bytes as the input regardless of encoding.
3263 else => {3263 else => {
3264 try w.writeAll("\\x");3264 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});
3266 },3267 },
3267 };3268 };
3268 try w.writeByte('"');3269 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...@@ -982,7 +982,7 @@ pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: any
982 const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];982 const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];
983 try w.writeByte('"');983 try w.writeByte('"');
984 switch (size) {984 switch (size) {
985 .@"1" => try w.print("{}", .{std.zig.fmtEscapes(without_null)}),985 .@"1" => try w.print("{f}", .{std.zig.fmtString(without_null)}),
986 .@"2" => {986 .@"2" => {
987 var items: [2]u16 = undefined;987 var items: [2]u16 = undefined;
988 var i: usize = 0;988 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,...@@ -171,7 +171,7 @@ pub fn addRelocation(elf: *Elf, name: []const u8, section_kind: Object.Section,
171/// strtab171/// strtab
172/// section headers172/// section headers
173pub fn finish(elf: *Elf, file: std.fs.File) !void {173pub 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());
175 const w = buf_writer.writer();175 const w = buf_writer.writer();
176176
177 var num_sections: std.elf.Elf64_Half = additional_sections;177 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 {...@@ -849,7 +849,7 @@ const Context = struct {
849 fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {849 fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
850 if (std.zig.primitives.isPrimitive(bytes))850 if (std.zig.primitives.isPrimitive(bytes))
851 return c.addTokenFmt(.identifier, "@\"{s}\"", .{bytes});851 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 })});
853 }853 }
854854
855 fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {855 fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
...@@ -1201,7 +1201,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1201,7 +1201,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12011201
1202 const compile_error_tok = try c.addToken(.builtin, "@compileError");1202 const compile_error_tok = try c.addToken(.builtin, "@compileError");
1203 _ = try c.addToken(.l_paren, "(");1203 _ = 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)});
1205 const err_msg = try c.addNode(.{1205 const err_msg = try c.addNode(.{
1206 .tag = .string_literal,1206 .tag = .string_literal,
1207 .main_token = err_msg_tok,1207 .main_token = err_msg_tok,
...@@ -2116,7 +2116,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {...@@ -2116,7 +2116,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
2116 defer c.gpa.free(members);2116 defer c.gpa.free(members);
21172117
2118 for (payload.fields, 0..) |field, i| {2118 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 })});
2120 _ = try c.addToken(.colon, ":");2120 _ = try c.addToken(.colon, ":");
2121 const type_expr = try renderNode(c, field.type);2121 const type_expr = try renderNode(c, field.type);
21222122
...@@ -2205,7 +2205,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI...@@ -2205,7 +2205,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
2205 .main_token = try c.addToken(.period, "."),2205 .main_token = try c.addToken(.period, "."),
2206 .data = .{ .node_and_token = .{2206 .data = .{ .node_and_token = .{
2207 lhs,2207 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 })}),
2209 } },2209 } },
2210 });2210 });
2211}2211}
...@@ -2681,7 +2681,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {...@@ -2681,7 +2681,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
2681 _ = try c.addToken(.l_paren, "(");2681 _ = try c.addToken(.l_paren, "(");
2682 const res = try c.addNode(.{2682 const res = try c.addNode(.{
2683 .tag = .string_literal,2683 .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)}),
2685 .data = undefined,2685 .data = undefined,
2686 });2686 });
2687 _ = try c.addToken(.r_paren, ")");2687 _ = try c.addToken(.r_paren, ")");
...@@ -2765,7 +2765,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2765,7 +2765,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2765 _ = try c.addToken(.l_paren, "(");2765 _ = try c.addToken(.l_paren, "(");
2766 const res = try c.addNode(.{2766 const res = try c.addNode(.{
2767 .tag = .string_literal,2767 .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)}),
2769 .data = undefined,2769 .data = undefined,
2770 });2770 });
2771 _ = try c.addToken(.r_paren, ")");2771 _ = try c.addToken(.r_paren, ")");
lib/compiler/build_runner.zig+29-29
...@@ -365,7 +365,7 @@ pub fn main() !void {...@@ -365,7 +365,7 @@ pub fn main() !void {
365 .data = buffer.items,365 .data = buffer.items,
366 .flags = .{ .exclusive = true },366 .flags = .{ .exclusive = true },
367 }) catch |err| {367 }) catch |err| {
368 fatal("unable to write configuration results to '{}{s}': {s}", .{368 fatal("unable to write configuration results to '{f}{s}': {s}", .{
369 local_cache_directory, tmp_sub_path, @errorName(err),369 local_cache_directory, tmp_sub_path, @errorName(err),
370 });370 });
371 };371 };
...@@ -378,7 +378,7 @@ pub fn main() !void {...@@ -378,7 +378,7 @@ pub fn main() !void {
378378
379 validateSystemLibraryOptions(builder);379 validateSystemLibraryOptions(builder);
380380
381 const stdout_writer = std.fs.File.stdout().writer();381 const stdout_writer = std.fs.File.stdout().deprecatedWriter();
382382
383 if (help_menu)383 if (help_menu)
384 return usage(builder, stdout_writer);384 return usage(builder, stdout_writer);
...@@ -704,14 +704,14 @@ fn runStepNames(...@@ -704,14 +704,14 @@ fn runStepNames(
704 ttyconf.setColor(stderr, .cyan) catch {};704 ttyconf.setColor(stderr, .cyan) catch {};
705 stderr.writeAll("Build Summary:") catch {};705 stderr.writeAll("Build Summary:") catch {};
706 ttyconf.setColor(stderr, .reset) catch {};706 ttyconf.setColor(stderr, .reset) catch {};
707 stderr.writer().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};707 stderr.deprecatedWriter().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
708 if (skipped_count > 0) stderr.writer().print("; {d} skipped", .{skipped_count}) catch {};708 if (skipped_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{skipped_count}) catch {};
709 if (failure_count > 0) stderr.writer().print("; {d} failed", .{failure_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 {};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.writer().print("; {d} skipped", .{test_skip_count}) catch {};712 if (test_skip_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{test_skip_count}) catch {};
713 if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};713 if (test_fail_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{test_fail_count}) catch {};
714 if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};714 if (test_leak_count > 0) stderr.deprecatedWriter().print("; {d} leaked", .{test_leak_count}) catch {};
715715
716 stderr.writeAll("\n") catch {};716 stderr.writeAll("\n") catch {};
717717
...@@ -820,10 +820,10 @@ fn printStepStatus(...@@ -820,10 +820,10 @@ fn printStepStatus(
820 try stderr.writeAll(" cached");820 try stderr.writeAll(" cached");
821 } else if (s.test_results.test_count > 0) {821 } else if (s.test_results.test_count > 0) {
822 const pass_count = s.test_results.passCount();822 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});
824 if (s.test_results.skip_count > 0) {824 if (s.test_results.skip_count > 0) {
825 try ttyconf.setColor(stderr, .yellow);825 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});
827 }827 }
828 } else {828 } else {
829 try stderr.writeAll(" success");829 try stderr.writeAll(" success");
...@@ -832,15 +832,15 @@ fn printStepStatus(...@@ -832,15 +832,15 @@ fn printStepStatus(
832 if (s.result_duration_ns) |ns| {832 if (s.result_duration_ns) |ns| {
833 try ttyconf.setColor(stderr, .dim);833 try ttyconf.setColor(stderr, .dim);
834 if (ns >= std.time.ns_per_min) {834 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});
836 } else if (ns >= std.time.ns_per_s) {836 } 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});
838 } else if (ns >= std.time.ns_per_ms) {838 } 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});
840 } else if (ns >= std.time.ns_per_us) {840 } 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});
842 } else {842 } else {
843 try stderr.writer().print(" {d}ns", .{ns});843 try stderr.deprecatedWriter().print(" {d}ns", .{ns});
844 }844 }
845 try ttyconf.setColor(stderr, .reset);845 try ttyconf.setColor(stderr, .reset);
846 }846 }
...@@ -848,13 +848,13 @@ fn printStepStatus(...@@ -848,13 +848,13 @@ fn printStepStatus(
848 const rss = s.result_peak_rss;848 const rss = s.result_peak_rss;
849 try ttyconf.setColor(stderr, .dim);849 try ttyconf.setColor(stderr, .dim);
850 if (rss >= 1000_000_000) {850 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});
852 } else if (rss >= 1000_000) {852 } 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});
854 } else if (rss >= 1000) {854 } else if (rss >= 1000) {
855 try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000});855 try stderr.deprecatedWriter().print(" MaxRSS:{d}K", .{rss / 1000});
856 } else {856 } else {
857 try stderr.writer().print(" MaxRSS:{d}B", .{rss});857 try stderr.deprecatedWriter().print(" MaxRSS:{d}B", .{rss});
858 }858 }
859 try ttyconf.setColor(stderr, .reset);859 try ttyconf.setColor(stderr, .reset);
860 }860 }
...@@ -866,7 +866,7 @@ fn printStepStatus(...@@ -866,7 +866,7 @@ fn printStepStatus(
866 if (skip == .skipped_oom) {866 if (skip == .skipped_oom) {
867 try stderr.writeAll(" (not enough memory)");867 try stderr.writeAll(" (not enough memory)");
868 try ttyconf.setColor(stderr, .dim);868 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 });
870 try ttyconf.setColor(stderr, .yellow);870 try ttyconf.setColor(stderr, .yellow);
871 }871 }
872 try stderr.writeAll("\n");872 try stderr.writeAll("\n");
...@@ -883,18 +883,18 @@ fn printStepFailure(...@@ -883,18 +883,18 @@ fn printStepFailure(
883) !void {883) !void {
884 if (s.result_error_bundle.errorMessageCount() > 0) {884 if (s.result_error_bundle.errorMessageCount() > 0) {
885 try ttyconf.setColor(stderr, .red);885 try ttyconf.setColor(stderr, .red);
886 try stderr.writer().print(" {d} errors\n", .{886 try stderr.deprecatedWriter().print(" {d} errors\n", .{
887 s.result_error_bundle.errorMessageCount(),887 s.result_error_bundle.errorMessageCount(),
888 });888 });
889 try ttyconf.setColor(stderr, .reset);889 try ttyconf.setColor(stderr, .reset);
890 } else if (!s.test_results.isSuccess()) {890 } else if (!s.test_results.isSuccess()) {
891 try stderr.writer().print(" {d}/{d} passed", .{891 try stderr.deprecatedWriter().print(" {d}/{d} passed", .{
892 s.test_results.passCount(), s.test_results.test_count,892 s.test_results.passCount(), s.test_results.test_count,
893 });893 });
894 if (s.test_results.fail_count > 0) {894 if (s.test_results.fail_count > 0) {
895 try stderr.writeAll(", ");895 try stderr.writeAll(", ");
896 try ttyconf.setColor(stderr, .red);896 try ttyconf.setColor(stderr, .red);
897 try stderr.writer().print("{d} failed", .{897 try stderr.deprecatedWriter().print("{d} failed", .{
898 s.test_results.fail_count,898 s.test_results.fail_count,
899 });899 });
900 try ttyconf.setColor(stderr, .reset);900 try ttyconf.setColor(stderr, .reset);
...@@ -902,7 +902,7 @@ fn printStepFailure(...@@ -902,7 +902,7 @@ fn printStepFailure(
902 if (s.test_results.skip_count > 0) {902 if (s.test_results.skip_count > 0) {
903 try stderr.writeAll(", ");903 try stderr.writeAll(", ");
904 try ttyconf.setColor(stderr, .yellow);904 try ttyconf.setColor(stderr, .yellow);
905 try stderr.writer().print("{d} skipped", .{905 try stderr.deprecatedWriter().print("{d} skipped", .{
906 s.test_results.skip_count,906 s.test_results.skip_count,
907 });907 });
908 try ttyconf.setColor(stderr, .reset);908 try ttyconf.setColor(stderr, .reset);
...@@ -910,7 +910,7 @@ fn printStepFailure(...@@ -910,7 +910,7 @@ fn printStepFailure(
910 if (s.test_results.leak_count > 0) {910 if (s.test_results.leak_count > 0) {
911 try stderr.writeAll(", ");911 try stderr.writeAll(", ");
912 try ttyconf.setColor(stderr, .red);912 try ttyconf.setColor(stderr, .red);
913 try stderr.writer().print("{d} leaked", .{913 try stderr.deprecatedWriter().print("{d} leaked", .{
914 s.test_results.leak_count,914 s.test_results.leak_count,
915 });915 });
916 try ttyconf.setColor(stderr, .reset);916 try ttyconf.setColor(stderr, .reset);
...@@ -992,7 +992,7 @@ fn printTreeStep(...@@ -992,7 +992,7 @@ fn printTreeStep(
992 if (s.dependencies.items.len == 0) {992 if (s.dependencies.items.len == 0) {
993 try stderr.writeAll(" (reused)\n");993 try stderr.writeAll(" (reused)\n");
994 } else {994 } else {
995 try stderr.writer().print(" (+{d} more reused dependencies)\n", .{995 try stderr.deprecatedWriter().print(" (+{d} more reused dependencies)\n", .{
996 s.dependencies.items.len,996 s.dependencies.items.len,
997 });997 });
998 }998 }
...@@ -1209,7 +1209,7 @@ pub fn printErrorMessages(...@@ -1209,7 +1209,7 @@ pub fn printErrorMessages(
1209 var indent: usize = 0;1209 var indent: usize = 0;
1210 while (step_stack.pop()) |s| : (indent += 1) {1210 while (step_stack.pop()) |s| : (indent += 1) {
1211 if (indent > 0) {1211 if (indent > 0) {
1212 try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3);1212 try stderr.deprecatedWriter().writeByteNTimes(' ', (indent - 1) * 3);
1213 try printChildNodePrefix(stderr, ttyconf);1213 try printChildNodePrefix(stderr, ttyconf);
1214 }1214 }
12151215
...@@ -1231,7 +1231,7 @@ pub fn printErrorMessages(...@@ -1231,7 +1231,7 @@ pub fn printErrorMessages(
1231 }1231 }
12321232
1233 if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {1233 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());
1235 }1235 }
12361236
1237 for (failing_step.result_error_msgs.items) |msg| {1237 for (failing_step.result_error_msgs.items) |msg| {
lib/compiler/libc.zig+3-3
...@@ -40,7 +40,7 @@ pub fn main() !void {...@@ -40,7 +40,7 @@ pub fn main() !void {
40 const arg = args[i];40 const arg = args[i];
41 if (mem.startsWith(u8, arg, "-")) {41 if (mem.startsWith(u8, arg, "-")) {
42 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {42 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();
44 try stdout.writeAll(usage_libc);44 try stdout.writeAll(usage_libc);
45 return std.process.cleanExit();45 return std.process.cleanExit();
46 } else if (mem.eql(u8, arg, "-target")) {46 } else if (mem.eql(u8, arg, "-target")) {
...@@ -97,7 +97,7 @@ pub fn main() !void {...@@ -97,7 +97,7 @@ pub fn main() !void {
97 fatal("no include dirs detected for target {s}", .{zig_target});97 fatal("no include dirs detected for target {s}", .{zig_target});
98 }98 }
9999
100 var bw = std.io.bufferedWriter(std.fs.File.stdout().writer());100 var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
101 var writer = bw.writer();101 var writer = bw.writer();
102 for (libc_dirs.libc_include_dir_list) |include_dir| {102 for (libc_dirs.libc_include_dir_list) |include_dir| {
103 try writer.writeAll(include_dir);103 try writer.writeAll(include_dir);
...@@ -125,7 +125,7 @@ pub fn main() !void {...@@ -125,7 +125,7 @@ pub fn main() !void {
125 };125 };
126 defer libc.deinit(gpa);126 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());
129 try libc.render(bw.writer());129 try libc.render(bw.writer());
130 try bw.flush();130 try bw.flush();
131 }131 }
lib/compiler/objcopy.zig+3-3
...@@ -635,11 +635,11 @@ const HexWriter = struct {...@@ -635,11 +635,11 @@ const HexWriter = struct {
635 const payload_bytes = self.getPayloadBytes();635 const payload_bytes = self.getPayloadBytes();
636 assert(payload_bytes.len <= MAX_PAYLOAD_LEN);636 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, .{
639 @as(u8, @intCast(payload_bytes.len)),639 @as(u8, @intCast(payload_bytes.len)),
640 self.address,640 self.address,
641 @intFromEnum(self.payload),641 @intFromEnum(self.payload),
642 std.fmt.fmtSliceHexUpper(payload_bytes),642 payload_bytes,
643 self.checksum(),643 self.checksum(),
644 });644 });
645 try file.writeAll(line);645 try file.writeAll(line);
...@@ -1495,7 +1495,7 @@ const ElfFileHelper = struct {...@@ -1495,7 +1495,7 @@ const ElfFileHelper = struct {
1495 if (size < prefix.len) return null;1495 if (size < prefix.len) return null;
14961496
1497 try in_file.seekTo(offset);1497 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
1500 // allocate as large as decompressed data. if the compression doesn't fit, keep the data uncompressed.1500 // allocate as large as decompressed data. if the compression doesn't fit, keep the data uncompressed.
1501 const compressed_data = try allocator.alignedAlloc(u8, .@"8", @intCast(size));1501 const compressed_data = try allocator.alignedAlloc(u8, .@"8", @intCast(size));
lib/compiler/reduce.zig+1-1
...@@ -68,7 +68,7 @@ pub fn main() !void {...@@ -68,7 +68,7 @@ pub fn main() !void {
68 const arg = args[i];68 const arg = args[i];
69 if (mem.startsWith(u8, arg, "-")) {69 if (mem.startsWith(u8, arg, "-")) {
70 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {70 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();
72 try stdout.writeAll(usage);72 try stdout.writeAll(usage);
73 return std.process.cleanExit();73 return std.process.cleanExit();
74 } else if (mem.eql(u8, arg, "--")) {74 } else if (mem.eql(u8, arg, "--")) {
lib/compiler/resinator/cli.zig+1-1
...@@ -127,7 +127,7 @@ pub const Diagnostics = struct {...@@ -127,7 +127,7 @@ pub const Diagnostics = struct {
127 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.io.tty.Config) void {127 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.io.tty.Config) void {
128 std.debug.lockStdErr();128 std.debug.lockStdErr();
129 defer std.debug.unlockStdErr();129 defer std.debug.unlockStdErr();
130 const stderr = std.fs.File.stderr().writer();130 const stderr = std.fs.File.stderr().deprecatedWriter();
131 self.renderToWriter(args, stderr, config) catch return;131 self.renderToWriter(args, stderr, config) catch return;
132 }132 }
133133
lib/compiler/resinator/compile.zig+9-9
...@@ -570,7 +570,7 @@ pub const Compiler = struct {...@@ -570,7 +570,7 @@ pub const Compiler = struct {
570 switch (predefined_type) {570 switch (predefined_type) {
571 .GROUP_ICON, .GROUP_CURSOR => {571 .GROUP_ICON, .GROUP_CURSOR => {
572 // Check for animated icon first572 // Check for animated icon first
573 if (ani.isAnimatedIcon(file.reader())) {573 if (ani.isAnimatedIcon(file.deprecatedReader())) {
574 // Animated icons are just put into the resource unmodified,574 // Animated icons are just put into the resource unmodified,
575 // and the resource type changes to ANIICON/ANICURSOR575 // and the resource type changes to ANIICON/ANICURSOR
576576
...@@ -586,14 +586,14 @@ pub const Compiler = struct {...@@ -586,14 +586,14 @@ pub const Compiler = struct {
586586
587 try header.write(writer, self.errContext(node.id));587 try header.write(writer, self.errContext(node.id));
588 try file.seekTo(0);588 try file.seekTo(0);
589 try writeResourceData(writer, file.reader(), header.data_size);589 try writeResourceData(writer, file.deprecatedReader(), header.data_size);
590 return;590 return;
591 }591 }
592592
593 // isAnimatedIcon moved the file cursor so reset to the start593 // isAnimatedIcon moved the file cursor so reset to the start
594 try file.seekTo(0);594 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) {
597 error.OutOfMemory => |e| return e,597 error.OutOfMemory => |e| return e,
598 else => |e| {598 else => |e| {
599 return self.iconReadError(599 return self.iconReadError(
...@@ -672,7 +672,7 @@ pub const Compiler = struct {...@@ -672,7 +672,7 @@ pub const Compiler = struct {
672 }672 }
673673
674 try file.seekTo(entry.data_offset_from_start_of_file);674 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 {
676 return self.iconReadError(676 return self.iconReadError(
677 error.UnexpectedEOF,677 error.UnexpectedEOF,
678 filename_utf8,678 filename_utf8,
...@@ -803,7 +803,7 @@ pub const Compiler = struct {...@@ -803,7 +803,7 @@ pub const Compiler = struct {
803 }803 }
804804
805 try file.seekTo(entry.data_offset_from_start_of_file);805 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);
807 try writeDataPadding(writer, full_data_size);807 try writeDataPadding(writer, full_data_size);
808808
809 if (self.state.icon_id == std.math.maxInt(u16)) {809 if (self.state.icon_id == std.math.maxInt(u16)) {
...@@ -859,7 +859,7 @@ pub const Compiler = struct {...@@ -859,7 +859,7 @@ pub const Compiler = struct {
859 header.applyMemoryFlags(node.common_resource_attributes, self.source);859 header.applyMemoryFlags(node.common_resource_attributes, self.source);
860 const file_size = try file.getEndPos();860 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| {
863 const filename_string_index = try self.diagnostics.putString(filename_utf8);863 const filename_string_index = try self.diagnostics.putString(filename_utf8);
864 return self.addErrorDetailsAndFail(.{864 return self.addErrorDetailsAndFail(.{
865 .err = .bmp_read_error,865 .err = .bmp_read_error,
...@@ -922,7 +922,7 @@ pub const Compiler = struct {...@@ -922,7 +922,7 @@ pub const Compiler = struct {
922 header.data_size = bmp_bytes_to_write;922 header.data_size = bmp_bytes_to_write;
923 try header.write(writer, self.errContext(node.id));923 try header.write(writer, self.errContext(node.id));
924 try file.seekTo(bmp.file_header_len);924 try file.seekTo(bmp.file_header_len);
925 const file_reader = file.reader();925 const file_reader = file.deprecatedReader();
926 try writeResourceDataNoPadding(writer, file_reader, bitmap_info.dib_header_size);926 try writeResourceDataNoPadding(writer, file_reader, bitmap_info.dib_header_size);
927 if (bitmap_info.getBitmasksByteLen() > 0) {927 if (bitmap_info.getBitmasksByteLen() > 0) {
928 try writeResourceDataNoPadding(writer, file_reader, bitmap_info.getBitmasksByteLen());928 try writeResourceDataNoPadding(writer, file_reader, bitmap_info.getBitmasksByteLen());
...@@ -968,7 +968,7 @@ pub const Compiler = struct {...@@ -968,7 +968,7 @@ pub const Compiler = struct {
968 header.data_size = @intCast(file_size);968 header.data_size = @intCast(file_size);
969 try header.write(writer, self.errContext(node.id));969 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());
972 try writeResourceData(writer, header_slurping_reader.reader(), header.data_size);972 try writeResourceData(writer, header_slurping_reader.reader(), header.data_size);
973973
974 try self.state.font_dir.add(self.arena, FontDir.Font{974 try self.state.font_dir.add(self.arena, FontDir.Font{
...@@ -1002,7 +1002,7 @@ pub const Compiler = struct {...@@ -1002,7 +1002,7 @@ pub const Compiler = struct {
1002 // We now know that the data size will fit in a u321002 // We now know that the data size will fit in a u32
1003 header.data_size = @intCast(data_size);1003 header.data_size = @intCast(data_size);
1004 try header.write(writer, self.errContext(node.id));1004 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);
1006 }1006 }
10071007
1008 fn iconReadError(1008 fn iconReadError(
lib/compiler/resinator/errors.zig+11-14
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;
2const Token = @import("lex.zig").Token;3const Token = @import("lex.zig").Token;
3const SourceMappings = @import("source_mapping.zig").SourceMappings;4const SourceMappings = @import("source_mapping.zig").SourceMappings;
4const utils = @import("utils.zig");5const utils = @import("utils.zig");
...@@ -63,7 +64,7 @@ pub const Diagnostics = struct {...@@ -63,7 +64,7 @@ pub const Diagnostics = struct {
63 pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.io.tty.Config, source_mappings: ?SourceMappings) void {64 pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.io.tty.Config, source_mappings: ?SourceMappings) void {
64 std.debug.lockStdErr();65 std.debug.lockStdErr();
65 defer std.debug.unlockStdErr();66 defer std.debug.unlockStdErr();
66 const stderr = std.fs.File.stderr().writer();67 const stderr = std.fs.File.stderr().deprecatedWriter();
67 for (self.errors.items) |err_details| {68 for (self.errors.items) |err_details| {
68 renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;69 renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
69 }70 }
...@@ -409,15 +410,7 @@ pub const ErrorDetails = struct {...@@ -409,15 +410,7 @@ pub const ErrorDetails = struct {
409 failed_to_open_cwd,410 failed_to_open_cwd,
410 };411 };
411412
412 fn formatToken(413 fn formatToken(ctx: TokenFormatContext, writer: *std.io.Writer) std.io.Writer.Error!void {
413 ctx: TokenFormatContext,
414 comptime fmt: []const u8,
415 options: std.fmt.FormatOptions,
416 writer: anytype,
417 ) !void {
418 _ = fmt;
419 _ = options;
420
421 switch (ctx.token.id) {414 switch (ctx.token.id) {
422 .eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),415 .eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),
423 else => {},416 else => {},
...@@ -441,7 +434,7 @@ pub const ErrorDetails = struct {...@@ -441,7 +434,7 @@ pub const ErrorDetails = struct {
441 code_page: SupportedCodePage,434 code_page: SupportedCodePage,
442 };435 };
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) {
445 return .{ .data = .{438 return .{ .data = .{
446 .token = self.token,439 .token = self.token,
447 .code_page = self.code_page,440 .code_page = self.code_page,
...@@ -466,10 +459,14 @@ pub const ErrorDetails = struct {...@@ -466,10 +459,14 @@ pub const ErrorDetails = struct {
466 .hint => return,459 .hint => return,
467 },460 },
468 .illegal_byte => {461 .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 });
470 },465 },
471 .illegal_byte_outside_string_literals => {466 .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 });
473 },470 },
474 .illegal_codepoint_outside_string_literals => {471 .illegal_codepoint_outside_string_literals => {
475 // This is somewhat hacky, but we know that:472 // This is somewhat hacky, but we know that:
...@@ -1106,7 +1103,7 @@ const CorrespondingLines = struct {...@@ -1106,7 +1103,7 @@ const CorrespondingLines = struct {
1106 .code_page = err_details.code_page,1103 .code_page = err_details.code_page,
1107 };1104 };
1108 corresponding_lines.buffered_reader = BufferedReaderType{1105 corresponding_lines.buffered_reader = BufferedReaderType{
1109 .unbuffered_reader = corresponding_lines.file.reader(),1106 .unbuffered_reader = corresponding_lines.file.deprecatedReader(),
1110 };1107 };
1111 errdefer corresponding_lines.deinit();1108 errdefer corresponding_lines.deinit();
11121109
lib/compiler/resinator/lex.zig+3-1
...@@ -237,7 +237,9 @@ pub const Lexer = struct {...@@ -237,7 +237,9 @@ pub const Lexer = struct {
237 }237 }
238238
239 pub fn dump(self: *Self, token: *const Token) void {239 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 });
241 }243 }
242244
243 pub const LexMethod = enum {245 pub const LexMethod = enum {
lib/compiler/resinator/main.zig+6-6
...@@ -29,7 +29,7 @@ pub fn main() !void {...@@ -29,7 +29,7 @@ pub fn main() !void {
29 defer std.process.argsFree(allocator, args);29 defer std.process.argsFree(allocator, args);
3030
31 if (args.len < 2) {31 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", .{});
33 std.process.exit(1);33 std.process.exit(1);
34 }34 }
35 const zig_lib_dir = args[1];35 const zig_lib_dir = args[1];
...@@ -82,14 +82,14 @@ pub fn main() !void {...@@ -82,14 +82,14 @@ pub fn main() !void {
8282
83 if (options.print_help_and_exit) {83 if (options.print_help_and_exit) {
84 const stdout = std.fs.File.stdout();84 const stdout = std.fs.File.stdout();
85 try cli.writeUsage(stdout.writer(), "zig rc");85 try cli.writeUsage(stdout.deprecatedWriter(), "zig rc");
86 return;86 return;
87 }87 }
8888
89 // Don't allow verbose when integrating with Zig via stdout89 // Don't allow verbose when integrating with Zig via stdout
90 options.verbose = false;90 options.verbose = false;
9191
92 const stdout_writer = std.fs.File.stdout().writer();92 const stdout_writer = std.fs.File.stdout().deprecatedWriter();
93 if (options.verbose) {93 if (options.verbose) {
94 try options.dumpVerbose(stdout_writer);94 try options.dumpVerbose(stdout_writer);
95 try stdout_writer.writeByte('\n');95 try stdout_writer.writeByte('\n');
...@@ -290,7 +290,7 @@ pub fn main() !void {...@@ -290,7 +290,7 @@ pub fn main() !void {
290 };290 };
291 defer depfile.close();291 defer depfile.close();
292292
293 const depfile_writer = depfile.writer();293 const depfile_writer = depfile.deprecatedWriter();
294 var depfile_buffered_writer = std.io.bufferedWriter(depfile_writer);294 var depfile_buffered_writer = std.io.bufferedWriter(depfile_writer);
295 switch (options.depfile_fmt) {295 switch (options.depfile_fmt) {
296 .json => {296 .json => {
...@@ -645,7 +645,7 @@ const ErrorHandler = union(enum) {...@@ -645,7 +645,7 @@ const ErrorHandler = union(enum) {
645 },645 },
646 .tty => {646 .tty => {
647 // extra newline to separate this line from the aro errors647 // 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});
649 aro.Diagnostics.render(comp, self.tty);649 aro.Diagnostics.render(comp, self.tty);
650 },650 },
651 }651 }
...@@ -690,7 +690,7 @@ const ErrorHandler = union(enum) {...@@ -690,7 +690,7 @@ const ErrorHandler = union(enum) {
690 try server.serveErrorBundle(error_bundle);690 try server.serveErrorBundle(error_bundle);
691 },691 },
692 .tty => {692 .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);
694 },694 },
695 }695 }
696 }696 }
lib/compiler/resinator/res.zig+13-31
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;
2const rc = @import("rc.zig");3const rc = @import("rc.zig");
3const ResourceType = rc.ResourceType;4const ResourceType = rc.ResourceType;
4const CommonResourceAttributes = rc.CommonResourceAttributes;5const CommonResourceAttributes = rc.CommonResourceAttributes;
...@@ -163,14 +164,8 @@ pub const Language = packed struct(u16) {...@@ -163,14 +164,8 @@ pub const Language = packed struct(u16) {
163 return @bitCast(self);164 return @bitCast(self);
164 }165 }
165166
166 pub fn format(167 pub fn format(language: Language, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
167 language: Language,168 comptime assert(fmt.len == 0);
168 comptime fmt: []const u8,
169 options: std.fmt.FormatOptions,
170 out_stream: anytype,
171 ) !void {
172 _ = fmt;
173 _ = options;
174 const language_id = language.asInt();169 const language_id = language.asInt();
175 const language_name = language_name: {170 const language_name = language_name: {
176 if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {171 if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {
...@@ -181,7 +176,7 @@ pub const Language = packed struct(u16) {...@@ -181,7 +176,7 @@ pub const Language = packed struct(u16) {
181 }176 }
182 break :language_name "<UNKNOWN>";177 break :language_name "<UNKNOWN>";
183 };178 };
184 try out_stream.print("{s} (0x{X})", .{ language_name, language_id });179 try w.print("{s} (0x{X})", .{ language_name, language_id });
185 }180 }
186};181};
187182
...@@ -445,47 +440,34 @@ pub const NameOrOrdinal = union(enum) {...@@ -445,47 +440,34 @@ pub const NameOrOrdinal = union(enum) {
445 }440 }
446 }441 }
447442
448 pub fn format(443 pub fn format(self: NameOrOrdinal, w: *std.io.Writer, comptime fmt: []const u8) !void {
449 self: NameOrOrdinal,444 comptime assert(fmt.len == 0);
450 comptime fmt: []const u8,
451 options: std.fmt.FormatOptions,
452 out_stream: anytype,
453 ) !void {
454 _ = fmt;
455 _ = options;
456 switch (self) {445 switch (self) {
457 .name => |name| {446 .name => |name| {
458 try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});447 try w.print("{s}", .{std.unicode.fmtUtf16Le(name)});
459 },448 },
460 .ordinal => |ordinal| {449 .ordinal => |ordinal| {
461 try out_stream.print("{d}", .{ordinal});450 try w.print("{d}", .{ordinal});
462 },451 },
463 }452 }
464 }453 }
465454
466 fn formatResourceType(455 fn formatResourceType(self: NameOrOrdinal, w: *std.io.Writer) std.io.Writer.Error!void {
467 self: NameOrOrdinal,
468 comptime fmt: []const u8,
469 options: std.fmt.FormatOptions,
470 out_stream: anytype,
471 ) !void {
472 _ = fmt;
473 _ = options;
474 switch (self) {456 switch (self) {
475 .name => |name| {457 .name => |name| {
476 try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});458 try w.print("{s}", .{std.unicode.fmtUtf16Le(name)});
477 },459 },
478 .ordinal => |ordinal| {460 .ordinal => |ordinal| {
479 if (std.enums.tagName(RT, @enumFromInt(ordinal))) |predefined_type_name| {461 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});
481 } else {463 } else {
482 try out_stream.print("{d}", .{ordinal});464 try w.print("{d}", .{ordinal});
483 }465 }
484 },466 },
485 }467 }
486 }468 }
487469
488 pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(formatResourceType) {470 pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(NameOrOrdinal, formatResourceType) {
489 return .{ .data = type_value };471 return .{ .data = type_value };
490 }472 }
491};473};
lib/compiler/test_runner.zig+1-1
...@@ -328,7 +328,7 @@ pub fn mainSimple() anyerror!void {...@@ -328,7 +328,7 @@ pub fn mainSimple() anyerror!void {
328 passed += 1;328 passed += 1;
329 }329 }
330 if (enable_print and print_summary) {330 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 {};
332 }332 }
333 if (failed != 0) std.process.exit(1);333 if (failed != 0) std.process.exit(1);
334}334}
lib/docs/wasm/markdown.zig+1-1
...@@ -160,7 +160,7 @@ fn mainImpl() !void {...@@ -160,7 +160,7 @@ fn mainImpl() !void {
160 var doc = try parser.endInput();160 var doc = try parser.endInput();
161 defer doc.deinit(gpa);161 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());
164 try doc.render(stdout_buf.writer());164 try doc.render(stdout_buf.writer());
165 try stdout_buf.flush();165 try stdout_buf.flush();
166}166}
lib/docs/wasm/markdown/renderer.zig+3-9
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const Document = @import("Document.zig");2const Document = @import("Document.zig");
3const Node = Document.Node;3const Node = Document.Node;
4const assert = std.debug.assert;
45
5/// A Markdown document renderer.6/// A Markdown document renderer.
6///7///
...@@ -229,18 +230,11 @@ pub fn renderInlineNodeText(...@@ -229,18 +230,11 @@ pub fn renderInlineNodeText(
229 }230 }
230}231}
231232
232pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter(formatHtml) {233pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) {
233 return .{ .data = bytes };234 return .{ .data = bytes };
234}235}
235236
236fn formatHtml(237fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
237 bytes: []const u8,
238 comptime fmt: []const u8,
239 options: std.fmt.FormatOptions,
240 writer: anytype,
241) !void {
242 _ = fmt;
243 _ = options;
244 for (bytes) |b| {238 for (bytes) |b| {
245 switch (b) {239 switch (b) {
246 '<' => try writer.writeAll("&lt;"),240 '<' => try writer.writeAll("&lt;"),
lib/init/src/root.zig+1-1
...@@ -5,7 +5,7 @@ pub fn bufferedPrint() !void {...@@ -5,7 +5,7 @@ pub fn bufferedPrint() !void {
5 // Stdout is for the actual output of your application, for example if you5 // Stdout is for the actual output of your application, for example if you
6 // are implementing gzip, then only the compressed bytes should be sent to6 // are implementing gzip, then only the compressed bytes should be sent to
7 // stdout, not any debugging messages.7 // stdout, not any debugging messages.
8 const stdout_file = std.fs.File.stdout().writer();8 const stdout_file = std.fs.File.stdout().deprecatedWriter();
9 // Buffering can improve performance significantly in print-heavy programs.9 // Buffering can improve performance significantly in print-heavy programs.
10 var bw = std.io.bufferedWriter(stdout_file);10 var bw = std.io.bufferedWriter(stdout_file);
11 const stdout = bw.writer();11 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...@@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8
1745 return true;1745 return true;
1746 },1746 },
1747 .lazy_path, .lazy_path_list => {1747 .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)) });
1749 return true;1749 return true;
1750 },1750 },
1751 }1751 }
...@@ -2059,7 +2059,7 @@ pub fn runAllowFail(...@@ -2059,7 +2059,7 @@ pub fn runAllowFail(
2059 try Step.handleVerbose2(b, null, child.env_map, argv);2059 try Step.handleVerbose2(b, null, child.env_map, argv);
2060 try child.spawn();2060 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 {
2063 return error.ReadFailure;2063 return error.ReadFailure;
2064 };2064 };
2065 errdefer b.allocator.free(stdout);2065 errdefer b.allocator.free(stdout);
...@@ -2770,7 +2770,7 @@ fn dumpBadDirnameHelp(...@@ -2770,7 +2770,7 @@ fn dumpBadDirnameHelp(
2770 defer debug.unlockStdErr();2770 defer debug.unlockStdErr();
27712771
2772 const stderr: fs.File = .stderr();2772 const stderr: fs.File = .stderr();
2773 const w = stderr.writer();2773 const w = stderr.deprecatedWriter();
2774 try w.print(msg, args);2774 try w.print(msg, args);
27752775
2776 const tty_config = std.io.tty.detectConfig(stderr);2776 const tty_config = std.io.tty.detectConfig(stderr);
...@@ -2785,7 +2785,7 @@ fn dumpBadDirnameHelp(...@@ -2785,7 +2785,7 @@ fn dumpBadDirnameHelp(
27852785
2786 if (asking_step) |as| {2786 if (asking_step) |as| {
2787 tty_config.setColor(w, .red) catch {};2787 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});
2789 tty_config.setColor(w, .reset) catch {};2789 tty_config.setColor(w, .reset) catch {};
27902790
2791 as.dump(stderr);2791 as.dump(stderr);
...@@ -2803,7 +2803,7 @@ pub fn dumpBadGetPathHelp(...@@ -2803,7 +2803,7 @@ pub fn dumpBadGetPathHelp(
2803 src_builder: *Build,2803 src_builder: *Build,
2804 asking_step: ?*Step,2804 asking_step: ?*Step,
2805) anyerror!void {2805) anyerror!void {
2806 const w = stderr.writer();2806 const w = stderr.deprecatedWriter();
2807 try w.print(2807 try w.print(
2808 \\getPath() was called on a GeneratedFile that wasn't built yet.2808 \\getPath() was called on a GeneratedFile that wasn't built yet.
2809 \\ source package path: {s}2809 \\ source package path: {s}
...@@ -2822,7 +2822,7 @@ pub fn dumpBadGetPathHelp(...@@ -2822,7 +2822,7 @@ pub fn dumpBadGetPathHelp(
2822 s.dump(stderr);2822 s.dump(stderr);
2823 if (asking_step) |as| {2823 if (asking_step) |as| {
2824 tty_config.setColor(w, .red) catch {};2824 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});
2826 tty_config.setColor(w, .reset) catch {};2826 tty_config.setColor(w, .reset) catch {};
28272827
2828 as.dump(stderr);2828 as.dump(stderr);
lib/std/Build/Cache.zig+30-38
...@@ -68,7 +68,7 @@ const PrefixedPath = struct {...@@ -68,7 +68,7 @@ const PrefixedPath = struct {
6868
69fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {69fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
70 const gpa = cache.gpa;70 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});
72 errdefer gpa.free(resolved_path);72 errdefer gpa.free(resolved_path);
73 return findPrefixResolved(cache, resolved_path);73 return findPrefixResolved(cache, resolved_path);
74}74}
...@@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3);...@@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3);
132/// Initial state with random bytes, that can be copied.132/// Initial state with random bytes, that can be copied.
133/// Refresh this with new random bytes when the manifest133/// Refresh this with new random bytes when the manifest
134/// format is modified in a non-backwards-compatible way.134/// format is modified in a non-backwards-compatible way.
135pub const hasher_init: Hasher = Hasher.init(&[_]u8{135pub const hasher_init: Hasher = Hasher.init(&.{
136 0x33, 0x52, 0xa2, 0x84,136 0x33, 0x52, 0xa2, 0x84,
137 0xcf, 0x17, 0x56, 0x57,137 0xcf, 0x17, 0x56, 0x57,
138 0x01, 0xbb, 0xcd, 0xe4,138 0x01, 0xbb, 0xcd, 0xe4,
...@@ -286,11 +286,8 @@ pub const HashHelper = struct {...@@ -286,11 +286,8 @@ pub const HashHelper = struct {
286286
287pub fn binToHex(bin_digest: BinDigest) HexDigest {287pub fn binToHex(bin_digest: BinDigest) HexDigest {
288 var out_digest: HexDigest = undefined;288 var out_digest: HexDigest = undefined;
289 _ = fmt.bufPrint(289 var w: std.io.Writer = .fixed(&out_digest);
290 &out_digest,290 w.printHex(&bin_digest, .lower) catch unreachable;
291 "{s}",
292 .{fmt.fmtSliceHexLower(&bin_digest)},
293 ) catch unreachable;
294 return out_digest;291 return out_digest;
295}292}
296293
...@@ -337,7 +334,6 @@ pub const Manifest = struct {...@@ -337,7 +334,6 @@ pub const Manifest = struct {
337 manifest_create: fs.File.OpenError,334 manifest_create: fs.File.OpenError,
338 manifest_read: fs.File.ReadError,335 manifest_read: fs.File.ReadError,
339 manifest_lock: fs.File.LockError,336 manifest_lock: fs.File.LockError,
340 manifest_seek: fs.File.SeekError,
341 file_open: FileOp,337 file_open: FileOp,
342 file_stat: FileOp,338 file_stat: FileOp,
343 file_read: FileOp,339 file_read: FileOp,
...@@ -611,12 +607,6 @@ pub const Manifest = struct {...@@ -611,12 +607,6 @@ pub const Manifest = struct {
611 var file = self.files.pop().?;607 var file = self.files.pop().?;
612 file.key.deinit(self.cache.gpa);608 file.key.deinit(self.cache.gpa);
613 }609 }
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
620 switch (try self.hitWithCurrentLock()) {610 switch (try self.hitWithCurrentLock()) {
621 .hit => break :hit,611 .hit => break :hit,
622 .miss => |m| break :digests m.file_digests_populated,612 .miss => |m| break :digests m.file_digests_populated,
...@@ -661,9 +651,8 @@ pub const Manifest = struct {...@@ -661,9 +651,8 @@ pub const Manifest = struct {
661 return true;651 return true;
662 }652 }
663653
664 /// Assumes that `self.hash.hasher` has been updated only with the original digest, that654 /// Assumes that `self.hash.hasher` has been updated only with the original digest and that
665 /// `self.files` contains only the original input files, and that `self.manifest_file.?` is655 /// `self.files` contains only the original input files.
666 /// seeked to the start of the file.
667 fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) {656 fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) {
668 hit,657 hit,
669 miss: struct {658 miss: struct {
...@@ -672,12 +661,13 @@ pub const Manifest = struct {...@@ -672,12 +661,13 @@ pub const Manifest = struct {
672 } {661 } {
673 const gpa = self.cache.gpa;662 const gpa = self.cache.gpa;
674 const input_file_count = self.files.entries.len;663 const input_file_count = self.files.entries.len;
675664 var manifest_reader = self.manifest_file.?.reader(&.{}); // Reads positionally from zero.
676 const file_contents = self.manifest_file.?.reader().readAllAlloc(gpa, manifest_file_size_max) catch |err| switch (err) {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) {
677 error.OutOfMemory => return error.OutOfMemory,667 error.OutOfMemory => return error.OutOfMemory,
678 error.StreamTooLong => return error.OutOfMemory,668 error.StreamTooLong => return error.OutOfMemory,
679 else => |e| {669 error.ReadFailed => {
680 self.diagnostic = .{ .manifest_read = e };670 self.diagnostic = .{ .manifest_read = manifest_reader.err.? };
681 return error.CacheCheckFailed;671 return error.CacheCheckFailed;
682 },672 },
683 };673 };
...@@ -1063,14 +1053,17 @@ pub const Manifest = struct {...@@ -1063,14 +1053,17 @@ pub const Manifest = struct {
1063 }1053 }
10641054
1065 fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {1055 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);1056 const gpa = self.cache.gpa;
1067 defer self.cache.gpa.free(dep_file_contents);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);1060 var error_buf: std.ArrayListUnmanaged(u8) = .empty;
1070 defer error_buf.deinit();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 };
1074 while (it.next()) |token| {1067 while (it.next()) |token| {
1075 switch (token) {1068 switch (token) {
1076 // We don't care about targets, we only want the prereqs1069 // We don't care about targets, we only want the prereqs
...@@ -1080,16 +1073,14 @@ pub const Manifest = struct {...@@ -1080,16 +1073,14 @@ pub const Manifest = struct {
1080 _ = try self.addFile(file_path, null);1073 _ = try self.addFile(file_path, null);
1081 } else try self.addFilePost(file_path),1074 } else try self.addFilePost(file_path),
1082 .prereq_must_resolve => {1075 .prereq_must_resolve => {
1083 var resolve_buf = std.ArrayList(u8).init(self.cache.gpa);1076 resolve_buf.clearRetainingCapacity();
1084 defer resolve_buf.deinit();1077 try token.resolve(gpa, &resolve_buf);
1085
1086 try token.resolve(resolve_buf.writer());
1087 if (self.manifest_file == null) {1078 if (self.manifest_file == null) {
1088 _ = try self.addFile(resolve_buf.items, null);1079 _ = try self.addFile(resolve_buf.items, null);
1089 } else try self.addFilePost(resolve_buf.items);1080 } else try self.addFilePost(resolve_buf.items);
1090 },1081 },
1091 else => |err| {1082 else => |err| {
1092 try err.printError(error_buf.writer());1083 try err.printError(gpa, &error_buf);
1093 log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items });1084 log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items });
1094 return error.InvalidDepFile;1085 return error.InvalidDepFile;
1095 },1086 },
...@@ -1127,24 +1118,25 @@ pub const Manifest = struct {...@@ -1127,24 +1118,25 @@ pub const Manifest = struct {
1127 if (self.manifest_dirty) {1118 if (self.manifest_dirty) {
1128 self.manifest_dirty = false;1119 self.manifest_dirty = false;
11291120
1130 var contents = std.ArrayList(u8).init(self.cache.gpa);1121 const gpa = self.cache.gpa;
1131 defer contents.deinit();1122 var contents: std.ArrayListUnmanaged(u8) = .empty;
1123 defer contents.deinit(gpa);
11321124
1133 const writer = contents.writer();1125 try contents.appendSlice(gpa, manifest_header ++ "\n");
1134 try writer.writeAll(manifest_header ++ "\n");
1135 for (self.files.keys()) |file| {1126 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", .{
1137 file.stat.size,1128 file.stat.size,
1138 file.stat.inode,1129 file.stat.inode,
1139 file.stat.mtime,1130 file.stat.mtime,
1140 fmt.fmtSliceHexLower(&file.bin_digest),1131 &file.bin_digest,
1141 file.prefixed_path.prefix,1132 file.prefixed_path.prefix,
1142 file.prefixed_path.sub_path,1133 file.prefixed_path.sub_path,
1143 });1134 });
1144 }1135 }
11451136
1146 try manifest_file.setEndPos(contents.items.len);1137 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);
1148 }1140 }
11491141
1150 if (self.want_shared_lock) {1142 if (self.want_shared_lock) {
lib/std/Build/Cache/DepTokenizer.zig+43-158
...@@ -7,6 +7,7 @@ state: State = .lhs,...@@ -7,6 +7,7 @@ state: State = .lhs,
7const std = @import("std");7const std = @import("std");
8const testing = std.testing;8const testing = std.testing;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const Allocator = std.mem.Allocator;
1011
11pub fn next(self: *Tokenizer) ?Token {12pub fn next(self: *Tokenizer) ?Token {
12 var start = self.index;13 var start = self.index;
...@@ -362,7 +363,7 @@ pub const Token = union(enum) {...@@ -362,7 +363,7 @@ pub const Token = union(enum) {
362 };363 };
363364
364 /// Resolve escapes in target or prereq. Only valid with .target_must_resolve or .prereq_must_resolve.365 /// 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 {
366 switch (self) {367 switch (self) {
367 .target_must_resolve => |bytes| {368 .target_must_resolve => |bytes| {
368 var state: enum { start, escape, dollar } = .start;369 var state: enum { start, escape, dollar } = .start;
...@@ -372,27 +373,27 @@ pub const Token = union(enum) {...@@ -372,27 +373,27 @@ pub const Token = union(enum) {
372 switch (c) {373 switch (c) {
373 '\\' => state = .escape,374 '\\' => state = .escape,
374 '$' => state = .dollar,375 '$' => state = .dollar,
375 else => try writer.writeByte(c),376 else => try list.append(gpa, c),
376 }377 }
377 },378 },
378 .escape => {379 .escape => {
379 switch (c) {380 switch (c) {
380 ' ', '#', '\\' => {},381 ' ', '#', '\\' => {},
381 '$' => {382 '$' => {
382 try writer.writeByte('\\');383 try list.append(gpa, '\\');
383 state = .dollar;384 state = .dollar;
384 continue;385 continue;
385 },386 },
386 else => try writer.writeByte('\\'),387 else => try list.append(gpa, '\\'),
387 }388 }
388 try writer.writeByte(c);389 try list.append(gpa, c);
389 state = .start;390 state = .start;
390 },391 },
391 .dollar => {392 .dollar => {
392 try writer.writeByte('$');393 try list.append(gpa, '$');
393 switch (c) {394 switch (c) {
394 '$' => {},395 '$' => {},
395 else => try writer.writeByte(c),396 else => try list.append(gpa, c),
396 }397 }
397 state = .start;398 state = .start;
398 },399 },
...@@ -406,19 +407,19 @@ pub const Token = union(enum) {...@@ -406,19 +407,19 @@ pub const Token = union(enum) {
406 .start => {407 .start => {
407 switch (c) {408 switch (c) {
408 '\\' => state = .escape,409 '\\' => state = .escape,
409 else => try writer.writeByte(c),410 else => try list.append(gpa, c),
410 }411 }
411 },412 },
412 .escape => {413 .escape => {
413 switch (c) {414 switch (c) {
414 ' ' => {},415 ' ' => {},
415 '\\' => {416 '\\' => {
416 try writer.writeByte(c);417 try list.append(gpa, c);
417 continue;418 continue;
418 },419 },
419 else => try writer.writeByte('\\'),420 else => try list.append(gpa, '\\'),
420 }421 }
421 try writer.writeByte(c);422 try list.append(gpa, c);
422 state = .start;423 state = .start;
423 },424 },
424 }425 }
...@@ -428,20 +429,20 @@ pub const Token = union(enum) {...@@ -428,20 +429,20 @@ pub const Token = union(enum) {
428 }429 }
429 }430 }
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 {
432 switch (self) {433 switch (self) {
433 .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error434 .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error
434 .incomplete_quoted_prerequisite,435 .incomplete_quoted_prerequisite,
435 .incomplete_target,436 .incomplete_target,
436 => |index_and_bytes| {437 => |index_and_bytes| {
437 try writer.print("{s} '", .{self.errStr()});438 try list.print(gpa, "{s} '", .{self.errStr()});
438 if (self == .incomplete_target) {439 if (self == .incomplete_target) {
439 const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };440 const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };
440 try tmp.resolve(writer);441 try tmp.resolve(gpa, list);
441 } else {442 } else {
442 try printCharValues(writer, index_and_bytes.bytes);443 try printCharValues(gpa, list, index_and_bytes.bytes);
443 }444 }
444 try writer.print("' at position {d}", .{index_and_bytes.index});445 try list.print(gpa, "' at position {d}", .{index_and_bytes.index});
445 },446 },
446 .invalid_target,447 .invalid_target,
447 .bad_target_escape,448 .bad_target_escape,
...@@ -450,9 +451,9 @@ pub const Token = union(enum) {...@@ -450,9 +451,9 @@ pub const Token = union(enum) {
450 .incomplete_escape,451 .incomplete_escape,
451 .expected_colon,452 .expected_colon,
452 => |index_and_char| {453 => |index_and_char| {
453 try writer.writeAll("illegal char ");454 try list.appendSlice(gpa, "illegal char ");
454 try printUnderstandableChar(writer, index_and_char.char);455 try printUnderstandableChar(gpa, list, index_and_char.char);
455 try writer.print(" at position {d}: {s}", .{ index_and_char.index, self.errStr() });456 try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() });
456 },457 },
457 }458 }
458 }459 }
...@@ -1026,41 +1027,41 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {...@@ -1026,41 +1027,41 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
1026 defer arena_allocator.deinit();1027 defer arena_allocator.deinit();
10271028
1028 var it: Tokenizer = .{ .bytes = input };1029 var it: Tokenizer = .{ .bytes = input };
1029 var buffer = std.ArrayList(u8).init(arena);1030 var buffer: std.ArrayListUnmanaged(u8) = .empty;
1030 var resolve_buf = std.ArrayList(u8).init(arena);1031 var resolve_buf: std.ArrayListUnmanaged(u8) = .empty;
1031 var i: usize = 0;1032 var i: usize = 0;
1032 while (it.next()) |token| {1033 while (it.next()) |token| {
1033 if (i != 0) try buffer.appendSlice("\n");1034 if (i != 0) try buffer.appendSlice(arena, "\n");
1034 switch (token) {1035 switch (token) {
1035 .target, .prereq => |bytes| {1036 .target, .prereq => |bytes| {
1036 try buffer.appendSlice(@tagName(token));1037 try buffer.appendSlice(arena, @tagName(token));
1037 try buffer.appendSlice(" = {");1038 try buffer.appendSlice(arena, " = {");
1038 for (bytes) |b| {1039 for (bytes) |b| {
1039 try buffer.append(printable_char_tab[b]);1040 try buffer.append(arena, printable_char_tab[b]);
1040 }1041 }
1041 try buffer.appendSlice("}");1042 try buffer.appendSlice(arena, "}");
1042 },1043 },
1043 .target_must_resolve => {1044 .target_must_resolve => {
1044 try buffer.appendSlice("target = {");1045 try buffer.appendSlice(arena, "target = {");
1045 try token.resolve(resolve_buf.writer());1046 try token.resolve(arena, &resolve_buf);
1046 for (resolve_buf.items) |b| {1047 for (resolve_buf.items) |b| {
1047 try buffer.append(printable_char_tab[b]);1048 try buffer.append(arena, printable_char_tab[b]);
1048 }1049 }
1049 resolve_buf.items.len = 0;1050 resolve_buf.items.len = 0;
1050 try buffer.appendSlice("}");1051 try buffer.appendSlice(arena, "}");
1051 },1052 },
1052 .prereq_must_resolve => {1053 .prereq_must_resolve => {
1053 try buffer.appendSlice("prereq = {");1054 try buffer.appendSlice(arena, "prereq = {");
1054 try token.resolve(resolve_buf.writer());1055 try token.resolve(arena, &resolve_buf);
1055 for (resolve_buf.items) |b| {1056 for (resolve_buf.items) |b| {
1056 try buffer.append(printable_char_tab[b]);1057 try buffer.append(arena, printable_char_tab[b]);
1057 }1058 }
1058 resolve_buf.items.len = 0;1059 resolve_buf.items.len = 0;
1059 try buffer.appendSlice("}");1060 try buffer.appendSlice(arena, "}");
1060 },1061 },
1061 else => {1062 else => {
1062 try buffer.appendSlice("ERROR: ");1063 try buffer.appendSlice(arena, "ERROR: ");
1063 try token.printError(buffer.writer());1064 try token.printError(arena, &buffer);
1064 break;1065 break;
1065 },1066 },
1066 }1067 }
...@@ -1072,134 +1073,18 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {...@@ -1072,134 +1073,18 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
1072 return;1073 return;
1073 }1074 }
10741075
1075 const out = std.fs.File.stderr().writer();1076 try testing.expectEqualStrings(expect, buffer.items);
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");
1160}1077}
11611078
1162fn hexDump16(out: anytype, offset: usize, bytes: []const u8) !void {1079fn printCharValues(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), bytes: []const u8) !void {
1163 try printDecValue(out, offset, 8);1080 for (bytes) |b| try list.append(gpa, printable_char_tab[b]);
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 }
1196}1081}
11971082
1198fn printUnderstandableChar(out: anytype, char: u8) !void {1083fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), char: u8) !void {
1199 if (std.ascii.isPrint(char)) {1084 if (std.ascii.isPrint(char)) {
1200 try out.print("'{c}'", .{char});1085 try list.print(gpa, "'{c}'", .{char});
1201 } else {1086 } else {
1202 try out.print("\\x{X:0>2}", .{char});1087 try list.print(gpa, "\\x{X:0>2}", .{char});
1203 }1088 }
1204}1089}
12051090
lib/std/Build/Cache/Directory.zig+3-8
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const Directory = @This();1const Directory = @This();
2const std = @import("../../std.zig");2const std = @import("../../std.zig");
3const assert = std.debug.assert;
3const fs = std.fs;4const fs = std.fs;
4const fmt = std.fmt;5const fmt = std.fmt;
5const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
...@@ -55,14 +56,8 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {...@@ -55,14 +56,8 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
55 self.* = undefined;56 self.* = undefined;
56}57}
5758
58pub fn format(59pub fn format(self: Directory, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
59 self: Directory,60 comptime assert(f.len == 0);
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);
66 if (self.path) |p| {61 if (self.path) |p| {
67 try writer.writeAll(p);62 try writer.writeAll(p);
68 try writer.writeAll(fs.path.sep_str);63 try writer.writeAll(fs.path.sep_str);
lib/std/Build/Cache/Path.zig+20-25
...@@ -1,3 +1,10 @@...@@ -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
1root_dir: Cache.Directory,8root_dir: Cache.Directory,
2/// The path, relative to the root dir, that this `Path` represents.9/// The path, relative to the root dir, that this `Path` represents.
3/// Empty string means the root_dir is the path.10/// Empty string means the root_dir is the path.
...@@ -133,38 +140,32 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {...@@ -133,38 +140,32 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {
133}140}
134141
135pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {142pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {
136 return std.fmt.allocPrint(allocator, "{}", .{p});143 return std.fmt.allocPrint(allocator, "{f}", .{p});
137}144}
138145
139pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {146pub 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);
141}148}
142149
143pub fn format(150pub fn format(self: Path, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
144 self: Path,151 if (f.len == 1) {
145 comptime fmt_string: []const u8,
146 options: std.fmt.FormatOptions,
147 writer: anytype,
148) !void {
149 if (fmt_string.len == 1) {
150 // Quote-escape the string.152 // Quote-escape the string.
151 const stringEscape = std.zig.stringEscape;153 const zigEscape = switch (f[0]) {
152 const f = switch (fmt_string[0]) {154 'q' => std.zig.stringEscape,
153 'q' => "",155 '\'' => std.zig.charEscape,
154 '\'' => "\'",156 else => @compileError("unsupported format string: " ++ f),
155 else => @compileError("unsupported format string: " ++ fmt_string),
156 };157 };
157 if (self.root_dir.path) |p| {158 if (self.root_dir.path) |p| {
158 try stringEscape(p, f, options, writer);159 try zigEscape(p, writer);
159 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, f, options, writer);160 if (self.sub_path.len > 0) try zigEscape(fs.path.sep_str, writer);
160 }161 }
161 if (self.sub_path.len > 0) {162 if (self.sub_path.len > 0) {
162 try stringEscape(self.sub_path, f, options, writer);163 try zigEscape(self.sub_path, writer);
163 }164 }
164 return;165 return;
165 }166 }
166 if (fmt_string.len > 0)167 if (f.len > 0)
167 std.fmt.invalidFmtError(fmt_string, self);168 std.fmt.invalidFmtError(f, self);
168 if (std.fs.path.isAbsolute(self.sub_path)) {169 if (std.fs.path.isAbsolute(self.sub_path)) {
169 try writer.writeAll(self.sub_path);170 try writer.writeAll(self.sub_path);
170 return;171 return;
...@@ -223,9 +224,3 @@ pub const TableAdapter = struct {...@@ -223,9 +224,3 @@ pub const TableAdapter = struct {
223 return a.eql(b);224 return a.eql(b);
224 }225 }
225};226};
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(...@@ -170,7 +170,7 @@ fn serveFile(
170 // We load the file with every request so that the user can make changes to the file170 // We load the file with every request so that the user can make changes to the file
171 // and refresh the HTML page without restarting this server.171 // and refresh the HTML page without restarting this server.
172 const file_contents = ws.zig_lib_directory.handle.readFileAlloc(gpa, name, 10 * 1024 * 1024) catch |err| {172 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) });
174 return error.AlreadyReported;174 return error.AlreadyReported;
175 };175 };
176 defer gpa.free(file_contents);176 defer gpa.free(file_contents);
...@@ -251,10 +251,10 @@ fn buildWasmBinary(...@@ -251,10 +251,10 @@ fn buildWasmBinary(
251 "-fsingle-threaded", //251 "-fsingle-threaded", //
252 "--dep", "Walk", //252 "--dep", "Walk", //
253 "--dep", "html_render", //253 "--dep", "html_render", //
254 try std.fmt.allocPrint(arena, "-Mroot={}", .{main_src_path}), //254 try std.fmt.allocPrint(arena, "-Mroot={f}", .{main_src_path}), //
255 try std.fmt.allocPrint(arena, "-MWalk={}", .{walk_src_path}), //255 try std.fmt.allocPrint(arena, "-MWalk={f}", .{walk_src_path}), //
256 "--dep", "Walk", //256 "--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}), //
258 "--listen=-",258 "--listen=-",
259 });259 });
260260
...@@ -526,7 +526,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {...@@ -526,7 +526,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
526526
527 for (deduped_paths) |joined_path| {527 for (deduped_paths) |joined_path| {
528 var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {528 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) });
530 continue;530 continue;
531 };531 };
532 defer file.close();532 defer file.close();
...@@ -604,7 +604,7 @@ fn prepareTables(...@@ -604,7 +604,7 @@ fn prepareTables(
604604
605 const rebuilt_exe_path = run_step.rebuilt_executable.?;605 const rebuilt_exe_path = run_step.rebuilt_executable.?;
606 var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {606 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}", .{
608 run_step.step.name, rebuilt_exe_path, @errorName(err),608 run_step.step.name, rebuilt_exe_path, @errorName(err),
609 });609 });
610 return error.AlreadyReported;610 return error.AlreadyReported;
...@@ -616,7 +616,7 @@ fn prepareTables(...@@ -616,7 +616,7 @@ fn prepareTables(
616 .sub_path = "v/" ++ std.fmt.hex(coverage_id),616 .sub_path = "v/" ++ std.fmt.hex(coverage_id),
617 };617 };
618 var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| {618 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}", .{
620 run_step.step.name, coverage_file_path, @errorName(err),620 run_step.step.name, coverage_file_path, @errorName(err),
621 });621 });
622 return error.AlreadyReported;622 return error.AlreadyReported;
...@@ -624,7 +624,7 @@ fn prepareTables(...@@ -624,7 +624,7 @@ fn prepareTables(
624 defer coverage_file.close();624 defer coverage_file.close();
625625
626 const file_size = coverage_file.getEndPos() catch |err| {626 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) });
628 return error.AlreadyReported;628 return error.AlreadyReported;
629 };629 };
630630
...@@ -636,7 +636,7 @@ fn prepareTables(...@@ -636,7 +636,7 @@ fn prepareTables(
636 coverage_file.handle,636 coverage_file.handle,
637 0,637 0,
638 ) catch |err| {638 ) 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) });
640 return error.AlreadyReported;640 return error.AlreadyReported;
641 };641 };
642 gop.value_ptr.mapped_memory = mapped_memory;642 gop.value_ptr.mapped_memory = mapped_memory;
lib/std/Build/Module.zig+1-1
...@@ -186,7 +186,7 @@ pub const IncludeDir = union(enum) {...@@ -186,7 +186,7 @@ pub const IncludeDir = union(enum) {
186 .embed_path => |lazy_path| {186 .embed_path => |lazy_path| {
187 // Special case: this is a single arg.187 // Special case: this is a single arg.
188 const resolved = lazy_path.getPath3(b, asking_step);188 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});
190 return zig_args.append(arg);190 return zig_args.append(arg);
191 },191 },
192 };192 };
lib/std/Build/Step.zig+5-4
...@@ -287,7 +287,8 @@ pub fn cast(step: *Step, comptime T: type) ?*T {...@@ -287,7 +287,8 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
287287
288/// For debugging purposes, prints identifying information about this Step.288/// For debugging purposes, prints identifying information about this Step.
289pub fn dump(step: *Step, file: std.fs.File) void {289pub fn dump(step: *Step, file: std.fs.File) void {
290 const w = file.writer();290 var fw = file.writer(&.{});
291 const w = &fw.interface;
291 const tty_config = std.io.tty.detectConfig(file);292 const tty_config = std.io.tty.detectConfig(file);
292 const debug_info = std.debug.getSelfDebugInfo() catch |err| {293 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
293 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{294 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
...@@ -482,9 +483,9 @@ pub fn evalZigProcess(...@@ -482,9 +483,9 @@ pub fn evalZigProcess(
482pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {483pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
483 const b = s.owner;484 const b = s.owner;
484 const src_path = src_lazy_path.getPath3(b, s);485 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 });
486 return src_path.root_dir.handle.updateFile(src_path.sub_path, std.fs.cwd(), dest_path, .{}) catch |err| {487 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}", .{
488 src_path, dest_path, @errorName(err),489 src_path, dest_path, @errorName(err),
489 });490 });
490 };491 };
...@@ -821,7 +822,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac...@@ -821,7 +822,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac
821 switch (err) {822 switch (err) {
822 error.CacheCheckFailed => switch (man.diagnostic) {823 error.CacheCheckFailed => switch (man.diagnostic) {
823 .none => unreachable,824 .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}", .{
825 @tagName(man.diagnostic), @errorName(e),826 @tagName(man.diagnostic), @errorName(e),
826 }),827 }),
827 .file_open, .file_stat, .file_read, .file_hash => |op| {828 .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;...@@ -6,6 +6,7 @@ const macho = std.macho;
6const math = std.math;6const math = std.math;
7const mem = std.mem;7const mem = std.mem;
8const testing = std.testing;8const testing = std.testing;
9const Writer = std.io.Writer;
910
10const CheckObject = @This();11const CheckObject = @This();
1112
...@@ -28,14 +29,14 @@ pub fn create(...@@ -28,14 +29,14 @@ pub fn create(
28 const gpa = owner.allocator;29 const gpa = owner.allocator;
29 const check_object = gpa.create(CheckObject) catch @panic("OOM");30 const check_object = gpa.create(CheckObject) catch @panic("OOM");
30 check_object.* = .{31 check_object.* = .{
31 .step = Step.init(.{32 .step = .init(.{
32 .id = base_id,33 .id = base_id,
33 .name = "CheckObject",34 .name = "CheckObject",
34 .owner = owner,35 .owner = owner,
35 .makeFn = make,36 .makeFn = make,
36 }),37 }),
37 .source = source.dupe(owner),38 .source = source.dupe(owner),
38 .checks = std.ArrayList(Check).init(gpa),39 .checks = .init(gpa),
39 .obj_format = obj_format,40 .obj_format = obj_format,
40 };41 };
41 check_object.source.addStepDependencies(&check_object.step);42 check_object.source.addStepDependencies(&check_object.step);
...@@ -74,13 +75,13 @@ const Action = struct {...@@ -74,13 +75,13 @@ const Action = struct {
74 b: *std.Build,75 b: *std.Build,
75 step: *Step,76 step: *Step,
76 haystack: []const u8,77 haystack: []const u8,
77 global_vars: anytype,78 global_vars: *std.StringHashMap(u64),
78 ) !bool {79 ) !bool {
79 assert(act.tag == .extract);80 assert(act.tag == .extract);
80 const hay = mem.trim(u8, haystack, " ");81 const hay = mem.trim(u8, haystack, " ");
81 const phrase = mem.trim(u8, act.phrase.resolve(b, step), " ");82 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);
84 var hay_it = mem.tokenizeScalar(u8, hay, ' ');85 var hay_it = mem.tokenizeScalar(u8, hay, ' ');
85 var needle_it = mem.tokenizeScalar(u8, phrase, ' ');86 var needle_it = mem.tokenizeScalar(u8, phrase, ' ');
8687
...@@ -153,11 +154,11 @@ const Action = struct {...@@ -153,11 +154,11 @@ const Action = struct {
153 /// Will return true if the `phrase` is correctly parsed into an RPN program and154 /// Will return true if the `phrase` is correctly parsed into an RPN program and
154 /// its reduced, computed value compares using `op` with the expected value, either155 /// its reduced, computed value compares using `op` with the expected value, either
155 /// a literal or another extracted variable.156 /// 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 {
157 const gpa = step.owner.allocator;158 const gpa = step.owner.allocator;
158 const phrase = act.phrase.resolve(b, step);159 const phrase = act.phrase.resolve(b, step);
159 var op_stack = std.ArrayList(enum { add, sub, mod, mul }).init(gpa);160 var op_stack: std.ArrayList(enum { add, sub, mod, mul }) = .init(gpa);
160 var values = std.ArrayList(u64).init(gpa);161 var values: std.ArrayList(u64) = .init(gpa);
161162
162 var it = mem.tokenizeScalar(u8, phrase, ' ');163 var it = mem.tokenizeScalar(u8, phrase, ' ');
163 while (it.next()) |next| {164 while (it.next()) |next| {
...@@ -230,17 +231,15 @@ const ComputeCompareExpected = struct {...@@ -230,17 +231,15 @@ const ComputeCompareExpected = struct {
230 },231 },
231232
232 pub fn format(233 pub fn format(
233 value: @This(),234 value: ComputeCompareExpected,
235 bw: *Writer,
234 comptime fmt: []const u8,236 comptime fmt: []const u8,
235 options: std.fmt.FormatOptions,
236 writer: anytype,
237 ) !void {237 ) !void {
238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
239 _ = options;239 try bw.print("{s} ", .{@tagName(value.op)});
240 try writer.print("{s} ", .{@tagName(value.op)});
241 switch (value.value) {240 switch (value.value) {
242 .variable => |name| try writer.writeAll(name),241 .variable => |name| try bw.writeAll(name),
243 .literal => |x| try writer.print("{x}", .{x}),242 .literal => |x| try bw.print("{x}", .{x}),
244 }243 }
245 }244 }
246};245};
...@@ -248,56 +247,63 @@ const ComputeCompareExpected = struct {...@@ -248,56 +247,63 @@ const ComputeCompareExpected = struct {
248const Check = struct {247const Check = struct {
249 kind: Kind,248 kind: Kind,
250 payload: Payload,249 payload: Payload,
251 data: std.ArrayList(u8),250 allocator: Allocator,
252 actions: std.ArrayList(Action),251 data: std.ArrayListUnmanaged(u8),
252 actions: std.ArrayListUnmanaged(Action),
253253
254 fn create(allocator: Allocator, kind: Kind) Check {254 fn create(allocator: Allocator, kind: Kind) Check {
255 return .{255 return .{
256 .kind = kind,256 .kind = kind,
257 .payload = .{ .none = {} },257 .payload = .{ .none = {} },
258 .data = std.ArrayList(u8).init(allocator),258 .allocator = allocator,
259 .actions = std.ArrayList(Action).init(allocator),259 .data = .empty,
260 .actions = .empty,
260 };261 };
261 }262 }
262263
263 fn dumpSection(allocator: Allocator, name: [:0]const u8) Check {264 fn dumpSection(gpa: Allocator, name: [:0]const u8) Check {
264 var check = Check.create(allocator, .dump_section);265 var check = Check.create(gpa, .dump_section);
265 const off: u32 = @intCast(check.data.items.len);266 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");
267 check.payload = .{ .dump_section = off };268 check.payload = .{ .dump_section = off };
268 return check;269 return check;
269 }270 }
270271
271 fn extract(check: *Check, phrase: SearchPhrase) void {272 fn extract(check: *Check, phrase: SearchPhrase) void {
272 check.actions.append(.{273 const gpa = check.allocator;
274 check.actions.append(gpa, .{
273 .tag = .extract,275 .tag = .extract,
274 .phrase = phrase,276 .phrase = phrase,
275 }) catch @panic("OOM");277 }) catch @panic("OOM");
276 }278 }
277279
278 fn exact(check: *Check, phrase: SearchPhrase) void {280 fn exact(check: *Check, phrase: SearchPhrase) void {
279 check.actions.append(.{281 const gpa = check.allocator;
282 check.actions.append(gpa, .{
280 .tag = .exact,283 .tag = .exact,
281 .phrase = phrase,284 .phrase = phrase,
282 }) catch @panic("OOM");285 }) catch @panic("OOM");
283 }286 }
284287
285 fn contains(check: *Check, phrase: SearchPhrase) void {288 fn contains(check: *Check, phrase: SearchPhrase) void {
286 check.actions.append(.{289 const gpa = check.allocator;
290 check.actions.append(gpa, .{
287 .tag = .contains,291 .tag = .contains,
288 .phrase = phrase,292 .phrase = phrase,
289 }) catch @panic("OOM");293 }) catch @panic("OOM");
290 }294 }
291295
292 fn notPresent(check: *Check, phrase: SearchPhrase) void {296 fn notPresent(check: *Check, phrase: SearchPhrase) void {
293 check.actions.append(.{297 const gpa = check.allocator;
298 check.actions.append(gpa, .{
294 .tag = .not_present,299 .tag = .not_present,
295 .phrase = phrase,300 .phrase = phrase,
296 }) catch @panic("OOM");301 }) catch @panic("OOM");
297 }302 }
298303
299 fn computeCmp(check: *Check, phrase: SearchPhrase, expected: ComputeCompareExpected) void {304 fn computeCmp(check: *Check, phrase: SearchPhrase, expected: ComputeCompareExpected) void {
300 check.actions.append(.{305 const gpa = check.allocator;
306 check.actions.append(gpa, .{
301 .tag = .compute_cmp,307 .tag = .compute_cmp,
302 .phrase = phrase,308 .phrase = phrase,
303 .expected = expected,309 .expected = expected,
...@@ -565,9 +571,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -565,9 +571,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
565 null,571 null,
566 .of(u64),572 .of(u64),
567 null,573 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);
571 for (check_object.checks.items) |chk| {577 for (check_object.checks.items) |chk| {
572 if (chk.kind == .compute_compare) {578 if (chk.kind == .compute_compare) {
573 assert(chk.actions.items.len == 1);579 assert(chk.actions.items.len == 1);
...@@ -581,7 +587,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -581,7 +587,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
581 return step.fail(587 return step.fail(
582 \\588 \\
583 \\========= comparison failed for action: ===========589 \\========= comparison failed for action: ===========
584 \\{s} {}590 \\{s} {f}
585 \\===================================================591 \\===================================================
586 , .{ act.phrase.resolve(b, step), act.expected.? });592 , .{ act.phrase.resolve(b, step), act.expected.? });
587 }593 }
...@@ -600,7 +606,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -600,7 +606,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
600 // we either format message string with escaped codes, or not to aid debugging606 // we either format message string with escaped codes, or not to aid debugging
601 // the failed test.607 // the failed test.
602 const fmtMessageString = struct {608 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) {
604 return .{ .data = .{610 return .{ .data = .{
605 .kind = kind,611 .kind = kind,
606 .msg = msg,612 .msg = msg,
...@@ -612,17 +618,10 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -612,17 +618,10 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
612 msg: []const u8,618 msg: []const u8,
613 };619 };
614620
615 fn formatMessageString(621 fn formatMessageString(ctx: Ctx, w: *Writer) !void {
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;
623 switch (ctx.kind) {622 switch (ctx.kind) {
624 .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),623 .dump_section => try w.print("{f}", .{std.ascii.hexEscape(ctx.msg, .lower)}),
625 else => try writer.writeAll(ctx.msg),624 else => try w.writeAll(ctx.msg),
626 }625 }
627 }626 }
628 }.fmtMessageString;627 }.fmtMessageString;
...@@ -637,11 +636,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -637,11 +636,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
637 return step.fail(636 return step.fail(
638 \\637 \\
639 \\========= expected to find: ==========================638 \\========= expected to find: ==========================
640 \\{s}639 \\{f}
641 \\========= but parsed file does not contain it: =======640 \\========= but parsed file does not contain it: =======
642 \\{s}641 \\{f}
643 \\========= file path: =================================642 \\========= file path: =================================
644 \\{}643 \\{f}
645 , .{644 , .{
646 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),645 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
647 fmtMessageString(chk.kind, output),646 fmtMessageString(chk.kind, output),
...@@ -657,11 +656,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -657,11 +656,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
657 return step.fail(656 return step.fail(
658 \\657 \\
659 \\========= expected to find: ==========================658 \\========= expected to find: ==========================
660 \\*{s}*659 \\*{f}*
661 \\========= but parsed file does not contain it: =======660 \\========= but parsed file does not contain it: =======
662 \\{s}661 \\{f}
663 \\========= file path: =================================662 \\========= file path: =================================
664 \\{}663 \\{f}
665 , .{664 , .{
666 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),665 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
667 fmtMessageString(chk.kind, output),666 fmtMessageString(chk.kind, output),
...@@ -676,11 +675,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -676,11 +675,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
676 return step.fail(675 return step.fail(
677 \\676 \\
678 \\========= expected not to find: ===================677 \\========= expected not to find: ===================
679 \\{s}678 \\{f}
680 \\========= but parsed file does contain it: ========679 \\========= but parsed file does contain it: ========
681 \\{s}680 \\{f}
682 \\========= file path: ==============================681 \\========= file path: ==============================
683 \\{}682 \\{f}
684 , .{683 , .{
685 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),684 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
686 fmtMessageString(chk.kind, output),685 fmtMessageString(chk.kind, output),
...@@ -696,13 +695,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -696,13 +695,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
696 return step.fail(695 return step.fail(
697 \\696 \\
698 \\========= expected to find and extract: ==============697 \\========= expected to find and extract: ==============
699 \\{s}698 \\{f}
700 \\========= but parsed file does not contain it: =======699 \\========= but parsed file does not contain it: =======
701 \\{s}700 \\{f}
702 \\========= file path: ==============================701 \\========= file path: ==============================
703 \\{}702 \\{f}
704 , .{703 , .{
705 act.phrase.resolve(b, step),704 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
706 fmtMessageString(chk.kind, output),705 fmtMessageString(chk.kind, output),
707 src_path,706 src_path,
708 });707 });
...@@ -755,14 +754,14 @@ const MachODumper = struct {...@@ -755,14 +754,14 @@ const MachODumper = struct {
755 },754 },
756 .SYMTAB => {755 .SYMTAB => {
757 const lc = cmd.cast(macho.symtab_command).?;756 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];
759 const strtab = ctx.data[lc.stroff..][0..lc.strsize];758 const strtab = ctx.data[lc.stroff..][0..lc.strsize];
760 try ctx.symtab.appendUnalignedSlice(ctx.gpa, symtab);759 try ctx.symtab.appendUnalignedSlice(ctx.gpa, symtab);
761 try ctx.strtab.appendSlice(ctx.gpa, strtab);760 try ctx.strtab.appendSlice(ctx.gpa, strtab);
762 },761 },
763 .DYSYMTAB => {762 .DYSYMTAB => {
764 const lc = cmd.cast(macho.dysymtab_command).?;763 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];
766 try ctx.indsymtab.appendUnalignedSlice(ctx.gpa, indexes);765 try ctx.indsymtab.appendUnalignedSlice(ctx.gpa, indexes);
767 },766 },
768 .LOAD_DYLIB,767 .LOAD_DYLIB,
...@@ -780,7 +779,7 @@ const MachODumper = struct {...@@ -780,7 +779,7 @@ const MachODumper = struct {
780779
781 fn getString(ctx: ObjectContext, off: u32) [:0]const u8 {780 fn getString(ctx: ObjectContext, off: u32) [:0]const u8 {
782 assert(off < ctx.strtab.items.len);781 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);
784 }783 }
785784
786 fn getLoadCommandIterator(ctx: ObjectContext) macho.LoadCommandIterator {785 fn getLoadCommandIterator(ctx: ObjectContext) macho.LoadCommandIterator {
...@@ -810,7 +809,7 @@ const MachODumper = struct {...@@ -810,7 +809,7 @@ const MachODumper = struct {
810 return null;809 return null;
811 }810 }
812811
813 fn dumpHeader(hdr: macho.mach_header_64, writer: anytype) !void {812 fn dumpHeader(hdr: macho.mach_header_64, bw: *Writer) !void {
814 const cputype = switch (hdr.cputype) {813 const cputype = switch (hdr.cputype) {
815 macho.CPU_TYPE_ARM64 => "ARM64",814 macho.CPU_TYPE_ARM64 => "ARM64",
816 macho.CPU_TYPE_X86_64 => "X86_64",815 macho.CPU_TYPE_X86_64 => "X86_64",
...@@ -831,7 +830,7 @@ const MachODumper = struct {...@@ -831,7 +830,7 @@ const MachODumper = struct {
831 else => "Unknown",830 else => "Unknown",
832 };831 };
833832
834 try writer.print(833 try bw.print(
835 \\header834 \\header
836 \\cputype {s}835 \\cputype {s}
837 \\filetype {s}836 \\filetype {s}
...@@ -846,41 +845,41 @@ const MachODumper = struct {...@@ -846,41 +845,41 @@ const MachODumper = struct {
846 });845 });
847846
848 if (hdr.flags > 0) {847 if (hdr.flags > 0) {
849 if (hdr.flags & macho.MH_NOUNDEFS != 0) try writer.writeAll(" NOUNDEFS");848 if (hdr.flags & macho.MH_NOUNDEFS != 0) try bw.writeAll(" NOUNDEFS");
850 if (hdr.flags & macho.MH_INCRLINK != 0) try writer.writeAll(" INCRLINK");849 if (hdr.flags & macho.MH_INCRLINK != 0) try bw.writeAll(" INCRLINK");
851 if (hdr.flags & macho.MH_DYLDLINK != 0) try writer.writeAll(" DYLDLINK");850 if (hdr.flags & macho.MH_DYLDLINK != 0) try bw.writeAll(" DYLDLINK");
852 if (hdr.flags & macho.MH_BINDATLOAD != 0) try writer.writeAll(" BINDATLOAD");851 if (hdr.flags & macho.MH_BINDATLOAD != 0) try bw.writeAll(" BINDATLOAD");
853 if (hdr.flags & macho.MH_PREBOUND != 0) try writer.writeAll(" PREBOUND");852 if (hdr.flags & macho.MH_PREBOUND != 0) try bw.writeAll(" PREBOUND");
854 if (hdr.flags & macho.MH_SPLIT_SEGS != 0) try writer.writeAll(" SPLIT_SEGS");853 if (hdr.flags & macho.MH_SPLIT_SEGS != 0) try bw.writeAll(" SPLIT_SEGS");
855 if (hdr.flags & macho.MH_LAZY_INIT != 0) try writer.writeAll(" LAZY_INIT");854 if (hdr.flags & macho.MH_LAZY_INIT != 0) try bw.writeAll(" LAZY_INIT");
856 if (hdr.flags & macho.MH_TWOLEVEL != 0) try writer.writeAll(" TWOLEVEL");855 if (hdr.flags & macho.MH_TWOLEVEL != 0) try bw.writeAll(" TWOLEVEL");
857 if (hdr.flags & macho.MH_FORCE_FLAT != 0) try writer.writeAll(" FORCE_FLAT");856 if (hdr.flags & macho.MH_FORCE_FLAT != 0) try bw.writeAll(" FORCE_FLAT");
858 if (hdr.flags & macho.MH_NOMULTIDEFS != 0) try writer.writeAll(" NOMULTIDEFS");857 if (hdr.flags & macho.MH_NOMULTIDEFS != 0) try bw.writeAll(" NOMULTIDEFS");
859 if (hdr.flags & macho.MH_NOFIXPREBINDING != 0) try writer.writeAll(" NOFIXPREBINDING");858 if (hdr.flags & macho.MH_NOFIXPREBINDING != 0) try bw.writeAll(" NOFIXPREBINDING");
860 if (hdr.flags & macho.MH_PREBINDABLE != 0) try writer.writeAll(" PREBINDABLE");859 if (hdr.flags & macho.MH_PREBINDABLE != 0) try bw.writeAll(" PREBINDABLE");
861 if (hdr.flags & macho.MH_ALLMODSBOUND != 0) try writer.writeAll(" ALLMODSBOUND");860 if (hdr.flags & macho.MH_ALLMODSBOUND != 0) try bw.writeAll(" ALLMODSBOUND");
862 if (hdr.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) try writer.writeAll(" SUBSECTIONS_VIA_SYMBOLS");861 if (hdr.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) try bw.writeAll(" SUBSECTIONS_VIA_SYMBOLS");
863 if (hdr.flags & macho.MH_CANONICAL != 0) try writer.writeAll(" CANONICAL");862 if (hdr.flags & macho.MH_CANONICAL != 0) try bw.writeAll(" CANONICAL");
864 if (hdr.flags & macho.MH_WEAK_DEFINES != 0) try writer.writeAll(" WEAK_DEFINES");863 if (hdr.flags & macho.MH_WEAK_DEFINES != 0) try bw.writeAll(" WEAK_DEFINES");
865 if (hdr.flags & macho.MH_BINDS_TO_WEAK != 0) try writer.writeAll(" BINDS_TO_WEAK");864 if (hdr.flags & macho.MH_BINDS_TO_WEAK != 0) try bw.writeAll(" BINDS_TO_WEAK");
866 if (hdr.flags & macho.MH_ALLOW_STACK_EXECUTION != 0) try writer.writeAll(" ALLOW_STACK_EXECUTION");865 if (hdr.flags & macho.MH_ALLOW_STACK_EXECUTION != 0) try bw.writeAll(" ALLOW_STACK_EXECUTION");
867 if (hdr.flags & macho.MH_ROOT_SAFE != 0) try writer.writeAll(" ROOT_SAFE");866 if (hdr.flags & macho.MH_ROOT_SAFE != 0) try bw.writeAll(" ROOT_SAFE");
868 if (hdr.flags & macho.MH_SETUID_SAFE != 0) try writer.writeAll(" SETUID_SAFE");867 if (hdr.flags & macho.MH_SETUID_SAFE != 0) try bw.writeAll(" SETUID_SAFE");
869 if (hdr.flags & macho.MH_NO_REEXPORTED_DYLIBS != 0) try writer.writeAll(" NO_REEXPORTED_DYLIBS");868 if (hdr.flags & macho.MH_NO_REEXPORTED_DYLIBS != 0) try bw.writeAll(" NO_REEXPORTED_DYLIBS");
870 if (hdr.flags & macho.MH_PIE != 0) try writer.writeAll(" PIE");869 if (hdr.flags & macho.MH_PIE != 0) try bw.writeAll(" PIE");
871 if (hdr.flags & macho.MH_DEAD_STRIPPABLE_DYLIB != 0) try writer.writeAll(" DEAD_STRIPPABLE_DYLIB");870 if (hdr.flags & macho.MH_DEAD_STRIPPABLE_DYLIB != 0) try bw.writeAll(" DEAD_STRIPPABLE_DYLIB");
872 if (hdr.flags & macho.MH_HAS_TLV_DESCRIPTORS != 0) try writer.writeAll(" HAS_TLV_DESCRIPTORS");871 if (hdr.flags & macho.MH_HAS_TLV_DESCRIPTORS != 0) try bw.writeAll(" HAS_TLV_DESCRIPTORS");
873 if (hdr.flags & macho.MH_NO_HEAP_EXECUTION != 0) try writer.writeAll(" NO_HEAP_EXECUTION");872 if (hdr.flags & macho.MH_NO_HEAP_EXECUTION != 0) try bw.writeAll(" NO_HEAP_EXECUTION");
874 if (hdr.flags & macho.MH_APP_EXTENSION_SAFE != 0) try writer.writeAll(" APP_EXTENSION_SAFE");873 if (hdr.flags & macho.MH_APP_EXTENSION_SAFE != 0) try bw.writeAll(" APP_EXTENSION_SAFE");
875 if (hdr.flags & macho.MH_NLIST_OUTOFSYNC_WITH_DYLDINFO != 0) try writer.writeAll(" NLIST_OUTOFSYNC_WITH_DYLDINFO");874 if (hdr.flags & macho.MH_NLIST_OUTOFSYNC_WITH_DYLDINFO != 0) try bw.writeAll(" NLIST_OUTOFSYNC_WITH_DYLDINFO");
876 }875 }
877876
878 try writer.writeByte('\n');877 try bw.writeByte('\n');
879 }878 }
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 {
882 // print header first881 // print header first
883 try writer.print(882 try bw.print(
884 \\LC {d}883 \\LC {d}
885 \\cmd {s}884 \\cmd {s}
886 \\cmdsize {d}885 \\cmdsize {d}
...@@ -889,8 +888,8 @@ const MachODumper = struct {...@@ -889,8 +888,8 @@ const MachODumper = struct {
889 switch (lc.cmd()) {888 switch (lc.cmd()) {
890 .SEGMENT_64 => {889 .SEGMENT_64 => {
891 const seg = lc.cast(macho.segment_command_64).?;890 const seg = lc.cast(macho.segment_command_64).?;
892 try writer.writeByte('\n');891 try bw.writeByte('\n');
893 try writer.print(892 try bw.print(
894 \\segname {s}893 \\segname {s}
895 \\vmaddr {x}894 \\vmaddr {x}
896 \\vmsize {x}895 \\vmsize {x}
...@@ -905,8 +904,8 @@ const MachODumper = struct {...@@ -905,8 +904,8 @@ const MachODumper = struct {
905 });904 });
906905
907 for (lc.getSections()) |sect| {906 for (lc.getSections()) |sect| {
908 try writer.writeByte('\n');907 try bw.writeByte('\n');
909 try writer.print(908 try bw.print(
910 \\sectname {s}909 \\sectname {s}
911 \\addr {x}910 \\addr {x}
912 \\size {x}911 \\size {x}
...@@ -928,8 +927,8 @@ const MachODumper = struct {...@@ -928,8 +927,8 @@ const MachODumper = struct {
928 .REEXPORT_DYLIB,927 .REEXPORT_DYLIB,
929 => {928 => {
930 const dylib = lc.cast(macho.dylib_command).?;929 const dylib = lc.cast(macho.dylib_command).?;
931 try writer.writeByte('\n');930 try bw.writeByte('\n');
932 try writer.print(931 try bw.print(
933 \\name {s}932 \\name {s}
934 \\timestamp {d}933 \\timestamp {d}
935 \\current version {x}934 \\current version {x}
...@@ -944,16 +943,16 @@ const MachODumper = struct {...@@ -944,16 +943,16 @@ const MachODumper = struct {
944943
945 .MAIN => {944 .MAIN => {
946 const main = lc.cast(macho.entry_point_command).?;945 const main = lc.cast(macho.entry_point_command).?;
947 try writer.writeByte('\n');946 try bw.writeByte('\n');
948 try writer.print(947 try bw.print(
949 \\entryoff {x}948 \\entryoff {x}
950 \\stacksize {x}949 \\stacksize {x}
951 , .{ main.entryoff, main.stacksize });950 , .{ main.entryoff, main.stacksize });
952 },951 },
953952
954 .RPATH => {953 .RPATH => {
955 try writer.writeByte('\n');954 try bw.writeByte('\n');
956 try writer.print(955 try bw.print(
957 \\path {s}956 \\path {s}
958 , .{957 , .{
959 lc.getRpathPathName(),958 lc.getRpathPathName(),
...@@ -962,8 +961,8 @@ const MachODumper = struct {...@@ -962,8 +961,8 @@ const MachODumper = struct {
962961
963 .UUID => {962 .UUID => {
964 const uuid = lc.cast(macho.uuid_command).?;963 const uuid = lc.cast(macho.uuid_command).?;
965 try writer.writeByte('\n');964 try bw.writeByte('\n');
966 try writer.print("uuid {x}", .{std.fmt.fmtSliceHexLower(&uuid.uuid)});965 try bw.print("uuid {x}", .{&uuid.uuid});
967 },966 },
968967
969 .DATA_IN_CODE,968 .DATA_IN_CODE,
...@@ -971,8 +970,8 @@ const MachODumper = struct {...@@ -971,8 +970,8 @@ const MachODumper = struct {
971 .CODE_SIGNATURE,970 .CODE_SIGNATURE,
972 => {971 => {
973 const llc = lc.cast(macho.linkedit_data_command).?;972 const llc = lc.cast(macho.linkedit_data_command).?;
974 try writer.writeByte('\n');973 try bw.writeByte('\n');
975 try writer.print(974 try bw.print(
976 \\dataoff {x}975 \\dataoff {x}
977 \\datasize {x}976 \\datasize {x}
978 , .{ llc.dataoff, llc.datasize });977 , .{ llc.dataoff, llc.datasize });
...@@ -980,8 +979,8 @@ const MachODumper = struct {...@@ -980,8 +979,8 @@ const MachODumper = struct {
980979
981 .DYLD_INFO_ONLY => {980 .DYLD_INFO_ONLY => {
982 const dlc = lc.cast(macho.dyld_info_command).?;981 const dlc = lc.cast(macho.dyld_info_command).?;
983 try writer.writeByte('\n');982 try bw.writeByte('\n');
984 try writer.print(983 try bw.print(
985 \\rebaseoff {x}984 \\rebaseoff {x}
986 \\rebasesize {x}985 \\rebasesize {x}
987 \\bindoff {x}986 \\bindoff {x}
...@@ -1008,8 +1007,8 @@ const MachODumper = struct {...@@ -1008,8 +1007,8 @@ const MachODumper = struct {
10081007
1009 .SYMTAB => {1008 .SYMTAB => {
1010 const slc = lc.cast(macho.symtab_command).?;1009 const slc = lc.cast(macho.symtab_command).?;
1011 try writer.writeByte('\n');1010 try bw.writeByte('\n');
1012 try writer.print(1011 try bw.print(
1013 \\symoff {x}1012 \\symoff {x}
1014 \\nsyms {x}1013 \\nsyms {x}
1015 \\stroff {x}1014 \\stroff {x}
...@@ -1024,8 +1023,8 @@ const MachODumper = struct {...@@ -1024,8 +1023,8 @@ const MachODumper = struct {
10241023
1025 .DYSYMTAB => {1024 .DYSYMTAB => {
1026 const dlc = lc.cast(macho.dysymtab_command).?;1025 const dlc = lc.cast(macho.dysymtab_command).?;
1027 try writer.writeByte('\n');1026 try bw.writeByte('\n');
1028 try writer.print(1027 try bw.print(
1029 \\ilocalsym {x}1028 \\ilocalsym {x}
1030 \\nlocalsym {x}1029 \\nlocalsym {x}
1031 \\iextdefsym {x}1030 \\iextdefsym {x}
...@@ -1048,8 +1047,8 @@ const MachODumper = struct {...@@ -1048,8 +1047,8 @@ const MachODumper = struct {
10481047
1049 .BUILD_VERSION => {1048 .BUILD_VERSION => {
1050 const blc = lc.cast(macho.build_version_command).?;1049 const blc = lc.cast(macho.build_version_command).?;
1051 try writer.writeByte('\n');1050 try bw.writeByte('\n');
1052 try writer.print(1051 try bw.print(
1053 \\platform {s}1052 \\platform {s}
1054 \\minos {d}.{d}.{d}1053 \\minos {d}.{d}.{d}
1055 \\sdk {d}.{d}.{d}1054 \\sdk {d}.{d}.{d}
...@@ -1065,12 +1064,12 @@ const MachODumper = struct {...@@ -1065,12 +1064,12 @@ const MachODumper = struct {
1065 blc.ntools,1064 blc.ntools,
1066 });1065 });
1067 for (lc.getBuildVersionTools()) |tool| {1066 for (lc.getBuildVersionTools()) |tool| {
1068 try writer.writeByte('\n');1067 try bw.writeByte('\n');
1069 switch (tool.tool) {1068 switch (tool.tool) {
1070 .CLANG, .SWIFT, .LD, .LLD, .ZIG => try writer.print("tool {s}\n", .{@tagName(tool.tool)}),1069 .CLANG, .SWIFT, .LD, .LLD, .ZIG => try bw.print("tool {s}\n", .{@tagName(tool.tool)}),
1071 else => |x| try writer.print("tool {d}\n", .{@intFromEnum(x)}),1070 else => |x| try bw.print("tool {d}\n", .{@intFromEnum(x)}),
1072 }1071 }
1073 try writer.print(1072 try bw.print(
1074 \\version {d}.{d}.{d}1073 \\version {d}.{d}.{d}
1075 , .{1074 , .{
1076 tool.version >> 16,1075 tool.version >> 16,
...@@ -1086,8 +1085,8 @@ const MachODumper = struct {...@@ -1086,8 +1085,8 @@ const MachODumper = struct {
1086 .VERSION_MIN_TVOS,1085 .VERSION_MIN_TVOS,
1087 => {1086 => {
1088 const vlc = lc.cast(macho.version_min_command).?;1087 const vlc = lc.cast(macho.version_min_command).?;
1089 try writer.writeByte('\n');1088 try bw.writeByte('\n');
1090 try writer.print(1089 try bw.print(
1091 \\version {d}.{d}.{d}1090 \\version {d}.{d}.{d}
1092 \\sdk {d}.{d}.{d}1091 \\sdk {d}.{d}.{d}
1093 , .{1092 , .{
...@@ -1104,8 +1103,8 @@ const MachODumper = struct {...@@ -1104,8 +1103,8 @@ const MachODumper = struct {
1104 }1103 }
1105 }1104 }
11061105
1107 fn dumpSymtab(ctx: ObjectContext, writer: anytype) !void {1106 fn dumpSymtab(ctx: ObjectContext, bw: *Writer) !void {
1108 try writer.writeAll(symtab_label ++ "\n");1107 try bw.writeAll(symtab_label ++ "\n");
11091108
1110 for (ctx.symtab.items) |sym| {1109 for (ctx.symtab.items) |sym| {
1111 const sym_name = ctx.getString(sym.n_strx);1110 const sym_name = ctx.getString(sym.n_strx);
...@@ -1120,32 +1119,32 @@ const MachODumper = struct {...@@ -1120,32 +1119,32 @@ const MachODumper = struct {
1120 macho.N_STSYM => "STSYM",1119 macho.N_STSYM => "STSYM",
1121 else => "UNKNOWN STAB",1120 else => "UNKNOWN STAB",
1122 };1121 };
1123 try writer.print("{x}", .{sym.n_value});1122 try bw.print("{x}", .{sym.n_value});
1124 if (sym.n_sect > 0) {1123 if (sym.n_sect > 0) {
1125 const sect = ctx.sections.items[sym.n_sect - 1];1124 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() });
1127 }1126 }
1128 try writer.print(" {s} (stab) {s}\n", .{ tt, sym_name });1127 try bw.print(" {s} (stab) {s}\n", .{ tt, sym_name });
1129 } else if (sym.sect()) {1128 } else if (sym.sect()) {
1130 const sect = ctx.sections.items[sym.n_sect - 1];1129 const sect = ctx.sections.items[sym.n_sect - 1];
1131 try writer.print("{x} ({s},{s})", .{1130 try bw.print("{x} ({s},{s})", .{
1132 sym.n_value,1131 sym.n_value,
1133 sect.segName(),1132 sect.segName(),
1134 sect.sectName(),1133 sect.sectName(),
1135 });1134 });
1136 if (sym.n_desc & macho.REFERENCED_DYNAMICALLY != 0) try writer.writeAll(" [referenced dynamically]");1135 if (sym.n_desc & macho.REFERENCED_DYNAMICALLY != 0) try bw.writeAll(" [referenced dynamically]");
1137 if (sym.weakDef()) try writer.writeAll(" weak");1136 if (sym.weakDef()) try bw.writeAll(" weak");
1138 if (sym.weakRef()) try writer.writeAll(" weakref");1137 if (sym.weakRef()) try bw.writeAll(" weakref");
1139 if (sym.ext()) {1138 if (sym.ext()) {
1140 if (sym.pext()) try writer.writeAll(" private");1139 if (sym.pext()) try bw.writeAll(" private");
1141 try writer.writeAll(" external");1140 try bw.writeAll(" external");
1142 } else if (sym.pext()) try writer.writeAll(" (was private external)");1141 } else if (sym.pext()) try bw.writeAll(" (was private external)");
1143 try writer.print(" {s}\n", .{sym_name});1142 try bw.print(" {s}\n", .{sym_name});
1144 } else if (sym.tentative()) {1143 } else if (sym.tentative()) {
1145 const alignment = (sym.n_desc >> 8) & 0x0F;1144 const alignment = (sym.n_desc >> 8) & 0x0F;
1146 try writer.print(" 0x{x:0>16} (common) (alignment 2^{d})", .{ sym.n_value, alignment });1145 try bw.print(" 0x{x:0>16} (common) (alignment 2^{d})", .{ sym.n_value, alignment });
1147 if (sym.ext()) try writer.writeAll(" external");1146 if (sym.ext()) try bw.writeAll(" external");
1148 try writer.print(" {s}\n", .{sym_name});1147 try bw.print(" {s}\n", .{sym_name});
1149 } else if (sym.undf()) {1148 } else if (sym.undf()) {
1150 const ordinal = @divFloor(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);1149 const ordinal = @divFloor(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);
1151 const import_name = blk: {1150 const import_name = blk: {
...@@ -1164,10 +1163,10 @@ const MachODumper = struct {...@@ -1164,10 +1163,10 @@ const MachODumper = struct {
1164 const ext = mem.lastIndexOfScalar(u8, basename, '.') orelse basename.len;1163 const ext = mem.lastIndexOfScalar(u8, basename, '.') orelse basename.len;
1165 break :blk basename[0..ext];1164 break :blk basename[0..ext];
1166 };1165 };
1167 try writer.writeAll("(undefined)");1166 try bw.writeAll("(undefined)");
1168 if (sym.weakRef()) try writer.writeAll(" weakref");1167 if (sym.weakRef()) try bw.writeAll(" weakref");
1169 if (sym.ext()) try writer.writeAll(" external");1168 if (sym.ext()) try bw.writeAll(" external");
1170 try writer.print(" {s} (from {s})\n", .{1169 try bw.print(" {s} (from {s})\n", .{
1171 sym_name,1170 sym_name,
1172 import_name,1171 import_name,
1173 });1172 });
...@@ -1175,8 +1174,8 @@ const MachODumper = struct {...@@ -1175,8 +1174,8 @@ const MachODumper = struct {
1175 }1174 }
1176 }1175 }
11771176
1178 fn dumpIndirectSymtab(ctx: ObjectContext, writer: anytype) !void {1177 fn dumpIndirectSymtab(ctx: ObjectContext, bw: *Writer) !void {
1179 try writer.writeAll(indirect_symtab_label ++ "\n");1178 try bw.writeAll(indirect_symtab_label ++ "\n");
11801179
1181 var sects_buffer: [3]macho.section_64 = undefined;1180 var sects_buffer: [3]macho.section_64 = undefined;
1182 const sects = blk: {1181 const sects = blk: {
...@@ -1214,35 +1213,33 @@ const MachODumper = struct {...@@ -1214,35 +1213,33 @@ const MachODumper = struct {
1214 break :blk @sizeOf(u64);1213 break :blk @sizeOf(u64);
1215 };1214 };
12161215
1217 try writer.print("{s},{s}\n", .{ sect.segName(), sect.sectName() });1216 try bw.print("{s},{s}\n", .{ sect.segName(), sect.sectName() });
1218 try writer.print("nentries {d}\n", .{end - start});1217 try bw.print("nentries {d}\n", .{end - start});
1219 for (ctx.indsymtab.items[start..end], 0..) |index, j| {1218 for (ctx.indsymtab.items[start..end], 0..) |index, j| {
1220 const sym = ctx.symtab.items[index];1219 const sym = ctx.symtab.items[index];
1221 const addr = sect.addr + entry_size * j;1220 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) });
1223 }1222 }
1224 }1223 }
1225 }1224 }
12261225
1227 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, writer: anytype) !void {1226 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1228 var rebases = std.ArrayList(u64).init(ctx.gpa);1227 var rebases: std.ArrayList(u64) = .init(ctx.gpa);
1229 defer rebases.deinit();1228 defer rebases.deinit();
1230 try ctx.parseRebaseInfo(data, &rebases);1229 try ctx.parseRebaseInfo(data, &rebases);
1231 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));1230 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
1232 for (rebases.items) |addr| {1231 for (rebases.items) |addr| {
1233 try writer.print("0x{x}\n", .{addr});1232 try bw.print("0x{x}\n", .{addr});
1234 }1233 }
1235 }1234 }
12361235
1237 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {1236 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
1238 var stream = std.io.fixedBufferStream(data);1237 var br: std.io.Reader = .fixed(data);
1239 var creader = std.io.countingReader(stream.reader());
1240 const reader = creader.reader();
12411238
1242 var seg_id: ?u8 = null;1239 var seg_id: ?u8 = null;
1243 var offset: u64 = 0;1240 var offset: u64 = 0;
1244 while (true) {1241 while (true) {
1245 const byte = reader.readByte() catch break;1242 const byte = br.takeByte() catch break;
1246 const opc = byte & macho.REBASE_OPCODE_MASK;1243 const opc = byte & macho.REBASE_OPCODE_MASK;
1247 const imm = byte & macho.REBASE_IMMEDIATE_MASK;1244 const imm = byte & macho.REBASE_IMMEDIATE_MASK;
1248 switch (opc) {1245 switch (opc) {
...@@ -1250,17 +1247,17 @@ const MachODumper = struct {...@@ -1250,17 +1247,17 @@ const MachODumper = struct {
1250 macho.REBASE_OPCODE_SET_TYPE_IMM => {},1247 macho.REBASE_OPCODE_SET_TYPE_IMM => {},
1251 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {1248 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
1252 seg_id = imm;1249 seg_id = imm;
1253 offset = try std.leb.readUleb128(u64, reader);1250 offset = try br.takeLeb128(u64);
1254 },1251 },
1255 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {1252 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {
1256 offset += imm * @sizeOf(u64);1253 offset += imm * @sizeOf(u64);
1257 },1254 },
1258 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {1255 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {
1259 const addend = try std.leb.readUleb128(u64, reader);1256 const addend = try br.takeLeb128(u64);
1260 offset += addend;1257 offset += addend;
1261 },1258 },
1262 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {1259 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {
1263 const addend = try std.leb.readUleb128(u64, reader);1260 const addend = try br.takeLeb128(u64);
1264 const seg = ctx.segments.items[seg_id.?];1261 const seg = ctx.segments.items[seg_id.?];
1265 const addr = seg.vmaddr + offset;1262 const addr = seg.vmaddr + offset;
1266 try rebases.append(addr);1263 try rebases.append(addr);
...@@ -1277,11 +1274,11 @@ const MachODumper = struct {...@@ -1277,11 +1274,11 @@ const MachODumper = struct {
1277 ntimes = imm;1274 ntimes = imm;
1278 },1275 },
1279 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {1276 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {
1280 ntimes = try std.leb.readUleb128(u64, reader);1277 ntimes = try br.takeLeb128(u64);
1281 },1278 },
1282 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {1279 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {
1283 ntimes = try std.leb.readUleb128(u64, reader);1280 ntimes = try br.takeLeb128(u64);
1284 skip = try std.leb.readUleb128(u64, reader);1281 skip = try br.takeLeb128(u64);
1285 },1282 },
1286 else => unreachable,1283 else => unreachable,
1287 }1284 }
...@@ -1323,8 +1320,8 @@ const MachODumper = struct {...@@ -1323,8 +1320,8 @@ const MachODumper = struct {
1323 };1320 };
1324 };1321 };
13251322
1326 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, writer: anytype) !void {1323 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1327 var bindings = std.ArrayList(Binding).init(ctx.gpa);1324 var bindings: std.ArrayList(Binding) = .init(ctx.gpa);
1328 defer {1325 defer {
1329 for (bindings.items) |*b| {1326 for (bindings.items) |*b| {
1330 b.deinit(ctx.gpa);1327 b.deinit(ctx.gpa);
...@@ -1334,22 +1331,20 @@ const MachODumper = struct {...@@ -1334,22 +1331,20 @@ const MachODumper = struct {
1334 try ctx.parseBindInfo(data, &bindings);1331 try ctx.parseBindInfo(data, &bindings);
1335 mem.sort(Binding, bindings.items, {}, Binding.lessThan);1332 mem.sort(Binding, bindings.items, {}, Binding.lessThan);
1336 for (bindings.items) |binding| {1333 for (bindings.items) |binding| {
1337 try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });1334 try bw.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });
1338 try writer.writeAll(" (");1335 try bw.writeAll(" (");
1339 switch (binding.tag) {1336 switch (binding.tag) {
1340 .self => try writer.writeAll("self"),1337 .self => try bw.writeAll("self"),
1341 .exe => try writer.writeAll("main executable"),1338 .exe => try bw.writeAll("main executable"),
1342 .flat => try writer.writeAll("flat lookup"),1339 .flat => try bw.writeAll("flat lookup"),
1343 .ord => try writer.writeAll(std.fs.path.basename(ctx.imports.items[binding.ordinal - 1])),1340 .ord => try bw.writeAll(std.fs.path.basename(ctx.imports.items[binding.ordinal - 1])),
1344 }1341 }
1345 try writer.print(") {s}\n", .{binding.name});1342 try bw.print(") {s}\n", .{binding.name});
1346 }1343 }
1347 }1344 }
13481345
1349 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {1346 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
1350 var stream = std.io.fixedBufferStream(data);1347 var br: std.io.Reader = .fixed(data);
1351 var creader = std.io.countingReader(stream.reader());
1352 const reader = creader.reader();
13531348
1354 var seg_id: ?u8 = null;1349 var seg_id: ?u8 = null;
1355 var tag: Binding.Tag = .self;1350 var tag: Binding.Tag = .self;
...@@ -1357,11 +1352,10 @@ const MachODumper = struct {...@@ -1357,11 +1352,10 @@ const MachODumper = struct {
1357 var offset: u64 = 0;1352 var offset: u64 = 0;
1358 var addend: i64 = 0;1353 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);
1361 defer name_buf.deinit();1356 defer name_buf.deinit();
13621357
1363 while (true) {1358 while (br.takeByte()) |byte| {
1364 const byte = reader.readByte() catch break;
1365 const opc = byte & macho.BIND_OPCODE_MASK;1359 const opc = byte & macho.BIND_OPCODE_MASK;
1366 const imm = byte & macho.BIND_IMMEDIATE_MASK;1360 const imm = byte & macho.BIND_IMMEDIATE_MASK;
1367 switch (opc) {1361 switch (opc) {
...@@ -1382,18 +1376,19 @@ const MachODumper = struct {...@@ -1382,18 +1376,19 @@ const MachODumper = struct {
1382 },1376 },
1383 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {1377 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
1384 seg_id = imm;1378 seg_id = imm;
1385 offset = try std.leb.readUleb128(u64, reader);1379 offset = try br.takeLeb128(u64);
1386 },1380 },
1387 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {1381 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
1388 name_buf.clearRetainingCapacity();1382 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));
1390 try name_buf.append(0);1385 try name_buf.append(0);
1391 },1386 },
1392 macho.BIND_OPCODE_SET_ADDEND_SLEB => {1387 macho.BIND_OPCODE_SET_ADDEND_SLEB => {
1393 addend = try std.leb.readIleb128(i64, reader);1388 addend = try br.takeLeb128(i64);
1394 },1389 },
1395 macho.BIND_OPCODE_ADD_ADDR_ULEB => {1390 macho.BIND_OPCODE_ADD_ADDR_ULEB => {
1396 const x = try std.leb.readUleb128(u64, reader);1391 const x = try br.takeLeb128(u64);
1397 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));1392 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));
1398 },1393 },
1399 macho.BIND_OPCODE_DO_BIND,1394 macho.BIND_OPCODE_DO_BIND,
...@@ -1408,14 +1403,14 @@ const MachODumper = struct {...@@ -1408,14 +1403,14 @@ const MachODumper = struct {
1408 switch (opc) {1403 switch (opc) {
1409 macho.BIND_OPCODE_DO_BIND => {},1404 macho.BIND_OPCODE_DO_BIND => {},
1410 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {1405 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
1411 add_addr = try std.leb.readUleb128(u64, reader);1406 add_addr = try br.takeLeb128(u64);
1412 },1407 },
1413 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {1408 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
1414 add_addr = imm * @sizeOf(u64);1409 add_addr = imm * @sizeOf(u64);
1415 },1410 },
1416 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {1411 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
1417 count = try std.leb.readUleb128(u64, reader);1412 count = try br.takeLeb128(u64);
1418 skip = try std.leb.readUleb128(u64, reader);1413 skip = try br.takeLeb128(u64);
1419 },1414 },
1420 else => unreachable,1415 else => unreachable,
1421 }1416 }
...@@ -1436,18 +1431,18 @@ const MachODumper = struct {...@@ -1436,18 +1431,18 @@ const MachODumper = struct {
1436 },1431 },
1437 else => break,1432 else => break,
1438 }1433 }
1439 }1434 } else |_| {}
1440 }1435 }
14411436
1442 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, writer: anytype) !void {1437 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *Writer) !void {
1443 const seg = ctx.getSegmentByName("__TEXT") orelse return;1438 const seg = ctx.getSegmentByName("__TEXT") orelse return;
14441439
1445 var arena = std.heap.ArenaAllocator.init(ctx.gpa);1440 var arena = std.heap.ArenaAllocator.init(ctx.gpa);
1446 defer arena.deinit();1441 defer arena.deinit();
14471442
1448 var exports = std.ArrayList(Export).init(arena.allocator());1443 var exports: std.ArrayList(Export) = .init(arena.allocator());
1449 var it = TrieIterator{ .data = data };1444 var br: std.io.Reader = .fixed(data);
1450 try parseTrieNode(arena.allocator(), &it, "", &exports);1445 try parseTrieNode(arena.allocator(), &br, "", &exports);
14511446
1452 mem.sort(Export, exports.items, {}, Export.lessThan);1447 mem.sort(Export, exports.items, {}, Export.lessThan);
14531448
...@@ -1456,66 +1451,26 @@ const MachODumper = struct {...@@ -1456,66 +1451,26 @@ const MachODumper = struct {
1456 .@"export" => {1451 .@"export" => {
1457 const info = exp.data.@"export";1452 const info = exp.data.@"export";
1458 if (info.kind != .regular or info.weak) {1453 if (info.kind != .regular or info.weak) {
1459 try writer.writeByte('[');1454 try bw.writeByte('[');
1460 }1455 }
1461 switch (info.kind) {1456 switch (info.kind) {
1462 .regular => {},1457 .regular => {},
1463 .absolute => try writer.writeAll("ABS, "),1458 .absolute => try bw.writeAll("ABS, "),
1464 .tlv => try writer.writeAll("THREAD_LOCAL, "),1459 .tlv => try bw.writeAll("THREAD_LOCAL, "),
1465 }1460 }
1466 if (info.weak) try writer.writeAll("WEAK");1461 if (info.weak) try bw.writeAll("WEAK");
1467 if (info.kind != .regular or info.weak) {1462 if (info.kind != .regular or info.weak) {
1468 try writer.writeAll("] ");1463 try bw.writeAll("] ");
1469 }1464 }
1470 try writer.print("{x} ", .{seg.vmaddr + info.vmoffset});1465 try bw.print("{x} ", .{seg.vmaddr + info.vmoffset});
1471 },1466 },
1472 else => {},1467 else => {},
1473 }1468 }
14741469
1475 try writer.print("{s}\n", .{exp.name});1470 try bw.print("{s}\n", .{exp.name});
1476 }1471 }
1477 }1472 }
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
1519 const Export = struct {1474 const Export = struct {
1520 name: []const u8,1475 name: []const u8,
1521 tag: enum { @"export", reexport, stub_resolver },1476 tag: enum { @"export", reexport, stub_resolver },
...@@ -1555,17 +1510,17 @@ const MachODumper = struct {...@@ -1555,17 +1510,17 @@ const MachODumper = struct {
15551510
1556 fn parseTrieNode(1511 fn parseTrieNode(
1557 arena: Allocator,1512 arena: Allocator,
1558 it: *TrieIterator,1513 br: *std.io.Reader,
1559 prefix: []const u8,1514 prefix: []const u8,
1560 exports: *std.ArrayList(Export),1515 exports: *std.ArrayList(Export),
1561 ) !void {1516 ) !void {
1562 const size = try it.readUleb128();1517 const size = try br.takeLeb128(u64);
1563 if (size > 0) {1518 if (size > 0) {
1564 const flags = try it.readUleb128();1519 const flags = try br.takeLeb128(u8);
1565 switch (flags) {1520 switch (flags) {
1566 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {1521 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {
1567 const ord = try it.readUleb128();1522 const ord = try br.takeLeb128(u64);
1568 const name = try arena.dupe(u8, try it.readString());1523 const name = try br.takeSentinel(0);
1569 try exports.append(.{1524 try exports.append(.{
1570 .name = if (name.len > 0) name else prefix,1525 .name = if (name.len > 0) name else prefix,
1571 .tag = .reexport,1526 .tag = .reexport,
...@@ -1573,8 +1528,8 @@ const MachODumper = struct {...@@ -1573,8 +1528,8 @@ const MachODumper = struct {
1573 });1528 });
1574 },1529 },
1575 macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER => {1530 macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER => {
1576 const stub_offset = try it.readUleb128();1531 const stub_offset = try br.takeLeb128(u64);
1577 const resolver_offset = try it.readUleb128();1532 const resolver_offset = try br.takeLeb128(u64);
1578 try exports.append(.{1533 try exports.append(.{
1579 .name = prefix,1534 .name = prefix,
1580 .tag = .stub_resolver,1535 .tag = .stub_resolver,
...@@ -1585,7 +1540,7 @@ const MachODumper = struct {...@@ -1585,7 +1540,7 @@ const MachODumper = struct {
1585 });1540 });
1586 },1541 },
1587 else => {1542 else => {
1588 const vmoff = try it.readUleb128();1543 const vmoff = try br.takeLeb128(u64);
1589 try exports.append(.{1544 try exports.append(.{
1590 .name = prefix,1545 .name = prefix,
1591 .tag = .@"export",1546 .tag = .@"export",
...@@ -1604,21 +1559,21 @@ const MachODumper = struct {...@@ -1604,21 +1559,21 @@ const MachODumper = struct {
1604 }1559 }
1605 }1560 }
16061561
1607 const nedges = try it.readByte();1562 const nedges = try br.takeByte();
1608 for (0..nedges) |_| {1563 for (0..nedges) |_| {
1609 const label = try it.readString();1564 const label = try br.takeSentinel(0);
1610 const off = try it.readUleb128();1565 const off = try br.takeLeb128(usize);
1611 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });1566 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });
1612 const curr = it.pos;1567 const seek = br.seek;
1613 it.pos = off;1568 br.seek = off;
1614 try parseTrieNode(arena, it, prefix_label, exports);1569 try parseTrieNode(arena, br, prefix_label, exports);
1615 it.pos = curr;1570 br.seek = seek;
1616 }1571 }
1617 }1572 }
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 {
1620 const data = ctx.data[sect.offset..][0..sect.size];1575 const data = ctx.data[sect.offset..][0..sect.size];
1621 try writer.print("{s}", .{data});1576 try bw.print("{s}", .{data});
1622 }1577 }
1623 };1578 };
16241579
...@@ -1632,29 +1587,30 @@ const MachODumper = struct {...@@ -1632,29 +1587,30 @@ const MachODumper = struct {
1632 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };1587 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };
1633 try ctx.parse();1588 try ctx.parse();
16341589
1635 var output = std.ArrayList(u8).init(gpa);1590 var aw: std.io.Writer.Allocating = .init(gpa);
1636 const writer = output.writer();1591 defer aw.deinit();
1592 const bw = &aw.interface;
16371593
1638 switch (check.kind) {1594 switch (check.kind) {
1639 .headers => {1595 .headers => {
1640 try ObjectContext.dumpHeader(ctx.header, writer);1596 try ObjectContext.dumpHeader(ctx.header, bw);
16411597
1642 var it = ctx.getLoadCommandIterator();1598 var it = ctx.getLoadCommandIterator();
1643 var i: usize = 0;1599 var i: usize = 0;
1644 while (it.next()) |cmd| {1600 while (it.next()) |cmd| {
1645 try ObjectContext.dumpLoadCommand(cmd, i, writer);1601 try ObjectContext.dumpLoadCommand(cmd, i, bw);
1646 try writer.writeByte('\n');1602 try bw.writeByte('\n');
16471603
1648 i += 1;1604 i += 1;
1649 }1605 }
1650 },1606 },
16511607
1652 .symtab => if (ctx.symtab.items.len > 0) {1608 .symtab => if (ctx.symtab.items.len > 0) {
1653 try ctx.dumpSymtab(writer);1609 try ctx.dumpSymtab(bw);
1654 } else return step.fail("no symbol table found", .{}),1610 } else return step.fail("no symbol table found", .{}),
16551611
1656 .indirect_symtab => if (ctx.symtab.items.len > 0 and ctx.indsymtab.items.len > 0) {1612 .indirect_symtab => if (ctx.symtab.items.len > 0 and ctx.indsymtab.items.len > 0) {
1657 try ctx.dumpIndirectSymtab(writer);1613 try ctx.dumpIndirectSymtab(bw);
1658 } else return step.fail("no indirect symbol table found", .{}),1614 } else return step.fail("no indirect symbol table found", .{}),
16591615
1660 .dyld_rebase,1616 .dyld_rebase,
...@@ -1669,26 +1625,26 @@ const MachODumper = struct {...@@ -1669,26 +1625,26 @@ const MachODumper = struct {
1669 switch (check.kind) {1625 switch (check.kind) {
1670 .dyld_rebase => if (lc.rebase_size > 0) {1626 .dyld_rebase => if (lc.rebase_size > 0) {
1671 const data = ctx.data[lc.rebase_off..][0..lc.rebase_size];1627 const data = ctx.data[lc.rebase_off..][0..lc.rebase_size];
1672 try writer.writeAll(dyld_rebase_label ++ "\n");1628 try bw.writeAll(dyld_rebase_label ++ "\n");
1673 try ctx.dumpRebaseInfo(data, writer);1629 try ctx.dumpRebaseInfo(data, bw);
1674 } else return step.fail("no rebase data found", .{}),1630 } else return step.fail("no rebase data found", .{}),
16751631
1676 .dyld_bind => if (lc.bind_size > 0) {1632 .dyld_bind => if (lc.bind_size > 0) {
1677 const data = ctx.data[lc.bind_off..][0..lc.bind_size];1633 const data = ctx.data[lc.bind_off..][0..lc.bind_size];
1678 try writer.writeAll(dyld_bind_label ++ "\n");1634 try bw.writeAll(dyld_bind_label ++ "\n");
1679 try ctx.dumpBindInfo(data, writer);1635 try ctx.dumpBindInfo(data, bw);
1680 } else return step.fail("no bind data found", .{}),1636 } else return step.fail("no bind data found", .{}),
16811637
1682 .dyld_weak_bind => if (lc.weak_bind_size > 0) {1638 .dyld_weak_bind => if (lc.weak_bind_size > 0) {
1683 const data = ctx.data[lc.weak_bind_off..][0..lc.weak_bind_size];1639 const data = ctx.data[lc.weak_bind_off..][0..lc.weak_bind_size];
1684 try writer.writeAll(dyld_weak_bind_label ++ "\n");1640 try bw.writeAll(dyld_weak_bind_label ++ "\n");
1685 try ctx.dumpBindInfo(data, writer);1641 try ctx.dumpBindInfo(data, bw);
1686 } else return step.fail("no weak bind data found", .{}),1642 } else return step.fail("no weak bind data found", .{}),
16871643
1688 .dyld_lazy_bind => if (lc.lazy_bind_size > 0) {1644 .dyld_lazy_bind => if (lc.lazy_bind_size > 0) {
1689 const data = ctx.data[lc.lazy_bind_off..][0..lc.lazy_bind_size];1645 const data = ctx.data[lc.lazy_bind_off..][0..lc.lazy_bind_size];
1690 try writer.writeAll(dyld_lazy_bind_label ++ "\n");1646 try bw.writeAll(dyld_lazy_bind_label ++ "\n");
1691 try ctx.dumpBindInfo(data, writer);1647 try ctx.dumpBindInfo(data, bw);
1692 } else return step.fail("no lazy bind data found", .{}),1648 } else return step.fail("no lazy bind data found", .{}),
16931649
1694 else => unreachable,1650 else => unreachable,
...@@ -1700,8 +1656,8 @@ const MachODumper = struct {...@@ -1700,8 +1656,8 @@ const MachODumper = struct {
1700 const lc = cmd.cast(macho.dyld_info_command).?;1656 const lc = cmd.cast(macho.dyld_info_command).?;
1701 if (lc.export_size > 0) {1657 if (lc.export_size > 0) {
1702 const data = ctx.data[lc.export_off..][0..lc.export_size];1658 const data = ctx.data[lc.export_off..][0..lc.export_size];
1703 try writer.writeAll(exports_label ++ "\n");1659 try bw.writeAll(exports_label ++ "\n");
1704 try ctx.dumpExportsTrie(data, writer);1660 try ctx.dumpExportsTrie(data, bw);
1705 break :blk;1661 break :blk;
1706 }1662 }
1707 }1663 }
...@@ -1709,20 +1665,20 @@ const MachODumper = struct {...@@ -1709,20 +1665,20 @@ const MachODumper = struct {
1709 },1665 },
17101666
1711 .dump_section => {1667 .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);
1713 const sep_index = mem.indexOfScalar(u8, name, ',') orelse1669 const sep_index = mem.indexOfScalar(u8, name, ',') orelse
1714 return step.fail("invalid section name: {s}", .{name});1670 return step.fail("invalid section name: {s}", .{name});
1715 const segname = name[0..sep_index];1671 const segname = name[0..sep_index];
1716 const sectname = name[sep_index + 1 ..];1672 const sectname = name[sep_index + 1 ..];
1717 const sect = ctx.getSectionByName(segname, sectname) orelse1673 const sect = ctx.getSectionByName(segname, sectname) orelse
1718 return step.fail("section '{s}' not found", .{name});1674 return step.fail("section '{s}' not found", .{name});
1719 try ctx.dumpSection(sect, writer);1675 try ctx.dumpSection(sect, bw);
1720 },1676 },
17211677
1722 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),1678 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),
1723 }1679 }
17241680
1725 return output.toOwnedSlice();1681 return aw.toOwnedSlice();
1726 }1682 }
1727};1683};
17281684
...@@ -1741,161 +1697,138 @@ const ElfDumper = struct {...@@ -1741,161 +1697,138 @@ const ElfDumper = struct {
17411697
1742 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1698 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1743 const gpa = step.owner.allocator;1699 const gpa = step.owner.allocator;
1744 var stream = std.io.fixedBufferStream(bytes);1700 var br: std.io.Reader = .fixed(bytes);
1745 const reader = stream.reader();
17461701
1747 const magic = try reader.readBytesNoEof(elf.ARMAG.len);1702 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
1748 if (!mem.eql(u8, &magic, elf.ARMAG)) {
1749 return error.InvalidArchiveMagicNumber;
1750 }
17511703
1752 var ctx = ArchiveContext{1704 var ctx: ArchiveContext = .{
1753 .gpa = gpa,1705 .gpa = gpa,
1754 .data = bytes,1706 .data = bytes,
1755 .strtab = &[0]u8{},1707 .symtab = &.{},
1708 .strtab = &.{},
1709 .objects = .empty,
1756 };1710 };
1757 defer {1711 defer ctx.deinit();
1758 for (ctx.objects.items) |*object| {
1759 gpa.free(object.name);
1760 }
1761 ctx.objects.deinit(gpa);
1762 }
17631712
1764 while (true) {1713 while (br.seek < bytes.len) {
1765 if (stream.pos >= ctx.data.len) break;1714 const hdr_seek = std.mem.alignForward(usize, br.seek, 2);
1766 if (!mem.isAligned(stream.pos, 2)) stream.pos += 1;1715 br.seek = hdr_seek;
17671716 const hdr = try br.takeStruct(elf.ar_hdr);
1768 const hdr = try reader.readStruct(elf.ar_hdr);
17691717
1770 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) return error.InvalidArchiveHeaderMagicNumber;1718 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) return error.InvalidArchiveHeaderMagicNumber;
17711719
1772 const size = try hdr.size();1720 const data = try br.take(try hdr.size());
1773 defer {
1774 _ = stream.seekBy(size) catch {};
1775 }
17761721
1777 if (hdr.isSymtab()) {1722 if (hdr.isSymtab()) {
1778 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p32);1723 try ctx.parseSymtab(data, .p32);
1779 continue;1724 continue;
1780 }1725 }
1781 if (hdr.isSymtab64()) {1726 if (hdr.isSymtab64()) {
1782 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p64);1727 try ctx.parseSymtab(data, .p64);
1783 continue;1728 continue;
1784 }1729 }
1785 if (hdr.isStrtab()) {1730 if (hdr.isStrtab()) {
1786 ctx.strtab = ctx.data[stream.pos..][0..size];1731 ctx.strtab = data;
1787 continue;1732 continue;
1788 }1733 }
1789 if (hdr.isSymdef() or hdr.isSymdefSorted()) continue;1734 if (hdr.isSymdef() or hdr.isSymdefSorted()) continue;
17901735
1791 const name = if (hdr.name()) |name|1736 const name = hdr.name() orelse ctx.getString((try hdr.nameOffset()).?);
1792 try gpa.dupe(u8, name)1737 try ctx.objects.putNoClobber(gpa, hdr_seek, .{
1793 else if (try hdr.nameOffset()) |off|1738 .name = name,
1794 try gpa.dupe(u8, ctx.getString(off))1739 .data = data,
1795 else1740 });
1796 unreachable;
1797
1798 try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size });
1799 }1741 }
18001742
1801 var output = std.ArrayList(u8).init(gpa);1743 var aw: std.io.Writer.Allocating = .init(gpa);
1802 const writer = output.writer();1744 defer aw.deinit();
1745 const bw = &aw.interface;
18031746
1804 switch (check.kind) {1747 switch (check.kind) {
1805 .archive_symtab => if (ctx.symtab.items.len > 0) {1748 .archive_symtab => if (ctx.symtab.len > 0) {
1806 try ctx.dumpSymtab(writer);1749 try ctx.dumpSymtab(bw);
1807 } else return step.fail("no archive symbol table found", .{}),1750 } else return step.fail("no archive symbol table found", .{}),
18081751
1809 else => if (ctx.objects.items.len > 0) {1752 else => if (ctx.objects.count() > 0) {
1810 try ctx.dumpObjects(step, check, writer);1753 try ctx.dumpObjects(step, check, bw);
1811 } else return step.fail("empty archive", .{}),1754 } else return step.fail("empty archive", .{}),
1812 }1755 }
18131756
1814 return output.toOwnedSlice();1757 return aw.toOwnedSlice();
1815 }1758 }
18161759
1817 const ArchiveContext = struct {1760 const ArchiveContext = struct {
1818 gpa: Allocator,1761 gpa: Allocator,
1819 data: []const u8,1762 data: []const u8,
1820 symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .empty,1763 symtab: []ArSymtabEntry,
1821 strtab: []const u8,1764 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 {1767 fn deinit(ctx: *ArchiveContext) void {
1825 var stream = std.io.fixedBufferStream(raw);1768 ctx.gpa.free(ctx.symtab);
1826 const reader = stream.reader();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);
1827 const num = switch (ptr_width) {1774 const num = switch (ptr_width) {
1828 .p32 => try reader.readInt(u32, .big),1775 .p32 => try br.takeInt(u32, .big),
1829 .p64 => try reader.readInt(u64, .big),1776 .p64 => try br.takeInt(u64, .big),
1830 };1777 };
1831 const ptr_size: usize = switch (ptr_width) {1778 const ptr_size: usize = switch (ptr_width) {
1832 .p32 => @sizeOf(u32),1779 .p32 => @sizeOf(u32),
1833 .p64 => @sizeOf(u64),1780 .p64 => @sizeOf(u64),
1834 };1781 };
1835 const strtab_off = (num + 1) * ptr_size;1782 _ = try br.discard(.limited(num * ptr_size));
1836 const strtab_len = raw.len - strtab_off;1783 const strtab = br.buffered();
1837 const strtab = raw[strtab_off..][0..strtab_len];
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
1841 var stroff: usize = 0;1788 var stroff: usize = 0;
1842 for (0..num) |_| {1789 for (ctx.symtab) |*entry| {
1843 const off = switch (ptr_width) {1790 const off = switch (ptr_width) {
1844 .p32 => try reader.readInt(u32, .big),1791 .p32 => try br.takeInt(u32, .big),
1845 .p64 => try reader.readInt(u64, .big),1792 .p64 => try br.takeInt(u64, .big),
1846 };1793 };
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);
1848 stroff += name.len + 1;1795 stroff += name.len + 1;
1849 ctx.symtab.appendAssumeCapacity(.{ .off = off, .name = name });1796 entry.* = .{ .off = off, .name = name };
1850 }1797 }
1851 }1798 }
18521799
1853 fn dumpSymtab(ctx: ArchiveContext, writer: anytype) !void {1800 fn dumpSymtab(ctx: ArchiveContext, bw: *Writer) !void {
1854 var files = std.AutoHashMap(usize, []const u8).init(ctx.gpa);1801 var symbols: std.AutoArrayHashMap(usize, std.ArrayList([]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);
1863 defer {1802 defer {
1864 for (symbols.values()) |*value| {1803 for (symbols.values()) |*value| value.deinit();
1865 value.deinit();
1866 }
1867 symbols.deinit();1804 symbols.deinit();
1868 }1805 }
18691806
1870 for (ctx.symtab.items) |entry| {1807 for (ctx.symtab) |entry| {
1871 const gop = try symbols.getOrPut(@intCast(entry.off));1808 const gop = try symbols.getOrPut(@intCast(entry.off));
1872 if (!gop.found_existing) {1809 if (!gop.found_existing) gop.value_ptr.* = .init(ctx.gpa);
1873 gop.value_ptr.* = std.ArrayList([]const u8).init(ctx.gpa);
1874 }
1875 try gop.value_ptr.append(entry.name);1810 try gop.value_ptr.append(entry.name);
1876 }1811 }
18771812
1878 try writer.print("{s}\n", .{archive_symtab_label});1813 try bw.print("{s}\n", .{archive_symtab_label});
1879 for (symbols.keys(), symbols.values()) |off, values| {1814 for (symbols.keys(), symbols.values()) |off, values| {
1880 try writer.print("in object {s}\n", .{files.get(off).?});1815 try bw.print("in object {s}\n", .{ctx.objects.get(off).?.name});
1881 for (values.items) |value| {1816 for (values.items) |value| try bw.print("{s}\n", .{value});
1882 try writer.print("{s}\n", .{value});
1883 }
1884 }1817 }
1885 }1818 }
18861819
1887 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, writer: anytype) !void {1820 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *Writer) !void {
1888 for (ctx.objects.items) |object| {1821 for (ctx.objects.values()) |object| {
1889 try writer.print("object {s}\n", .{object.name});1822 try bw.print("object {s}\n", .{object.name});
1890 const output = try parseAndDumpObject(step, check, ctx.data[object.off..][0..object.len]);1823 const output = try parseAndDumpObject(step, check, object.data);
1891 defer ctx.gpa.free(output);1824 defer ctx.gpa.free(output);
1892 try writer.print("{s}\n", .{output});1825 try bw.print("{s}\n", .{output});
1893 }1826 }
1894 }1827 }
18951828
1896 fn getString(ctx: ArchiveContext, off: u32) []const u8 {1829 fn getString(ctx: ArchiveContext, off: u32) []const u8 {
1897 assert(off < ctx.strtab.len);1830 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);
1899 return name[0 .. name.len - 1];1832 return name[0 .. name.len - 1];
1900 }1833 }
19011834
...@@ -1907,24 +1840,23 @@ const ElfDumper = struct {...@@ -1907,24 +1840,23 @@ const ElfDumper = struct {
19071840
1908 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1841 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1909 const gpa = step.owner.allocator;1842 const gpa = step.owner.allocator;
1910 var stream = std.io.fixedBufferStream(bytes);1843 var br: std.io.Reader = .fixed(bytes);
1911 const reader = stream.reader();
19121844
1913 const hdr = try reader.readStruct(elf.Elf64_Ehdr);1845 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
1914 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {1846 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;
1915 return error.InvalidMagicNumber;
1916 }
19171847
1918 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];1848 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes[hdr.e_shoff..].ptr))[0..hdr.e_shnum];
1919 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];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 = .{
1922 .gpa = gpa,1852 .gpa = gpa,
1923 .data = bytes,1853 .data = bytes,
1924 .hdr = hdr,1854 .hdr = hdr,
1925 .shdrs = shdrs,1855 .shdrs = shdrs,
1926 .phdrs = phdrs,1856 .phdrs = phdrs,
1927 .shstrtab = undefined,1857 .shstrtab = undefined,
1858 .symtab = .{},
1859 .dysymtab = .{},
1928 };1860 };
1929 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);1861 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
19301862
...@@ -1955,120 +1887,121 @@ const ElfDumper = struct {...@@ -1955,120 +1887,121 @@ const ElfDumper = struct {
1955 else => {},1887 else => {},
1956 };1888 };
19571889
1958 var output = std.ArrayList(u8).init(gpa);1890 var aw: std.io.Writer.Allocating = .init(gpa);
1959 const writer = output.writer();1891 defer aw.deinit();
1892 const bw = &aw.interface;
19601893
1961 switch (check.kind) {1894 switch (check.kind) {
1962 .headers => {1895 .headers => {
1963 try ctx.dumpHeader(writer);1896 try ctx.dumpHeader(bw);
1964 try ctx.dumpShdrs(writer);1897 try ctx.dumpShdrs(bw);
1965 try ctx.dumpPhdrs(writer);1898 try ctx.dumpPhdrs(bw);
1966 },1899 },
19671900
1968 .symtab => if (ctx.symtab.symbols.len > 0) {1901 .symtab => if (ctx.symtab.symbols.len > 0) {
1969 try ctx.dumpSymtab(.symtab, writer);1902 try ctx.dumpSymtab(.symtab, bw);
1970 } else return step.fail("no symbol table found", .{}),1903 } else return step.fail("no symbol table found", .{}),
19711904
1972 .dynamic_symtab => if (ctx.dysymtab.symbols.len > 0) {1905 .dynamic_symtab => if (ctx.dysymtab.symbols.len > 0) {
1973 try ctx.dumpSymtab(.dysymtab, writer);1906 try ctx.dumpSymtab(.dysymtab, bw);
1974 } else return step.fail("no dynamic symbol table found", .{}),1907 } else return step.fail("no dynamic symbol table found", .{}),
19751908
1976 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {1909 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {
1977 try ctx.dumpDynamicSection(shndx, writer);1910 try ctx.dumpDynamicSection(shndx, bw);
1978 } else return step.fail("no .dynamic section found", .{}),1911 } else return step.fail("no .dynamic section found", .{}),
19791912
1980 .dump_section => {1913 .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);
1982 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});1915 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);
1984 },1917 },
19851918
1986 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),1919 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),
1987 }1920 }
19881921
1989 return output.toOwnedSlice();1922 return aw.toOwnedSlice();
1990 }1923 }
19911924
1992 const ObjectContext = struct {1925 const ObjectContext = struct {
1993 gpa: Allocator,1926 gpa: Allocator,
1994 data: []const u8,1927 data: []const u8,
1995 hdr: elf.Elf64_Ehdr,1928 hdr: *align(1) const elf.Elf64_Ehdr,
1996 shdrs: []align(1) const elf.Elf64_Shdr,1929 shdrs: []align(1) const elf.Elf64_Shdr,
1997 phdrs: []align(1) const elf.Elf64_Phdr,1930 phdrs: []align(1) const elf.Elf64_Phdr,
1998 shstrtab: []const u8,1931 shstrtab: []const u8,
1999 symtab: Symtab = .{},1932 symtab: Symtab,
2000 dysymtab: Symtab = .{},1933 dysymtab: Symtab,
20011934
2002 fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {1935 fn dumpHeader(ctx: ObjectContext, bw: *Writer) !void {
2003 try writer.writeAll("header\n");1936 try bw.writeAll("header\n");
2004 try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});1937 try bw.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
2005 try writer.print("entry {x}\n", .{ctx.hdr.e_entry});1938 try bw.print("entry {x}\n", .{ctx.hdr.e_entry});
2006 }1939 }
20071940
2008 fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {1941 fn dumpPhdrs(ctx: ObjectContext, bw: *Writer) !void {
2009 if (ctx.phdrs.len == 0) return;1942 if (ctx.phdrs.len == 0) return;
20101943
2011 try writer.writeAll("program headers\n");1944 try bw.writeAll("program headers\n");
20121945
2013 for (ctx.phdrs, 0..) |phdr, phndx| {1946 for (ctx.phdrs, 0..) |phdr, phndx| {
2014 try writer.print("phdr {d}\n", .{phndx});1947 try bw.print("phdr {d}\n", .{phndx});
2015 try writer.print("type {s}\n", .{fmtPhType(phdr.p_type)});1948 try bw.print("type {f}\n", .{fmtPhType(phdr.p_type)});
2016 try writer.print("vaddr {x}\n", .{phdr.p_vaddr});1949 try bw.print("vaddr {x}\n", .{phdr.p_vaddr});
2017 try writer.print("paddr {x}\n", .{phdr.p_paddr});1950 try bw.print("paddr {x}\n", .{phdr.p_paddr});
2018 try writer.print("offset {x}\n", .{phdr.p_offset});1951 try bw.print("offset {x}\n", .{phdr.p_offset});
2019 try writer.print("memsz {x}\n", .{phdr.p_memsz});1952 try bw.print("memsz {x}\n", .{phdr.p_memsz});
2020 try writer.print("filesz {x}\n", .{phdr.p_filesz});1953 try bw.print("filesz {x}\n", .{phdr.p_filesz});
2021 try writer.print("align {x}\n", .{phdr.p_align});1954 try bw.print("align {x}\n", .{phdr.p_align});
20221955
2023 {1956 {
2024 const flags = phdr.p_flags;1957 const flags = phdr.p_flags;
2025 try writer.writeAll("flags");1958 try bw.writeAll("flags");
2026 if (flags > 0) try writer.writeByte(' ');1959 if (flags > 0) try bw.writeByte(' ');
2027 if (flags & elf.PF_R != 0) {1960 if (flags & elf.PF_R != 0) {
2028 try writer.writeByte('R');1961 try bw.writeByte('R');
2029 }1962 }
2030 if (flags & elf.PF_W != 0) {1963 if (flags & elf.PF_W != 0) {
2031 try writer.writeByte('W');1964 try bw.writeByte('W');
2032 }1965 }
2033 if (flags & elf.PF_X != 0) {1966 if (flags & elf.PF_X != 0) {
2034 try writer.writeByte('E');1967 try bw.writeByte('E');
2035 }1968 }
2036 if (flags & elf.PF_MASKOS != 0) {1969 if (flags & elf.PF_MASKOS != 0) {
2037 try writer.writeAll("OS");1970 try bw.writeAll("OS");
2038 }1971 }
2039 if (flags & elf.PF_MASKPROC != 0) {1972 if (flags & elf.PF_MASKPROC != 0) {
2040 try writer.writeAll("PROC");1973 try bw.writeAll("PROC");
2041 }1974 }
2042 try writer.writeByte('\n');1975 try bw.writeByte('\n');
2043 }1976 }
2044 }1977 }
2045 }1978 }
20461979
2047 fn dumpShdrs(ctx: ObjectContext, writer: anytype) !void {1980 fn dumpShdrs(ctx: ObjectContext, bw: *Writer) !void {
2048 if (ctx.shdrs.len == 0) return;1981 if (ctx.shdrs.len == 0) return;
20491982
2050 try writer.writeAll("section headers\n");1983 try bw.writeAll("section headers\n");
20511984
2052 for (ctx.shdrs, 0..) |shdr, shndx| {1985 for (ctx.shdrs, 0..) |shdr, shndx| {
2053 try writer.print("shdr {d}\n", .{shndx});1986 try bw.print("shdr {d}\n", .{shndx});
2054 try writer.print("name {s}\n", .{ctx.getSectionName(shndx)});1987 try bw.print("name {s}\n", .{ctx.getSectionName(shndx)});
2055 try writer.print("type {s}\n", .{fmtShType(shdr.sh_type)});1988 try bw.print("type {f}\n", .{fmtShType(shdr.sh_type)});
2056 try writer.print("addr {x}\n", .{shdr.sh_addr});1989 try bw.print("addr {x}\n", .{shdr.sh_addr});
2057 try writer.print("offset {x}\n", .{shdr.sh_offset});1990 try bw.print("offset {x}\n", .{shdr.sh_offset});
2058 try writer.print("size {x}\n", .{shdr.sh_size});1991 try bw.print("size {x}\n", .{shdr.sh_size});
2059 try writer.print("addralign {x}\n", .{shdr.sh_addralign});1992 try bw.print("addralign {x}\n", .{shdr.sh_addralign});
2060 // TODO dump formatted sh_flags1993 // TODO dump formatted sh_flags
2061 }1994 }
2062 }1995 }
20631996
2064 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {1997 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, bw: *Writer) !void {
2065 const shdr = ctx.shdrs[shndx];1998 const shdr = ctx.shdrs[shndx];
2066 const strtab = ctx.getSectionContents(shdr.sh_link);1999 const strtab = ctx.getSectionContents(shdr.sh_link);
2067 const data = ctx.getSectionContents(shndx);2000 const data = ctx.getSectionContents(shndx);
2068 const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));2001 const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));
2069 const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];2002 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
2073 for (entries) |entry| {2006 for (entries) |entry| {
2074 const key = @as(u64, @bitCast(entry.d_tag));2007 const key = @as(u64, @bitCast(entry.d_tag));
...@@ -2109,7 +2042,7 @@ const ElfDumper = struct {...@@ -2109,7 +2042,7 @@ const ElfDumper = struct {
2109 elf.DT_NULL => "NULL",2042 elf.DT_NULL => "NULL",
2110 else => "UNKNOWN",2043 else => "UNKNOWN",
2111 };2044 };
2112 try writer.print("{s}", .{key_str});2045 try bw.print("{s}", .{key_str});
21132046
2114 switch (key) {2047 switch (key) {
2115 elf.DT_NEEDED,2048 elf.DT_NEEDED,
...@@ -2118,7 +2051,7 @@ const ElfDumper = struct {...@@ -2118,7 +2051,7 @@ const ElfDumper = struct {
2118 elf.DT_RUNPATH,2051 elf.DT_RUNPATH,
2119 => {2052 => {
2120 const name = getString(strtab, @intCast(value));2053 const name = getString(strtab, @intCast(value));
2121 try writer.print(" {s}", .{name});2054 try bw.print(" {s}", .{name});
2122 },2055 },
21232056
2124 elf.DT_INIT_ARRAY,2057 elf.DT_INIT_ARRAY,
...@@ -2136,7 +2069,7 @@ const ElfDumper = struct {...@@ -2136,7 +2069,7 @@ const ElfDumper = struct {
2136 elf.DT_INIT,2069 elf.DT_INIT,
2137 elf.DT_FINI,2070 elf.DT_FINI,
2138 elf.DT_NULL,2071 elf.DT_NULL,
2139 => try writer.print(" {x}", .{value}),2072 => try bw.print(" {x}", .{value}),
21402073
2141 elf.DT_INIT_ARRAYSZ,2074 elf.DT_INIT_ARRAYSZ,
2142 elf.DT_FINI_ARRAYSZ,2075 elf.DT_FINI_ARRAYSZ,
...@@ -2146,77 +2079,77 @@ const ElfDumper = struct {...@@ -2146,77 +2079,77 @@ const ElfDumper = struct {
2146 elf.DT_RELASZ,2079 elf.DT_RELASZ,
2147 elf.DT_RELAENT,2080 elf.DT_RELAENT,
2148 elf.DT_RELACOUNT,2081 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) {
2152 elf.DT_REL => " REL",2085 elf.DT_REL => " REL",
2153 elf.DT_RELA => " RELA",2086 elf.DT_RELA => " RELA",
2154 else => " UNKNOWN",2087 else => " UNKNOWN",
2155 }),2088 }),
21562089
2157 elf.DT_FLAGS => if (value > 0) {2090 elf.DT_FLAGS => if (value > 0) {
2158 if (value & elf.DF_ORIGIN != 0) try writer.writeAll(" ORIGIN");2091 if (value & elf.DF_ORIGIN != 0) try bw.writeAll(" ORIGIN");
2159 if (value & elf.DF_SYMBOLIC != 0) try writer.writeAll(" SYMBOLIC");2092 if (value & elf.DF_SYMBOLIC != 0) try bw.writeAll(" SYMBOLIC");
2160 if (value & elf.DF_TEXTREL != 0) try writer.writeAll(" TEXTREL");2093 if (value & elf.DF_TEXTREL != 0) try bw.writeAll(" TEXTREL");
2161 if (value & elf.DF_BIND_NOW != 0) try writer.writeAll(" BIND_NOW");2094 if (value & elf.DF_BIND_NOW != 0) try bw.writeAll(" BIND_NOW");
2162 if (value & elf.DF_STATIC_TLS != 0) try writer.writeAll(" STATIC_TLS");2095 if (value & elf.DF_STATIC_TLS != 0) try bw.writeAll(" STATIC_TLS");
2163 },2096 },
21642097
2165 elf.DT_FLAGS_1 => if (value > 0) {2098 elf.DT_FLAGS_1 => if (value > 0) {
2166 if (value & elf.DF_1_NOW != 0) try writer.writeAll(" NOW");2099 if (value & elf.DF_1_NOW != 0) try bw.writeAll(" NOW");
2167 if (value & elf.DF_1_GLOBAL != 0) try writer.writeAll(" GLOBAL");2100 if (value & elf.DF_1_GLOBAL != 0) try bw.writeAll(" GLOBAL");
2168 if (value & elf.DF_1_GROUP != 0) try writer.writeAll(" GROUP");2101 if (value & elf.DF_1_GROUP != 0) try bw.writeAll(" GROUP");
2169 if (value & elf.DF_1_NODELETE != 0) try writer.writeAll(" NODELETE");2102 if (value & elf.DF_1_NODELETE != 0) try bw.writeAll(" NODELETE");
2170 if (value & elf.DF_1_LOADFLTR != 0) try writer.writeAll(" LOADFLTR");2103 if (value & elf.DF_1_LOADFLTR != 0) try bw.writeAll(" LOADFLTR");
2171 if (value & elf.DF_1_INITFIRST != 0) try writer.writeAll(" INITFIRST");2104 if (value & elf.DF_1_INITFIRST != 0) try bw.writeAll(" INITFIRST");
2172 if (value & elf.DF_1_NOOPEN != 0) try writer.writeAll(" NOOPEN");2105 if (value & elf.DF_1_NOOPEN != 0) try bw.writeAll(" NOOPEN");
2173 if (value & elf.DF_1_ORIGIN != 0) try writer.writeAll(" ORIGIN");2106 if (value & elf.DF_1_ORIGIN != 0) try bw.writeAll(" ORIGIN");
2174 if (value & elf.DF_1_DIRECT != 0) try writer.writeAll(" DIRECT");2107 if (value & elf.DF_1_DIRECT != 0) try bw.writeAll(" DIRECT");
2175 if (value & elf.DF_1_TRANS != 0) try writer.writeAll(" TRANS");2108 if (value & elf.DF_1_TRANS != 0) try bw.writeAll(" TRANS");
2176 if (value & elf.DF_1_INTERPOSE != 0) try writer.writeAll(" INTERPOSE");2109 if (value & elf.DF_1_INTERPOSE != 0) try bw.writeAll(" INTERPOSE");
2177 if (value & elf.DF_1_NODEFLIB != 0) try writer.writeAll(" NODEFLIB");2110 if (value & elf.DF_1_NODEFLIB != 0) try bw.writeAll(" NODEFLIB");
2178 if (value & elf.DF_1_NODUMP != 0) try writer.writeAll(" NODUMP");2111 if (value & elf.DF_1_NODUMP != 0) try bw.writeAll(" NODUMP");
2179 if (value & elf.DF_1_CONFALT != 0) try writer.writeAll(" CONFALT");2112 if (value & elf.DF_1_CONFALT != 0) try bw.writeAll(" CONFALT");
2180 if (value & elf.DF_1_ENDFILTEE != 0) try writer.writeAll(" ENDFILTEE");2113 if (value & elf.DF_1_ENDFILTEE != 0) try bw.writeAll(" ENDFILTEE");
2181 if (value & elf.DF_1_DISPRELDNE != 0) try writer.writeAll(" DISPRELDNE");2114 if (value & elf.DF_1_DISPRELDNE != 0) try bw.writeAll(" DISPRELDNE");
2182 if (value & elf.DF_1_DISPRELPND != 0) try writer.writeAll(" DISPRELPND");2115 if (value & elf.DF_1_DISPRELPND != 0) try bw.writeAll(" DISPRELPND");
2183 if (value & elf.DF_1_NODIRECT != 0) try writer.writeAll(" NODIRECT");2116 if (value & elf.DF_1_NODIRECT != 0) try bw.writeAll(" NODIRECT");
2184 if (value & elf.DF_1_IGNMULDEF != 0) try writer.writeAll(" IGNMULDEF");2117 if (value & elf.DF_1_IGNMULDEF != 0) try bw.writeAll(" IGNMULDEF");
2185 if (value & elf.DF_1_NOKSYMS != 0) try writer.writeAll(" NOKSYMS");2118 if (value & elf.DF_1_NOKSYMS != 0) try bw.writeAll(" NOKSYMS");
2186 if (value & elf.DF_1_NOHDR != 0) try writer.writeAll(" NOHDR");2119 if (value & elf.DF_1_NOHDR != 0) try bw.writeAll(" NOHDR");
2187 if (value & elf.DF_1_EDITED != 0) try writer.writeAll(" EDITED");2120 if (value & elf.DF_1_EDITED != 0) try bw.writeAll(" EDITED");
2188 if (value & elf.DF_1_NORELOC != 0) try writer.writeAll(" NORELOC");2121 if (value & elf.DF_1_NORELOC != 0) try bw.writeAll(" NORELOC");
2189 if (value & elf.DF_1_SYMINTPOSE != 0) try writer.writeAll(" SYMINTPOSE");2122 if (value & elf.DF_1_SYMINTPOSE != 0) try bw.writeAll(" SYMINTPOSE");
2190 if (value & elf.DF_1_GLOBAUDIT != 0) try writer.writeAll(" GLOBAUDIT");2123 if (value & elf.DF_1_GLOBAUDIT != 0) try bw.writeAll(" GLOBAUDIT");
2191 if (value & elf.DF_1_SINGLETON != 0) try writer.writeAll(" SINGLETON");2124 if (value & elf.DF_1_SINGLETON != 0) try bw.writeAll(" SINGLETON");
2192 if (value & elf.DF_1_STUB != 0) try writer.writeAll(" STUB");2125 if (value & elf.DF_1_STUB != 0) try bw.writeAll(" STUB");
2193 if (value & elf.DF_1_PIE != 0) try writer.writeAll(" PIE");2126 if (value & elf.DF_1_PIE != 0) try bw.writeAll(" PIE");
2194 },2127 },
21952128
2196 else => try writer.print(" {x}", .{value}),2129 else => try bw.print(" {x}", .{value}),
2197 }2130 }
2198 try writer.writeByte('\n');2131 try bw.writeByte('\n');
2199 }2132 }
2200 }2133 }
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 {
2203 const symtab = switch (@"type") {2136 const symtab = switch (@"type") {
2204 .symtab => ctx.symtab,2137 .symtab => ctx.symtab,
2205 .dysymtab => ctx.dysymtab,2138 .dysymtab => ctx.dysymtab,
2206 };2139 };
22072140
2208 try writer.writeAll(switch (@"type") {2141 try bw.writeAll(switch (@"type") {
2209 .symtab => symtab_label,2142 .symtab => symtab_label,
2210 .dysymtab => dynamic_symtab_label,2143 .dysymtab => dynamic_symtab_label,
2211 } ++ "\n");2144 } ++ "\n");
22122145
2213 for (symtab.symbols, 0..) |sym, index| {2146 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
2216 {2149 {
2217 if (elf.SHN_LORESERVE <= sym.st_shndx and sym.st_shndx < elf.SHN_HIRESERVE) {2150 if (elf.SHN_LORESERVE <= sym.st_shndx and sym.st_shndx < elf.SHN_HIRESERVE) {
2218 if (elf.SHN_LOPROC <= sym.st_shndx and sym.st_shndx < elf.SHN_HIPROC) {2151 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});
2220 } else {2153 } else {
2221 const sym_ndx = switch (sym.st_shndx) {2154 const sym_ndx = switch (sym.st_shndx) {
2222 elf.SHN_ABS => "ABS",2155 elf.SHN_ABS => "ABS",
...@@ -2224,12 +2157,12 @@ const ElfDumper = struct {...@@ -2224,12 +2157,12 @@ const ElfDumper = struct {
2224 elf.SHN_LIVEPATCH => "LIV",2157 elf.SHN_LIVEPATCH => "LIV",
2225 else => "UNK",2158 else => "UNK",
2226 };2159 };
2227 try writer.print(" {s}", .{sym_ndx});2160 try bw.print(" {s}", .{sym_ndx});
2228 }2161 }
2229 } else if (sym.st_shndx == elf.SHN_UNDEF) {2162 } else if (sym.st_shndx == elf.SHN_UNDEF) {
2230 try writer.writeAll(" UND");2163 try bw.writeAll(" UND");
2231 } else {2164 } else {
2232 try writer.print(" {x}", .{sym.st_shndx});2165 try bw.print(" {x}", .{sym.st_shndx});
2233 }2166 }
2234 }2167 }
22352168
...@@ -2246,12 +2179,12 @@ const ElfDumper = struct {...@@ -2246,12 +2179,12 @@ const ElfDumper = struct {
2246 elf.STT_NUM => "NUM",2179 elf.STT_NUM => "NUM",
2247 elf.STT_GNU_IFUNC => "IFUNC",2180 elf.STT_GNU_IFUNC => "IFUNC",
2248 else => if (elf.STT_LOPROC <= tt and tt < elf.STT_HIPROC) {2181 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});
2250 } else if (elf.STT_LOOS <= tt and tt < elf.STT_HIOS) {2183 } 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});
2252 } else "UNK",2185 } else "UNK",
2253 };2186 };
2254 try writer.print(" {s}", .{sym_type});2187 try bw.print(" {s}", .{sym_type});
2255 }2188 }
22562189
2257 blk: {2190 blk: {
...@@ -2262,28 +2195,28 @@ const ElfDumper = struct {...@@ -2262,28 +2195,28 @@ const ElfDumper = struct {
2262 elf.STB_WEAK => "WEAK",2195 elf.STB_WEAK => "WEAK",
2263 elf.STB_NUM => "NUM",2196 elf.STB_NUM => "NUM",
2264 else => if (elf.STB_LOPROC <= bind and bind < elf.STB_HIPROC) {2197 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});
2266 } else if (elf.STB_LOOS <= bind and bind < elf.STB_HIOS) {2199 } 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});
2268 } else "UNKNOWN",2201 } else "UNKNOWN",
2269 };2202 };
2270 try writer.print(" {s}", .{sym_bind});2203 try bw.print(" {s}", .{sym_bind});
2271 }2204 }
22722205
2273 const sym_vis = @as(elf.STV, @enumFromInt(@as(u2, @truncate(sym.st_other))));2206 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
2276 const sym_name = switch (sym.st_type()) {2209 const sym_name = switch (sym.st_type()) {
2277 elf.STT_SECTION => ctx.getSectionName(sym.st_shndx),2210 elf.STT_SECTION => ctx.getSectionName(sym.st_shndx),
2278 else => symtab.getName(index).?,2211 else => symtab.getName(index).?,
2279 };2212 };
2280 try writer.print(" {s}\n", .{sym_name});2213 try bw.print(" {s}\n", .{sym_name});
2281 }2214 }
2282 }2215 }
22832216
2284 fn dumpSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {2217 fn dumpSection(ctx: ObjectContext, shndx: usize, bw: *Writer) !void {
2285 const data = ctx.getSectionContents(shndx);2218 const data = ctx.getSectionContents(shndx);
2286 try writer.print("{s}", .{data});2219 try bw.print("{s}", .{data});
2287 }2220 }
22882221
2289 inline fn getSectionName(ctx: ObjectContext, shndx: usize) []const u8 {2222 inline fn getSectionName(ctx: ObjectContext, shndx: usize) []const u8 {
...@@ -2321,22 +2254,15 @@ const ElfDumper = struct {...@@ -2321,22 +2254,15 @@ const ElfDumper = struct {
2321 };2254 };
23222255
2323 fn getString(strtab: []const u8, off: u32) []const u8 {2256 fn getString(strtab: []const u8, off: u32) []const u8 {
2324 assert(off < strtab.len);2257 const str = strtab[off..];
2325 return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0);2258 return str[0..std.mem.indexOfScalar(u8, str, 0).?];
2326 }2259 }
23272260
2328 fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) {2261 fn fmtShType(sh_type: u32) std.fmt.Formatter(u32, formatShType) {
2329 return .{ .data = sh_type };2262 return .{ .data = sh_type };
2330 }2263 }
23312264
2332 fn formatShType(2265 fn formatShType(sh_type: u32, w: *Writer) Writer.Error!void {
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;
2340 const name = switch (sh_type) {2266 const name = switch (sh_type) {
2341 elf.SHT_NULL => "NULL",2267 elf.SHT_NULL => "NULL",
2342 elf.SHT_PROGBITS => "PROGBITS",2268 elf.SHT_PROGBITS => "PROGBITS",
...@@ -2362,28 +2288,21 @@ const ElfDumper = struct {...@@ -2362,28 +2288,21 @@ const ElfDumper = struct {
2362 elf.SHT_GNU_VERNEED => "VERNEED",2288 elf.SHT_GNU_VERNEED => "VERNEED",
2363 elf.SHT_GNU_VERSYM => "VERSYM",2289 elf.SHT_GNU_VERSYM => "VERSYM",
2364 else => if (elf.SHT_LOOS <= sh_type and sh_type < elf.SHT_HIOS) {2290 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});
2366 } else if (elf.SHT_LOPROC <= sh_type and sh_type < elf.SHT_HIPROC) {2292 } 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});
2368 } else if (elf.SHT_LOUSER <= sh_type and sh_type < elf.SHT_HIUSER) {2294 } 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});
2370 } else "UNKNOWN",2296 } else "UNKNOWN",
2371 };2297 };
2372 try writer.writeAll(name);2298 try w.writeAll(name);
2373 }2299 }
23742300
2375 fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) {2301 fn fmtPhType(ph_type: u32) std.fmt.Formatter(u32, formatPhType) {
2376 return .{ .data = ph_type };2302 return .{ .data = ph_type };
2377 }2303 }
23782304
2379 fn formatPhType(2305 fn formatPhType(ph_type: u32, w: *Writer) Writer.Error!void {
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;
2387 const p_type = switch (ph_type) {2306 const p_type = switch (ph_type) {
2388 elf.PT_NULL => "NULL",2307 elf.PT_NULL => "NULL",
2389 elf.PT_LOAD => "LOAD",2308 elf.PT_LOAD => "LOAD",
...@@ -2398,12 +2317,12 @@ const ElfDumper = struct {...@@ -2398,12 +2317,12 @@ const ElfDumper = struct {
2398 elf.PT_GNU_STACK => "GNU_STACK",2317 elf.PT_GNU_STACK => "GNU_STACK",
2399 elf.PT_GNU_RELRO => "GNU_RELRO",2318 elf.PT_GNU_RELRO => "GNU_RELRO",
2400 else => if (elf.PT_LOOS <= ph_type and ph_type < elf.PT_HIOS) {2319 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});
2402 } else if (elf.PT_LOPROC <= ph_type and ph_type < elf.PT_HIPROC) {2321 } 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});
2404 } else "UNKNOWN",2323 } else "UNKNOWN",
2405 };2324 };
2406 try writer.writeAll(p_type);2325 try w.writeAll(p_type);
2407 }2326 }
2408};2327};
24092328
...@@ -2412,49 +2331,39 @@ const WasmDumper = struct {...@@ -2412,49 +2331,39 @@ const WasmDumper = struct {
24122331
2413 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {2332 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
2414 const gpa = step.owner.allocator;2333 const gpa = step.owner.allocator;
2415 var fbs = std.io.fixedBufferStream(bytes);2334 var br: std.io.Reader = .fixed(bytes);
2416 const reader = fbs.reader();
24172335
2418 const buf = try reader.readBytesNoEof(8);2336 const buf = try br.takeArray(8);
2419 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) {2337 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;
2420 return error.InvalidMagicByte;2338 if (!mem.eql(u8, buf[4..8], &std.wasm.version)) return error.UnsupportedWasmVersion;
2421 }2339
2422 if (!mem.eql(u8, buf[4..], &std.wasm.version)) {2340 var aw: std.io.Writer.Allocating = .init(gpa);
2423 return error.UnsupportedWasmVersion;2341 defer aw.deinit();
2424 }2342 const bw = &aw.interface;
24252343
2426 var output = std.ArrayList(u8).init(gpa);2344 parseAndDumpInner(step, check, &br, bw) catch |err| switch (err) {
2427 defer output.deinit();2345 error.EndOfStream => try bw.writeAll("\n<UnexpectedEndOfStream>"),
2428 parseAndDumpInner(step, check, bytes, &fbs, &output) catch |err| switch (err) {
2429 error.EndOfStream => try output.appendSlice("\n<UnexpectedEndOfStream>"),
2430 else => |e| return e,2346 else => |e| return e,
2431 };2347 };
2432 return output.toOwnedSlice();2348 return aw.toOwnedSlice();
2433 }2349 }
24342350
2435 fn parseAndDumpInner(2351 fn parseAndDumpInner(
2436 step: *Step,2352 step: *Step,
2437 check: Check,2353 check: Check,
2438 bytes: []const u8,2354 br: *std.io.Reader,
2439 fbs: *std.io.FixedBufferStream([]const u8),2355 bw: *Writer,
2440 output: *std.ArrayList(u8),
2441 ) !void {2356 ) !void {
2442 const reader = fbs.reader();2357 var section_br: std.io.Reader = undefined;
2443 const writer = output.writer();
2444
2445 switch (check.kind) {2358 switch (check.kind) {
2446 .headers => {2359 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
2447 while (reader.readByte()) |current_byte| {2360 section_br = .fixed(try br.take(try br.takeLeb128(u32)));
2448 const section = std.enums.fromInt(std.wasm.Section, current_byte) orelse {2361 try parseAndDumpSection(step, section, &section_br, bw);
2449 return step.fail("Found invalid section id '{d}'", .{current_byte});2362 } else |err| switch (err) {
2450 };2363 error.InvalidEnumTag => return step.fail("invalid section id", .{}),
24512364 error.EndOfStream => {},
2452 const section_length = try std.leb.readUleb128(u32, reader);2365 else => |e| return e,
2453 try parseAndDumpSection(step, section, bytes[fbs.pos..][0..section_length], writer);
2454 fbs.pos += section_length;
2455 } else |_| {} // reached end of stream
2456 },2366 },
2457
2458 else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),2367 else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),
2459 }2368 }
2460 }2369 }
...@@ -2462,16 +2371,13 @@ const WasmDumper = struct {...@@ -2462,16 +2371,13 @@ const WasmDumper = struct {
2462 fn parseAndDumpSection(2371 fn parseAndDumpSection(
2463 step: *Step,2372 step: *Step,
2464 section: std.wasm.Section,2373 section: std.wasm.Section,
2465 data: []const u8,2374 br: *std.io.Reader,
2466 writer: anytype,2375 bw: *Writer,
2467 ) !void {2376 ) !void {
2468 var fbs = std.io.fixedBufferStream(data);2377 try bw.print(
2469 const reader = fbs.reader();
2470
2471 try writer.print(
2472 \\Section {s}2378 \\Section {s}
2473 \\size {d}2379 \\size {d}
2474 , .{ @tagName(section), data.len });2380 , .{ @tagName(section), br.buffer.len });
24752381
2476 switch (section) {2382 switch (section) {
2477 .type,2383 .type,
...@@ -2485,96 +2391,83 @@ const WasmDumper = struct {...@@ -2485,96 +2391,83 @@ const WasmDumper = struct {
2485 .code,2391 .code,
2486 .data,2392 .data,
2487 => {2393 => {
2488 const entries = try std.leb.readUleb128(u32, reader);2394 const entries = try br.takeLeb128(u32);
2489 try writer.print("\nentries {d}\n", .{entries});2395 try bw.print("\nentries {d}\n", .{entries});
2490 try parseSection(step, section, data[fbs.pos..], entries, writer);2396 try parseSection(step, section, br, entries, bw);
2491 },2397 },
2492 .custom => {2398 .custom => {
2493 const name_length = try std.leb.readUleb128(u32, reader);2399 const name = try br.take(try br.takeLeb128(u32));
2494 const name = data[fbs.pos..][0..name_length];2400 try bw.print("\nname {s}\n", .{name});
2495 fbs.pos += name_length;
2496 try writer.print("\nname {s}\n", .{name});
24972401
2498 if (mem.eql(u8, name, "name")) {2402 if (mem.eql(u8, name, "name")) {
2499 try parseDumpNames(step, reader, writer, data);2403 try parseDumpNames(step, br, bw);
2500 } else if (mem.eql(u8, name, "producers")) {2404 } else if (mem.eql(u8, name, "producers")) {
2501 try parseDumpProducers(reader, writer, data);2405 try parseDumpProducers(br, bw);
2502 } else if (mem.eql(u8, name, "target_features")) {2406 } else if (mem.eql(u8, name, "target_features")) {
2503 try parseDumpFeatures(reader, writer, data);2407 try parseDumpFeatures(br, bw);
2504 }2408 }
2505 // TODO: Implement parsing and dumping other custom sections (such as relocations)2409 // TODO: Implement parsing and dumping other custom sections (such as relocations)
2506 },2410 },
2507 .start => {2411 .start => {
2508 const start = try std.leb.readUleb128(u32, reader);2412 const start = try br.takeLeb128(u32);
2509 try writer.print("\nstart {d}\n", .{start});2413 try bw.print("\nstart {d}\n", .{start});
2510 },2414 },
2511 .data_count => {2415 .data_count => {
2512 const count = try std.leb.readUleb128(u32, reader);2416 const count = try br.takeLeb128(u32);
2513 try writer.print("\ncount {d}\n", .{count});2417 try bw.print("\ncount {d}\n", .{count});
2514 },2418 },
2515 else => {}, // skip unknown sections2419 else => {}, // skip unknown sections
2516 }2420 }
2517 }2421 }
25182422
2519 fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, writer: anytype) !void {2423 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.Reader, entries: u32, bw: *Writer) !void {
2520 var fbs = std.io.fixedBufferStream(data);
2521 const reader = fbs.reader();
2522
2523 switch (section) {2424 switch (section) {
2524 .type => {2425 .type => {
2525 var i: u32 = 0;2426 var i: u32 = 0;
2526 while (i < entries) : (i += 1) {2427 while (i < entries) : (i += 1) {
2527 const func_type = try reader.readByte();2428 const func_type = try br.takeByte();
2528 if (func_type != std.wasm.function_type) {2429 if (func_type != std.wasm.function_type) {
2529 return step.fail("expected function type, found byte '{d}'", .{func_type});2430 return step.fail("expected function type, found byte '{d}'", .{func_type});
2530 }2431 }
2531 const params = try std.leb.readUleb128(u32, reader);2432 const params = try br.takeLeb128(u32);
2532 try writer.print("params {d}\n", .{params});2433 try bw.print("params {d}\n", .{params});
2533 var index: u32 = 0;2434 var index: u32 = 0;
2534 while (index < params) : (index += 1) {2435 while (index < params) : (index += 1) {
2535 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2436 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2536 } else index = 0;2437 } else index = 0;
2537 const returns = try std.leb.readUleb128(u32, reader);2438 const returns = try br.takeLeb128(u32);
2538 try writer.print("returns {d}\n", .{returns});2439 try bw.print("returns {d}\n", .{returns});
2539 while (index < returns) : (index += 1) {2440 while (index < returns) : (index += 1) {
2540 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2441 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2541 }2442 }
2542 }2443 }
2543 },2444 },
2544 .import => {2445 .import => {
2545 var i: u32 = 0;2446 var i: u32 = 0;
2546 while (i < entries) : (i += 1) {2447 while (i < entries) : (i += 1) {
2547 const module_name_len = try std.leb.readUleb128(u32, reader);2448 const module_name = try br.take(try br.takeLeb128(u32));
2548 const module_name = data[fbs.pos..][0..module_name_len];2449 const name = try br.take(try br.takeLeb128(u32));
2549 fbs.pos += module_name_len;2450 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2550 const name_len = try std.leb.readUleb128(u32, reader);2451 error.InvalidEnumTag => return step.fail("invalid import kind", .{}),
2551 const name = data[fbs.pos..][0..name_len];2452 else => |e| return e,
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", .{});
2556 };2453 };
25572454
2558 try writer.print(2455 try bw.print(
2559 \\module {s}2456 \\module {s}
2560 \\name {s}2457 \\name {s}
2561 \\kind {s}2458 \\kind {s}
2562 , .{ module_name, name, @tagName(kind) });2459 , .{ module_name, name, @tagName(kind) });
2563 try writer.writeByte('\n');2460 try bw.writeByte('\n');
2564 switch (kind) {2461 switch (kind) {
2565 .function => {2462 .function => try bw.print("index {d}\n", .{try br.takeLeb128(u32)}),
2566 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2463 .memory => try parseDumpLimits(br, bw),
2567 },
2568 .memory => {
2569 try parseDumpLimits(reader, writer);
2570 },
2571 .global => {2464 .global => {
2572 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2465 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2573 try writer.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u32, reader)});2466 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u32)});
2574 },2467 },
2575 .table => {2468 .table => {
2576 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);2469 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2577 try parseDumpLimits(reader, writer);2470 try parseDumpLimits(br, bw);
2578 },2471 },
2579 }2472 }
2580 }2473 }
...@@ -2582,60 +2475,58 @@ const WasmDumper = struct {...@@ -2582,60 +2475,58 @@ const WasmDumper = struct {
2582 .function => {2475 .function => {
2583 var i: u32 = 0;2476 var i: u32 = 0;
2584 while (i < entries) : (i += 1) {2477 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)});
2586 }2479 }
2587 },2480 },
2588 .table => {2481 .table => {
2589 var i: u32 = 0;2482 var i: u32 = 0;
2590 while (i < entries) : (i += 1) {2483 while (i < entries) : (i += 1) {
2591 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);2484 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2592 try parseDumpLimits(reader, writer);2485 try parseDumpLimits(br, bw);
2593 }2486 }
2594 },2487 },
2595 .memory => {2488 .memory => {
2596 var i: u32 = 0;2489 var i: u32 = 0;
2597 while (i < entries) : (i += 1) {2490 while (i < entries) : (i += 1) {
2598 try parseDumpLimits(reader, writer);2491 try parseDumpLimits(br, bw);
2599 }2492 }
2600 },2493 },
2601 .global => {2494 .global => {
2602 var i: u32 = 0;2495 var i: u32 = 0;
2603 while (i < entries) : (i += 1) {2496 while (i < entries) : (i += 1) {
2604 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2497 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2605 try writer.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u1, reader)});2498 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u1)});
2606 try parseDumpInit(step, reader, writer);2499 try parseDumpInit(step, br, bw);
2607 }2500 }
2608 },2501 },
2609 .@"export" => {2502 .@"export" => {
2610 var i: u32 = 0;2503 var i: u32 = 0;
2611 while (i < entries) : (i += 1) {2504 while (i < entries) : (i += 1) {
2612 const name_len = try std.leb.readUleb128(u32, reader);2505 const name = try br.take(try br.takeLeb128(u32));
2613 const name = data[fbs.pos..][0..name_len];2506 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2614 fbs.pos += name_len;2507 error.InvalidEnumTag => return step.fail("invalid export kind value", .{}),
2615 const kind_byte = try std.leb.readUleb128(u8, reader);2508 else => |e| return e,
2616 const kind = std.enums.fromInt(std.wasm.ExternalKind, kind_byte) orelse {
2617 return step.fail("invalid export kind value '{d}'", .{kind_byte});
2618 };2509 };
2619 const index = try std.leb.readUleb128(u32, reader);2510 const index = try br.takeLeb128(u32);
2620 try writer.print(2511 try bw.print(
2621 \\name {s}2512 \\name {s}
2622 \\kind {s}2513 \\kind {s}
2623 \\index {d}2514 \\index {d}
2624 , .{ name, @tagName(kind), index });2515 , .{ name, @tagName(kind), index });
2625 try writer.writeByte('\n');2516 try bw.writeByte('\n');
2626 }2517 }
2627 },2518 },
2628 .element => {2519 .element => {
2629 var i: u32 = 0;2520 var i: u32 = 0;
2630 while (i < entries) : (i += 1) {2521 while (i < entries) : (i += 1) {
2631 try writer.print("table index {d}\n", .{try std.leb.readUleb128(u32, reader)});2522 try bw.print("table index {d}\n", .{try br.takeLeb128(u32)});
2632 try parseDumpInit(step, reader, writer);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);
2635 var function_index: u32 = 0;2526 var function_index: u32 = 0;
2636 try writer.print("indexes {d}\n", .{function_indexes});2527 try bw.print("indexes {d}\n", .{function_indexes});
2637 while (function_index < function_indexes) : (function_index += 1) {2528 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)});
2639 }2530 }
2640 }2531 }
2641 },2532 },
...@@ -2643,101 +2534,95 @@ const WasmDumper = struct {...@@ -2643,101 +2534,95 @@ const WasmDumper = struct {
2643 .data => {2534 .data => {
2644 var i: u32 = 0;2535 var i: u32 = 0;
2645 while (i < entries) : (i += 1) {2536 while (i < entries) : (i += 1) {
2646 const flags = try std.leb.readUleb128(u32, reader);2537 const flags: packed struct(u32) {
2647 const index = if (flags & 0x02 != 0)2538 passive: bool,
2648 try std.leb.readUleb128(u32, reader)2539 memidx: bool,
2649 else2540 unused: u30,
2650 0;2541 } = @bitCast(try br.takeLeb128(u32));
2651 try writer.print("memory index 0x{x}\n", .{index});2542 const index = if (flags.memidx) try br.takeLeb128(u32) else 0;
2652 if (flags == 0) {2543 try bw.print("memory index 0x{x}\n", .{index});
2653 try parseDumpInit(step, reader, writer);2544 if (!flags.passive) try parseDumpInit(step, br, bw);
2654 }2545 const size = try br.takeLeb128(u32);
26552546 try bw.print("size {d}\n", .{size});
2656 const size = try std.leb.readUleb128(u32, reader);2547 _ = try br.discard(.limited(size)); // we do not care about the content of the segments
2657 try writer.print("size {d}\n", .{size});
2658 try reader.skipBytes(size, .{}); // we do not care about the content of the segments
2659 }2548 }
2660 },2549 },
2661 else => unreachable,2550 else => unreachable,
2662 }2551 }
2663 }2552 }
26642553
2665 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, writer: anytype) !E {2554 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.Reader, bw: *Writer) !E {
2666 const byte = try reader.readByte();2555 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
2667 const tag = std.enums.fromInt(E, byte) orelse {2556 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
2668 return step.fail("invalid wasm type value '{d}'", .{byte});2557 else => |e| return e,
2669 };2558 };
2670 try writer.print("type {s}\n", .{@tagName(tag)});2559 try bw.print("type {s}\n", .{@tagName(tag)});
2671 return tag;2560 return tag;
2672 }2561 }
26732562
2674 fn parseDumpLimits(reader: anytype, writer: anytype) !void {2563 fn parseDumpLimits(br: *std.io.Reader, bw: *Writer) !void {
2675 const flags = try std.leb.readUleb128(u8, reader);2564 const flags = try br.takeLeb128(u8);
2676 const min = try std.leb.readUleb128(u32, reader);2565 const min = try br.takeLeb128(u32);
26772566
2678 try writer.print("min {x}\n", .{min});2567 try bw.print("min {x}\n", .{min});
2679 if (flags != 0) {2568 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
2680 try writer.print("max {x}\n", .{try std.leb.readUleb128(u32, reader)});
2681 }
2682 }2569 }
26832570
2684 fn parseDumpInit(step: *Step, reader: anytype, writer: anytype) !void {2571 fn parseDumpInit(step: *Step, br: *std.io.Reader, bw: *Writer) !void {
2685 const byte = try reader.readByte();2572 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
2686 const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse {2573 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
2687 return step.fail("invalid wasm opcode '{d}'", .{byte});2574 else => |e| return e,
2688 };2575 };
2689 switch (opcode) {2576 switch (opcode) {
2690 .i32_const => try writer.print("i32.const {x}\n", .{try std.leb.readIleb128(i32, reader)}),2577 .i32_const => try bw.print("i32.const {x}\n", .{try br.takeLeb128(i32)}),
2691 .i64_const => try writer.print("i64.const {x}\n", .{try std.leb.readIleb128(i64, reader)}),2578 .i64_const => try bw.print("i64.const {x}\n", .{try br.takeLeb128(i64)}),
2692 .f32_const => try writer.print("f32.const {x}\n", .{@as(f32, @bitCast(try reader.readInt(u32, .little)))}),2579 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try br.takeInt(u32, .little)))}),
2693 .f64_const => try writer.print("f64.const {x}\n", .{@as(f64, @bitCast(try reader.readInt(u64, .little)))}),2580 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try br.takeInt(u64, .little)))}),
2694 .global_get => try writer.print("global.get {x}\n", .{try std.leb.readUleb128(u32, reader)}),2581 .global_get => try bw.print("global.get {x}\n", .{try br.takeLeb128(u32)}),
2695 else => unreachable,2582 else => unreachable,
2696 }2583 }
2697 const end_opcode = try std.leb.readUleb128(u8, reader);2584 const end_opcode = try br.takeLeb128(u8);
2698 if (end_opcode != @intFromEnum(std.wasm.Opcode.end)) {2585 if (end_opcode != @intFromEnum(std.wasm.Opcode.end)) {
2699 return step.fail("expected 'end' opcode in init expression", .{});2586 return step.fail("expected 'end' opcode in init expression", .{});
2700 }2587 }
2701 }2588 }
27022589
2703 /// https://webassembly.github.io/spec/core/appendix/custom.html2590 /// https://webassembly.github.io/spec/core/appendix/custom.html
2704 fn parseDumpNames(step: *Step, reader: anytype, writer: anytype, data: []const u8) !void {2591 fn parseDumpNames(step: *Step, br: *std.io.Reader, bw: *Writer) !void {
2705 while (reader.context.pos < data.len) {2592 var subsection_br: std.io.Reader = undefined;
2706 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, writer)) {2593 while (br.seek < br.buffer.len) {
2594 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
2707 // The module name subsection ... consists of a single name2595 // The module name subsection ... consists of a single name
2708 // that is assigned to the module itself.2596 // that is assigned to the module itself.
2709 .module => {2597 .module => {
2710 const size = try std.leb.readUleb128(u32, reader);2598 subsection_br = .fixed(try br.take(try br.takeLeb128(u32)));
2711 const name_len = try std.leb.readUleb128(u32, reader);2599 const name = try subsection_br.take(try subsection_br.takeLeb128(u32));
2712 if (size != name_len + 1) return error.BadSubsectionSize;2600 try bw.print(
2713 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;2601 \\name {s}
2714 try writer.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});2602 \\
2715 reader.context.pos += name_len;2603 , .{name});
2604 if (subsection_br.seek != subsection_br.buffer.len) return error.BadSubsectionSize;
2716 },2605 },
27172606
2718 // The function name subsection ... consists of a name map2607 // The function name subsection ... consists of a name map
2719 // assigning function names to function indices.2608 // assigning function names to function indices.
2720 .function, .global, .data_segment => {2609 .function, .global, .data_segment => {
2721 const size = try std.leb.readUleb128(u32, reader);2610 subsection_br = .fixed(try br.take(try br.takeLeb128(u32)));
2722 const entries = try std.leb.readUleb128(u32, reader);2611 const entries = try br.takeLeb128(u32);
2723 try writer.print(2612 try bw.print(
2724 \\size {d}
2725 \\names {d}2613 \\names {d}
2726 \\2614 \\
2727 , .{ size, entries });2615 , .{entries});
2728 for (0..entries) |_| {2616 for (0..entries) |_| {
2729 const index = try std.leb.readUleb128(u32, reader);2617 const index = try br.takeLeb128(u32);
2730 const name_len = try std.leb.readUleb128(u32, reader);2618 const name = try br.take(try br.takeLeb128(u32));
2731 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;2619 try bw.print(
2732 const name = data[reader.context.pos..][0..name_len];
2733 reader.context.pos += name.len;
2734
2735 try writer.print(
2736 \\index {d}2620 \\index {d}
2737 \\name {s}2621 \\name {s}
2738 \\2622 \\
2739 , .{ index, name });2623 , .{ index, name });
2740 }2624 }
2625 if (subsection_br.seek != subsection_br.buffer.len) return error.BadSubsectionSize;
2741 },2626 },
27422627
2743 // The local name subsection ... consists of an indirect name2628 // The local name subsection ... consists of an indirect name
...@@ -2752,52 +2637,49 @@ const WasmDumper = struct {...@@ -2752,52 +2637,49 @@ const WasmDumper = struct {
2752 }2637 }
2753 }2638 }
27542639
2755 fn parseDumpProducers(reader: anytype, writer: anytype, data: []const u8) !void {2640 fn parseDumpProducers(br: *std.io.Reader, bw: *Writer) !void {
2756 const field_count = try std.leb.readUleb128(u32, reader);2641 const field_count = try br.takeLeb128(u32);
2757 try writer.print("fields {d}\n", .{field_count});2642 try bw.print(
2643 \\fields {d}
2644 \\
2645 , .{field_count});
2758 var current_field: u32 = 0;2646 var current_field: u32 = 0;
2759 while (current_field < field_count) : (current_field += 1) {2647 while (current_field < field_count) : (current_field += 1) {
2760 const field_name_length = try std.leb.readUleb128(u32, reader);2648 const field_name = try br.take(try br.takeLeb128(u32));
2761 const field_name = data[reader.context.pos..][0..field_name_length];2649 const value_count = try br.takeLeb128(u32);
2762 reader.context.pos += field_name_length;2650 try bw.print(
2763
2764 const value_count = try std.leb.readUleb128(u32, reader);
2765 try writer.print(
2766 \\field_name {s}2651 \\field_name {s}
2767 \\values {d}2652 \\values {d}
2653 \\
2768 , .{ field_name, value_count });2654 , .{ field_name, value_count });
2769 try writer.writeByte('\n');
2770 var current_value: u32 = 0;2655 var current_value: u32 = 0;
2771 while (current_value < value_count) : (current_value += 1) {2656 while (current_value < value_count) : (current_value += 1) {
2772 const value_length = try std.leb.readUleb128(u32, reader);2657 const value = try br.take(try br.takeLeb128(u32));
2773 const value = data[reader.context.pos..][0..value_length];2658 const version = try br.take(try br.takeLeb128(u32));
2774 reader.context.pos += value_length;2659 try bw.print(
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(
2781 \\value_name {s}2660 \\value_name {s}
2782 \\version {s}2661 \\version {s}
2662 \\
2783 , .{ value, version });2663 , .{ value, version });
2784 try writer.writeByte('\n');
2785 }2664 }
2786 }2665 }
2787 }2666 }
27882667
2789 fn parseDumpFeatures(reader: anytype, writer: anytype, data: []const u8) !void {2668 fn parseDumpFeatures(br: *std.io.Reader, bw: *Writer) !void {
2790 const feature_count = try std.leb.readUleb128(u32, reader);2669 const feature_count = try br.takeLeb128(u32);
2791 try writer.print("features {d}\n", .{feature_count});2670 try bw.print(
2671 \\features {d}
2672 \\
2673 , .{feature_count});
27922674
2793 var index: u32 = 0;2675 var index: u32 = 0;
2794 while (index < feature_count) : (index += 1) {2676 while (index < feature_count) : (index += 1) {
2795 const prefix_byte = try std.leb.readUleb128(u8, reader);2677 const prefix_byte = try br.takeLeb128(u8);
2796 const name_length = try std.leb.readUleb128(u32, reader);2678 const feature_name = try br.take(try br.takeLeb128(u32));
2797 const feature_name = data[reader.context.pos..][0..name_length];2679 try bw.print(
2798 reader.context.pos += name_length;2680 \\{c} {s}
27992681 \\
2800 try writer.print("{c} {s}\n", .{ prefix_byte, feature_name });2682 , .{ prefix_byte, feature_name });
2801 }2683 }
2802 }2684 }
2803};2685};
lib/std/Build/Step/Compile.zig+6-13
...@@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {1542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
1543 if (compile.version) |version| {1543 if (compile.version) |version| {
1544 try zig_args.append("--version");1544 try zig_args.append("--version");
1545 try zig_args.append(b.fmt("{}", .{version}));1545 try zig_args.append(b.fmt("{f}", .{version}));
1546 }1546 }
15471547
1548 if (compile.rootModuleTarget().os.tag.isDarwin()) {1548 if (compile.rootModuleTarget().os.tag.isDarwin()) {
...@@ -1696,9 +1696,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1696,9 +1696,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
16961696
1697 if (compile.build_id orelse b.build_id) |build_id| {1697 if (compile.build_id orelse b.build_id) |build_id| {
1698 try zig_args.append(switch (build_id) {1698 try zig_args.append(switch (build_id) {
1699 .hexstring => |hs| b.fmt("--build-id=0x{s}", .{1699 .hexstring => |hs| b.fmt("--build-id=0x{x}", .{hs.toSlice()}),
1700 std.fmt.fmtSliceHexLower(hs.toSlice()),
1701 }),
1702 .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),1700 .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
1703 });1701 });
1704 }1702 }
...@@ -1706,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1706,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1706 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|1704 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
1707 dir.getPath2(b, step)1705 dir.getPath2(b, step)
1708 else if (b.graph.zig_lib_directory.path) |_|1706 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})
1710 else1708 else
1711 null;1709 null;
17121710
...@@ -1746,8 +1744,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1746,8 +1744,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1746 }1744 }
17471745
1748 if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{1746 if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{
1749 "--error-limit",1747 "--error-limit", b.fmt("{d}", .{err_limit}),
1750 b.fmt("{}", .{err_limit}),
1751 });1748 });
17521749
1753 try addFlag(&zig_args, "incremental", b.graph.incremental);1750 try addFlag(&zig_args, "incremental", b.graph.incremental);
...@@ -1793,11 +1790,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1793,11 +1790,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1793 var args_hash: [Sha256.digest_length]u8 = undefined;1790 var args_hash: [Sha256.digest_length]u8 = undefined;
1794 Sha256.hash(args, &args_hash, .{});1791 Sha256.hash(args, &args_hash, .{});
1795 var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;1792 var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;
1796 _ = try std.fmt.bufPrint(1793 _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});
1797 &args_hex_hash,
1798 "{s}",
1799 .{std.fmt.fmtSliceHexLower(&args_hash)},
1800 );
18011794
1802 const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;1795 const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;
1803 try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });1796 try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });
...@@ -1836,7 +1829,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -1836,7 +1829,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
1836 // Update generated files1829 // Update generated files
1837 if (maybe_output_dir) |output_dir| {1830 if (maybe_output_dir) |output_dir| {
1838 if (compile.emit_directory) |lp| {1831 if (compile.emit_directory) |lp| {
1839 lp.path = b.fmt("{}", .{output_dir});1832 lp.path = b.fmt("{f}", .{output_dir});
1840 }1833 }
18411834
1842 // zig fmt: off1835 // zig fmt: off
lib/std/Build/Step/ConfigHeader.zig+91-139
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const ConfigHeader = @This();2const ConfigHeader = @This();
3const Step = std.Build.Step;3const Step = std.Build.Step;
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const Writer = std.io.Writer;
56
6pub const Style = union(enum) {7pub const Style = union(enum) {
7 /// A configure format supported by autotools that uses `#undef foo` to8 /// A configure format supported by autotools that uses `#undef foo` to
...@@ -87,7 +88,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -87,7 +88,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
87 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });88 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
8889
89 config_header.* = .{90 config_header.* = .{
90 .step = Step.init(.{91 .step = .init(.{
91 .id = base_id,92 .id = base_id,
92 .name = name,93 .name = name,
93 .owner = owner,94 .owner = owner,
...@@ -95,7 +96,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -95,7 +96,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
95 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),96 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
96 }),97 }),
97 .style = options.style,98 .style = options.style,
98 .values = std.StringArrayHashMap(Value).init(owner.allocator),99 .values = .init(owner.allocator),
99100
100 .max_bytes = options.max_bytes,101 .max_bytes = options.max_bytes,
101 .include_path = include_path,102 .include_path = include_path,
...@@ -195,8 +196,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -195,8 +196,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
195 man.hash.addBytes(config_header.include_path);196 man.hash.addBytes(config_header.include_path);
196 man.hash.addOptionalBytes(config_header.include_guard_override);197 man.hash.addOptionalBytes(config_header.include_guard_override);
197198
198 var output = std.ArrayList(u8).init(gpa);199 var aw: std.io.Writer.Allocating = .init(gpa);
199 defer output.deinit();200 defer aw.deinit();
201 const bw = &aw.interface;
200202
201 const header_text = "This file was generated by ConfigHeader using the Zig Build System.";203 const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
202 const c_generated_line = "/* " ++ header_text ++ " */\n";204 const c_generated_line = "/* " ++ header_text ++ " */\n";
...@@ -204,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -204,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
204206
205 switch (config_header.style) {207 switch (config_header.style) {
206 .autoconf_undef, .autoconf, .autoconf_at => |file_source| {208 .autoconf_undef, .autoconf, .autoconf_at => |file_source| {
207 try output.appendSlice(c_generated_line);209 try bw.writeAll(c_generated_line);
208 const src_path = file_source.getPath2(b, step);210 const src_path = file_source.getPath2(b, step);
209 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {211 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
210 return step.fail("unable to read autoconf input file '{s}': {s}", .{212 return step.fail("unable to read autoconf input file '{s}': {s}", .{
...@@ -212,32 +214,33 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -212,32 +214,33 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
212 });214 });
213 };215 };
214 switch (config_header.style) {216 switch (config_header.style) {
215 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path),217 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
216 .autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path),218 .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
217 else => unreachable,219 else => unreachable,
218 }220 }
219 },221 },
220 .cmake => |file_source| {222 .cmake => |file_source| {
221 try output.appendSlice(c_generated_line);223 try bw.writeAll(c_generated_line);
222 const src_path = file_source.getPath2(b, step);224 const src_path = file_source.getPath2(b, step);
223 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {225 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
224 return step.fail("unable to read cmake input file '{s}': {s}", .{226 return step.fail("unable to read cmake input file '{s}': {s}", .{
225 src_path, @errorName(err),227 src_path, @errorName(err),
226 });228 });
227 };229 };
228 try render_cmake(step, contents, &output, config_header.values, src_path);230 try render_cmake(step, contents, bw, config_header.values, src_path);
229 },231 },
230 .blank => {232 .blank => {
231 try output.appendSlice(c_generated_line);233 try bw.writeAll(c_generated_line);
232 try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override);234 try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override);
233 },235 },
234 .nasm => {236 .nasm => {
235 try output.appendSlice(asm_generated_line);237 try bw.writeAll(asm_generated_line);
236 try render_nasm(&output, config_header.values);238 try render_nasm(bw, config_header.values);
237 },239 },
238 }240 }
239241
240 man.hash.addBytes(output.items);242 const output = aw.getWritten();
243 man.hash.addBytes(output);
241244
242 if (try step.cacheHit(&man)) {245 if (try step.cacheHit(&man)) {
243 const digest = man.final();246 const digest = man.final();
...@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
256 const sub_path_dirname = std.fs.path.dirname(sub_path).?;259 const sub_path_dirname = std.fs.path.dirname(sub_path).?;
257260
258 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {261 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}", .{
260 b.cache_root, sub_path_dirname, @errorName(err),263 b.cache_root, sub_path_dirname, @errorName(err),
261 });264 });
262 };265 };
263266
264 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| {267 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| {
265 return step.fail("unable to write file '{}{s}': {s}", .{268 return step.fail("unable to write file '{f}{s}': {s}", .{
266 b.cache_root, sub_path, @errorName(err),269 b.cache_root, sub_path, @errorName(err),
267 });270 });
268 };271 };
...@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
274fn render_autoconf_undef(277fn render_autoconf_undef(
275 step: *Step,278 step: *Step,
276 contents: []const u8,279 contents: []const u8,
277 output: *std.ArrayList(u8),280 bw: *Writer,
278 values: std.StringArrayHashMap(Value),281 values: std.StringArrayHashMap(Value),
279 src_path: []const u8,282 src_path: []const u8,
280) !void {283) !void {
...@@ -289,15 +292,15 @@ fn render_autoconf_undef(...@@ -289,15 +292,15 @@ fn render_autoconf_undef(
289 var line_it = std.mem.splitScalar(u8, contents, '\n');292 var line_it = std.mem.splitScalar(u8, contents, '\n');
290 while (line_it.next()) |line| : (line_index += 1) {293 while (line_it.next()) |line| : (line_index += 1) {
291 if (!std.mem.startsWith(u8, line, "#")) {294 if (!std.mem.startsWith(u8, line, "#")) {
292 try output.appendSlice(line);295 try bw.writeAll(line);
293 try output.appendSlice("\n");296 try bw.writeByte('\n');
294 continue;297 continue;
295 }298 }
296 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");299 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
297 const undef = it.next().?;300 const undef = it.next().?;
298 if (!std.mem.eql(u8, undef, "undef")) {301 if (!std.mem.eql(u8, undef, "undef")) {
299 try output.appendSlice(line);302 try bw.writeAll(line);
300 try output.appendSlice("\n");303 try bw.writeByte('\n');
301 continue;304 continue;
302 }305 }
303 const name = it.next().?;306 const name = it.next().?;
...@@ -309,7 +312,7 @@ fn render_autoconf_undef(...@@ -309,7 +312,7 @@ fn render_autoconf_undef(
309 continue;312 continue;
310 };313 };
311 is_used.set(index);314 is_used.set(index);
312 try renderValueC(output, name, values.values()[index]);315 try renderValueC(bw, name, values.values()[index]);
313 }316 }
314317
315 var unused_value_it = is_used.iterator(.{ .kind = .unset });318 var unused_value_it = is_used.iterator(.{ .kind = .unset });
...@@ -326,12 +329,13 @@ fn render_autoconf_undef(...@@ -326,12 +329,13 @@ fn render_autoconf_undef(
326fn render_autoconf_at(329fn render_autoconf_at(
327 step: *Step,330 step: *Step,
328 contents: []const u8,331 contents: []const u8,
329 output: *std.ArrayList(u8),332 aw: *std.io.Writer.Allocating,
330 values: std.StringArrayHashMap(Value),333 values: std.StringArrayHashMap(Value),
331 src_path: []const u8,334 src_path: []const u8,
332) !void {335) !void {
333 const build = step.owner;336 const build = step.owner;
334 const allocator = build.allocator;337 const allocator = build.allocator;
338 const bw = &aw.interface;
335339
336 const used = allocator.alloc(bool, values.count()) catch @panic("OOM");340 const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
337 for (used) |*u| u.* = false;341 for (used) |*u| u.* = false;
...@@ -343,11 +347,11 @@ fn render_autoconf_at(...@@ -343,11 +347,11 @@ fn render_autoconf_at(
343 while (line_it.next()) |line| : (line_index += 1) {347 while (line_it.next()) |line| : (line_index += 1) {
344 const last_line = line_it.index == line_it.buffer.len;348 const last_line = line_it.index == line_it.buffer.len;
345349
346 const old_len = output.items.len;350 const old_len = aw.getWritten().len;
347 expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) {351 expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) {
348 error.MissingValue => {352 error.MissingValue => {
349 const name = output.items[old_len..];353 const name = aw.getWritten()[old_len..];
350 defer output.shrinkRetainingCapacity(old_len);354 defer aw.shrinkRetainingCapacity(old_len);
351 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{355 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
352 src_path, line_index + 1, name,356 src_path, line_index + 1, name,
353 });357 });
...@@ -362,9 +366,7 @@ fn render_autoconf_at(...@@ -362,9 +366,7 @@ fn render_autoconf_at(
362 continue;366 continue;
363 },367 },
364 };368 };
365 if (!last_line) {369 if (!last_line) try bw.writeByte('\n');
366 try output.append('\n');
367 }
368 }370 }
369371
370 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {372 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
...@@ -374,15 +376,13 @@ fn render_autoconf_at(...@@ -374,15 +376,13 @@ fn render_autoconf_at(
374 }376 }
375 }377 }
376378
377 if (any_errors) {379 if (any_errors) return error.MakeFailed;
378 return error.MakeFailed;
379 }
380}380}
381381
382fn render_cmake(382fn render_cmake(
383 step: *Step,383 step: *Step,
384 contents: []const u8,384 contents: []const u8,
385 output: *std.ArrayList(u8),385 bw: *Writer,
386 values: std.StringArrayHashMap(Value),386 values: std.StringArrayHashMap(Value),
387 src_path: []const u8,387 src_path: []const u8,
388) !void {388) !void {
...@@ -417,10 +417,8 @@ fn render_cmake(...@@ -417,10 +417,8 @@ fn render_cmake(
417 defer allocator.free(line);417 defer allocator.free(line);
418418
419 if (!std.mem.startsWith(u8, line, "#")) {419 if (!std.mem.startsWith(u8, line, "#")) {
420 try output.appendSlice(line);420 try bw.writeAll(line);
421 if (!last_line) {421 if (!last_line) try bw.writeByte('\n');
422 try output.appendSlice("\n");
423 }
424 continue;422 continue;
425 }423 }
426 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");424 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
...@@ -428,10 +426,8 @@ fn render_cmake(...@@ -428,10 +426,8 @@ fn render_cmake(
428 if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and426 if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
429 !std.mem.eql(u8, cmakedefine, "cmakedefine01"))427 !std.mem.eql(u8, cmakedefine, "cmakedefine01"))
430 {428 {
431 try output.appendSlice(line);429 try bw.writeAll(line);
432 if (!last_line) {430 if (!last_line) try bw.writeByte('\n');
433 try output.appendSlice("\n");
434 }
435 continue;431 continue;
436 }432 }
437433
...@@ -502,7 +498,7 @@ fn render_cmake(...@@ -502,7 +498,7 @@ fn render_cmake(
502 value = Value{ .ident = it.rest() };498 value = Value{ .ident = it.rest() };
503 }499 }
504500
505 try renderValueC(output, name, value);501 try renderValueC(bw, name, value);
506 }502 }
507503
508 if (any_errors) {504 if (any_errors) {
...@@ -511,13 +507,14 @@ fn render_cmake(...@@ -511,13 +507,14 @@ fn render_cmake(
511}507}
512508
513fn render_blank(509fn render_blank(
514 output: *std.ArrayList(u8),510 gpa: std.mem.Allocator,
511 bw: *Writer,
515 defines: std.StringArrayHashMap(Value),512 defines: std.StringArrayHashMap(Value),
516 include_path: []const u8,513 include_path: []const u8,
517 include_guard_override: ?[]const u8,514 include_guard_override: ?[]const u8,
518) !void {515) !void {
519 const include_guard_name = include_guard_override orelse blk: {516 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);
521 for (name) |*byte| {518 for (name) |*byte| {
522 switch (byte.*) {519 switch (byte.*) {
523 'a'...'z' => byte.* = byte.* - 'a' + 'A',520 'a'...'z' => byte.* = byte.* - 'a' + 'A',
...@@ -527,92 +524,53 @@ fn render_blank(...@@ -527,92 +524,53 @@ fn render_blank(
527 }524 }
528 break :blk name;525 break :blk name;
529 };526 };
527 defer if (include_guard_override == null) gpa.free(include_guard_name);
530528
531 try output.appendSlice("#ifndef ");529 try bw.print(
532 try output.appendSlice(include_guard_name);530 \\#ifndef {[0]s}
533 try output.appendSlice("\n#define ");531 \\#define {[0]s}
534 try output.appendSlice(include_guard_name);532 \\
535 try output.appendSlice("\n");533 , .{include_guard_name});
536534
537 const values = defines.values();535 const values = defines.values();
538 for (defines.keys(), 0..) |name, i| {536 for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]);
539 try renderValueC(output, name, values[i]);
540 }
541537
542 try output.appendSlice("#endif /* ");538 try bw.print(
543 try output.appendSlice(include_guard_name);539 \\#endif /* {s} */
544 try output.appendSlice(" */\n");540 \\
541 , .{include_guard_name});
545}542}
546543
547fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void {544fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {
548 const values = defines.values();545 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
549 for (defines.keys(), 0..) |name, i| {
550 try renderValueNasm(output, name, values[i]);
551 }
552}546}
553547
554fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {548fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void {
555 switch (value) {549 switch (value) {
556 .undef => {550 .undef => try bw.print("/* #undef {s} */\n", .{name}),
557 try output.appendSlice("/* #undef ");551 .defined => try bw.print("#define {s}\n", .{name}),
558 try output.appendSlice(name);552 .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
559 try output.appendSlice(" */\n");553 .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }),
560 },554 .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }),
561 .defined => {555 // TODO: use C-specific escaping instead of zig string literals
562 try output.appendSlice("#define ");556 .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
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 },
581 }557 }
582}558}
583559
584fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {560fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
585 switch (value) {561 switch (value) {
586 .undef => {562 .undef => try bw.print("; %undef {s}\n", .{name}),
587 try output.appendSlice("; %undef ");563 .defined => try bw.print("%define {s}\n", .{name}),
588 try output.appendSlice(name);564 .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
589 try output.appendSlice("\n");565 .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }),
590 },566 .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }),
591 .defined => {567 // TODO: use nasm-specific escaping instead of zig string literals
592 try output.appendSlice("%define ");568 .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
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 },
611 }569 }
612}570}
613571
614fn expand_variables_autoconf_at(572fn expand_variables_autoconf_at(
615 output: *std.ArrayList(u8),573 bw: *Writer,
616 contents: []const u8,574 contents: []const u8,
617 values: std.StringArrayHashMap(Value),575 values: std.StringArrayHashMap(Value),
618 used: []bool,576 used: []bool,
...@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(...@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(
637 const key = contents[curr + 1 .. close_pos];595 const key = contents[curr + 1 .. close_pos];
638 const index = values.getIndex(key) orelse {596 const index = values.getIndex(key) orelse {
639 // Report the missing key to the caller.597 // Report the missing key to the caller.
640 try output.appendSlice(key);598 try bw.writeAll(key);
641 return error.MissingValue;599 return error.MissingValue;
642 };600 };
643 const value = values.unmanaged.entries.slice().items(.value)[index];601 const value = values.unmanaged.entries.slice().items(.value)[index];
644 used[index] = true;602 used[index] = true;
645 try output.appendSlice(contents[source_offset..curr]);603 try bw.writeAll(contents[source_offset..curr]);
646 switch (value) {604 switch (value) {
647 .undef, .defined => {},605 .undef, .defined => {},
648 .boolean => |b| {606 .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)),
649 try output.append(if (b) '1' else '0');607 .int => |i| try bw.print("{d}", .{i}),
650 },608 .ident, .string => |s| try bw.writeAll(s),
651 .int => |i| {
652 try output.writer().print("{d}", .{i});
653 },
654 .ident, .string => |s| {
655 try output.appendSlice(s);
656 },
657 }609 }
658610
659 curr = close_pos;611 curr = close_pos;
...@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(...@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(
661 }613 }
662 }614 }
663615
664 try output.appendSlice(contents[source_offset..]);616 try bw.writeAll(contents[source_offset..]);
665}617}
666618
667fn expand_variables_cmake(619fn expand_variables_cmake(
...@@ -669,7 +621,7 @@ fn expand_variables_cmake(...@@ -669,7 +621,7 @@ fn expand_variables_cmake(
669 contents: []const u8,621 contents: []const u8,
670 values: std.StringArrayHashMap(Value),622 values: std.StringArrayHashMap(Value),
671) ![]const u8 {623) ![]const u8 {
672 var result = std.ArrayList(u8).init(allocator);624 var result: std.ArrayList(u8) = .init(allocator);
673 errdefer result.deinit();625 errdefer result.deinit();
674626
675 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";627 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
...@@ -681,7 +633,7 @@ fn expand_variables_cmake(...@@ -681,7 +633,7 @@ fn expand_variables_cmake(
681 source: usize,633 source: usize,
682 target: usize,634 target: usize,
683 };635 };
684 var var_stack = std.ArrayList(Position).init(allocator);636 var var_stack: std.ArrayList(Position) = .init(allocator);
685 defer var_stack.deinit();637 defer var_stack.deinit();
686 loop: while (curr < contents.len) : (curr += 1) {638 loop: while (curr < contents.len) : (curr += 1) {
687 switch (contents[curr]) {639 switch (contents[curr]) {
...@@ -707,7 +659,7 @@ fn expand_variables_cmake(...@@ -707,7 +659,7 @@ fn expand_variables_cmake(
707 try result.append(if (b) '1' else '0');659 try result.append(if (b) '1' else '0');
708 },660 },
709 .int => |i| {661 .int => |i| {
710 try result.writer().print("{d}", .{i});662 try result.print("{d}", .{i});
711 },663 },
712 .ident, .string => |s| {664 .ident, .string => |s| {
713 try result.appendSlice(s);665 try result.appendSlice(s);
...@@ -764,7 +716,7 @@ fn expand_variables_cmake(...@@ -764,7 +716,7 @@ fn expand_variables_cmake(
764 try result.append(if (b) '1' else '0');716 try result.append(if (b) '1' else '0');
765 },717 },
766 .int => |i| {718 .int => |i| {
767 try result.writer().print("{d}", .{i});719 try result.print("{d}", .{i});
768 },720 },
769 .ident, .string => |s| {721 .ident, .string => |s| {
770 try result.appendSlice(s);722 try result.appendSlice(s);
...@@ -801,17 +753,17 @@ fn testReplaceVariablesAutoconfAt(...@@ -801,17 +753,17 @@ fn testReplaceVariablesAutoconfAt(
801 expected: []const u8,753 expected: []const u8,
802 values: std.StringArrayHashMap(Value),754 values: std.StringArrayHashMap(Value),
803) !void {755) !void {
804 var output = std.ArrayList(u8).init(allocator);756 var output: std.io.Writer.Allocating = .init(allocator);
805 defer output.deinit();757 defer output.deinit();
806758
807 const used = try allocator.alloc(bool, values.count());759 const used = try allocator.alloc(bool, values.count());
808 for (used) |*u| u.* = false;760 for (used) |*u| u.* = false;
809 defer allocator.free(used);761 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
813 for (used) |u| if (!u) return error.UnusedValue;765 for (used) |u| if (!u) return error.UnusedValue;
814 try std.testing.expectEqualStrings(expected, output.items);766 try std.testing.expectEqualStrings(expected, output.getWritten());
815}767}
816768
817fn testReplaceVariablesCMake(769fn testReplaceVariablesCMake(
...@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(...@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(
828780
829test "expand_variables_autoconf_at simple cases" {781test "expand_variables_autoconf_at simple cases" {
830 const allocator = std.testing.allocator;782 const allocator = std.testing.allocator;
831 var values = std.StringArrayHashMap(Value).init(allocator);783 var values: std.StringArrayHashMap(Value) = .init(allocator);
832 defer values.deinit();784 defer values.deinit();
833785
834 // empty strings are preserved786 // empty strings are preserved
...@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {...@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {
924876
925test "expand_variables_autoconf_at edge cases" {877test "expand_variables_autoconf_at edge cases" {
926 const allocator = std.testing.allocator;878 const allocator = std.testing.allocator;
927 var values = std.StringArrayHashMap(Value).init(allocator);879 var values: std.StringArrayHashMap(Value) = .init(allocator);
928 defer values.deinit();880 defer values.deinit();
929881
930 // @-vars resolved only when they wrap valid characters, otherwise considered literals882 // @-vars resolved only when they wrap valid characters, otherwise considered literals
...@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {...@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {
940892
941test "expand_variables_cmake simple cases" {893test "expand_variables_cmake simple cases" {
942 const allocator = std.testing.allocator;894 const allocator = std.testing.allocator;
943 var values = std.StringArrayHashMap(Value).init(allocator);895 var values: std.StringArrayHashMap(Value) = .init(allocator);
944 defer values.deinit();896 defer values.deinit();
945897
946 try values.putNoClobber("undef", .undef);898 try values.putNoClobber("undef", .undef);
...@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {...@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {
1028980
1029test "expand_variables_cmake edge cases" {981test "expand_variables_cmake edge cases" {
1030 const allocator = std.testing.allocator;982 const allocator = std.testing.allocator;
1031 var values = std.StringArrayHashMap(Value).init(allocator);983 var values: std.StringArrayHashMap(Value) = .init(allocator);
1032 defer values.deinit();984 defer values.deinit();
1033985
1034 // special symbols986 // special symbols
...@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {...@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {
10891041
1090test "expand_variables_cmake escaped characters" {1042test "expand_variables_cmake escaped characters" {
1091 const allocator = std.testing.allocator;1043 const allocator = std.testing.allocator;
1092 var values = std.StringArrayHashMap(Value).init(allocator);1044 var values: std.StringArrayHashMap(Value) = .init(allocator);
1093 defer values.deinit();1045 defer values.deinit();
10941046
1095 try values.putNoClobber("string", Value{ .string = "text" });1047 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 {...@@ -164,7 +164,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
164 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);164 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
165165
166 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {166 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}", .{
168 src_dir_path, @errorName(err),168 src_dir_path, @errorName(err),
169 });169 });
170 };170 };
lib/std/Build/Step/InstallDir.zig+1-1
...@@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
65 const src_dir_path = install_dir.options.source_dir.getPath3(b, step);65 const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
66 const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);66 const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
67 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {67 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}", .{
69 src_dir_path, @errorName(err),69 src_dir_path, @errorName(err),
70 });70 });
71 };71 };
lib/std/Build/Step/Options.zig+146-112
...@@ -12,23 +12,23 @@ pub const base_id: Step.Id = .options;...@@ -12,23 +12,23 @@ pub const base_id: Step.Id = .options;
12step: Step,12step: Step,
13generated_file: GeneratedFile,13generated_file: GeneratedFile,
1414
15contents: std.ArrayList(u8),15contents: std.ArrayListUnmanaged(u8),
16args: std.ArrayList(Arg),16args: std.ArrayListUnmanaged(Arg),
17encountered_types: std.StringHashMap(void),17encountered_types: std.StringHashMapUnmanaged(void),
1818
19pub fn create(owner: *std.Build) *Options {19pub fn create(owner: *std.Build) *Options {
20 const options = owner.allocator.create(Options) catch @panic("OOM");20 const options = owner.allocator.create(Options) catch @panic("OOM");
21 options.* = .{21 options.* = .{
22 .step = Step.init(.{22 .step = .init(.{
23 .id = base_id,23 .id = base_id,
24 .name = "options",24 .name = "options",
25 .owner = owner,25 .owner = owner,
26 .makeFn = make,26 .makeFn = make,
27 }),27 }),
28 .generated_file = undefined,28 .generated_file = undefined,
29 .contents = std.ArrayList(u8).init(owner.allocator),29 .contents = .empty,
30 .args = std.ArrayList(Arg).init(owner.allocator),30 .args = .empty,
31 .encountered_types = std.StringHashMap(void).init(owner.allocator),31 .encountered_types = .empty,
32 };32 };
33 options.generated_file = .{ .step = &options.step };33 options.generated_file = .{ .step = &options.step };
3434
...@@ -40,110 +40,119 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T...@@ -40,110 +40,119 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T
40}40}
4141
42fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {42fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {
43 const out = options.contents.writer();43 try printType(options, &options.contents, T, value, 0, name);
44 try printType(options, out, T, value, 0, name);
45}44}
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;
48 switch (T) {55 switch (T) {
49 []const []const u8 => {56 []const []const u8 => {
50 if (name) |payload| {57 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)});
52 }59 }
5360
54 try out.writeAll("&[_][]const u8{\n");61 try out.appendSlice(gpa, "&[_][]const u8{\n");
5562
56 for (value) |slice| {63 for (value) |slice| {
57 try out.writeByteNTimes(' ', indent);64 try out.appendNTimes(gpa, ' ', indent);
58 try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)});65 try out.print(gpa, " \"{f}\",\n", .{std.zig.fmtString(slice)});
59 }66 }
6067
61 if (name != null) {68 if (name != null) {
62 try out.writeAll("};\n");69 try out.appendSlice(gpa, "};\n");
63 } else {70 } else {
64 try out.writeAll("},\n");71 try out.appendSlice(gpa, "},\n");
65 }72 }
6673
67 return;74 return;
68 },75 },
69 []const u8 => {76 []const u8 => {
70 if (name) |some| {77 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 });
72 } else {81 } else {
73 try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});82 try out.print(gpa, "\"{f}\",", .{std.zig.fmtString(value)});
74 }83 }
75 return out.writeAll("\n");84 return out.appendSlice(gpa, "\n");
76 },85 },
77 [:0]const u8 => {86 [:0]const u8 => {
78 if (name) |some| {87 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) });
80 } else {89 } else {
81 try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});90 try out.print(gpa, "\"{f}\",", .{std.zig.fmtString(value)});
82 }91 }
83 return out.writeAll("\n");92 return out.appendSlice(gpa, "\n");
84 },93 },
85 ?[]const u8 => {94 ?[]const u8 => {
86 if (name) |some| {95 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)});
88 }97 }
8998
90 if (value) |payload| {99 if (value) |payload| {
91 try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});100 try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)});
92 } else {101 } else {
93 try out.writeAll("null");102 try out.appendSlice(gpa, "null");
94 }103 }
95104
96 if (name != null) {105 if (name != null) {
97 try out.writeAll(";\n");106 try out.appendSlice(gpa, ";\n");
98 } else {107 } else {
99 try out.writeAll(",\n");108 try out.appendSlice(gpa, ",\n");
100 }109 }
101 return;110 return;
102 },111 },
103 ?[:0]const u8 => {112 ?[:0]const u8 => {
104 if (name) |some| {113 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)});
106 }115 }
107116
108 if (value) |payload| {117 if (value) |payload| {
109 try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});118 try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)});
110 } else {119 } else {
111 try out.writeAll("null");120 try out.appendSlice(gpa, "null");
112 }121 }
113122
114 if (name != null) {123 if (name != null) {
115 try out.writeAll(";\n");124 try out.appendSlice(gpa, ";\n");
116 } else {125 } else {
117 try out.writeAll(",\n");126 try out.appendSlice(gpa, ",\n");
118 }127 }
119 return;128 return;
120 },129 },
121 std.SemanticVersion => {130 std.SemanticVersion => {
122 if (name) |some| {131 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)});
124 }133 }
125134
126 try out.writeAll(".{\n");135 try out.appendSlice(gpa, ".{\n");
127 try out.writeByteNTimes(' ', indent);136 try out.appendNTimes(gpa, ' ', indent);
128 try out.print(" .major = {d},\n", .{value.major});137 try out.print(gpa, " .major = {d},\n", .{value.major});
129 try out.writeByteNTimes(' ', indent);138 try out.appendNTimes(gpa, ' ', indent);
130 try out.print(" .minor = {d},\n", .{value.minor});139 try out.print(gpa, " .minor = {d},\n", .{value.minor});
131 try out.writeByteNTimes(' ', indent);140 try out.appendNTimes(gpa, ' ', indent);
132 try out.print(" .patch = {d},\n", .{value.patch});141 try out.print(gpa, " .patch = {d},\n", .{value.patch});
133142
134 if (value.pre) |some| {143 if (value.pre) |some| {
135 try out.writeByteNTimes(' ', indent);144 try out.appendNTimes(gpa, ' ', indent);
136 try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});145 try out.print(gpa, " .pre = \"{f}\",\n", .{std.zig.fmtString(some)});
137 }146 }
138 if (value.build) |some| {147 if (value.build) |some| {
139 try out.writeByteNTimes(' ', indent);148 try out.appendNTimes(gpa, ' ', indent);
140 try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});149 try out.print(gpa, " .build = \"{f}\",\n", .{std.zig.fmtString(some)});
141 }150 }
142151
143 if (name != null) {152 if (name != null) {
144 try out.writeAll("};\n");153 try out.appendSlice(gpa, "};\n");
145 } else {154 } else {
146 try out.writeAll("},\n");155 try out.appendSlice(gpa, "},\n");
147 }156 }
148 return;157 return;
149 },158 },
...@@ -153,21 +162,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -153,21 +162,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
153 switch (@typeInfo(T)) {162 switch (@typeInfo(T)) {
154 .array => {163 .array => {
155 if (name) |some| {164 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) });
157 }166 }
158167
159 try out.print("{s} {{\n", .{@typeName(T)});168 try out.print(gpa, "{s} {{\n", .{@typeName(T)});
160 for (value) |item| {169 for (value) |item| {
161 try out.writeByteNTimes(' ', indent + 4);170 try out.appendNTimes(gpa, ' ', indent + 4);
162 try printType(options, out, @TypeOf(item), item, indent + 4, null);171 try printType(options, out, @TypeOf(item), item, indent + 4, null);
163 }172 }
164 try out.writeByteNTimes(' ', indent);173 try out.appendNTimes(gpa, ' ', indent);
165 try out.writeAll("}");174 try out.appendSlice(gpa, "}");
166175
167 if (name != null) {176 if (name != null) {
168 try out.writeAll(";\n");177 try out.appendSlice(gpa, ";\n");
169 } else {178 } else {
170 try out.writeAll(",\n");179 try out.appendSlice(gpa, ",\n");
171 }180 }
172 return;181 return;
173 },182 },
...@@ -177,27 +186,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -177,27 +186,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
177 }186 }
178187
179 if (name) |some| {188 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) });
181 }190 }
182191
183 try out.print("&[_]{s} {{\n", .{@typeName(p.child)});192 try out.print(gpa, "&[_]{s} {{\n", .{@typeName(p.child)});
184 for (value) |item| {193 for (value) |item| {
185 try out.writeByteNTimes(' ', indent + 4);194 try out.appendNTimes(gpa, ' ', indent + 4);
186 try printType(options, out, @TypeOf(item), item, indent + 4, null);195 try printType(options, out, @TypeOf(item), item, indent + 4, null);
187 }196 }
188 try out.writeByteNTimes(' ', indent);197 try out.appendNTimes(gpa, ' ', indent);
189 try out.writeAll("}");198 try out.appendSlice(gpa, "}");
190199
191 if (name != null) {200 if (name != null) {
192 try out.writeAll(";\n");201 try out.appendSlice(gpa, ";\n");
193 } else {202 } else {
194 try out.writeAll(",\n");203 try out.appendSlice(gpa, ",\n");
195 }204 }
196 return;205 return;
197 },206 },
198 .optional => {207 .optional => {
199 if (name) |some| {208 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) });
201 }210 }
202211
203 if (value) |inner| {212 if (value) |inner| {
...@@ -206,13 +215,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -206,13 +215,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
206 _ = options.contents.pop();215 _ = options.contents.pop();
207 _ = options.contents.pop();216 _ = options.contents.pop();
208 } else {217 } else {
209 try out.writeAll("null");218 try out.appendSlice(gpa, "null");
210 }219 }
211220
212 if (name != null) {221 if (name != null) {
213 try out.writeAll(";\n");222 try out.appendSlice(gpa, ";\n");
214 } else {223 } else {
215 try out.writeAll(",\n");224 try out.appendSlice(gpa, ",\n");
216 }225 }
217 return;226 return;
218 },227 },
...@@ -224,9 +233,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -224,9 +233,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
224 .null,233 .null,
225 => {234 => {
226 if (name) |some| {235 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 });
228 } else {237 } else {
229 try out.print("{any},\n", .{value});238 try out.print(gpa, "{any},\n", .{value});
230 }239 }
231 return;240 return;
232 },241 },
...@@ -234,10 +243,10 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -234,10 +243,10 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
234 try printEnum(options, out, T, info, indent);243 try printEnum(options, out, T, info, indent);
235244
236 if (name) |some| {245 if (name) |some| {
237 try out.print("pub const {}: {} = .{p_};\n", .{246 try out.print(gpa, "pub const {f}: {f} = .{f};\n", .{
238 std.zig.fmtId(some),247 std.zig.fmtId(some),
239 std.zig.fmtId(@typeName(T)),248 std.zig.fmtId(@typeName(T)),
240 std.zig.fmtId(@tagName(value)),249 std.zig.fmtIdFlags(@tagName(value), .{ .allow_underscore = true, .allow_primitive = true }),
241 });250 });
242 }251 }
243 return;252 return;
...@@ -246,7 +255,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -246,7 +255,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
246 try printStruct(options, out, T, info, indent);255 try printStruct(options, out, T, info, indent);
247256
248 if (name) |some| {257 if (name) |some| {
249 try out.print("pub const {}: {} = ", .{258 try out.print(gpa, "pub const {f}: {f} = ", .{
250 std.zig.fmtId(some),259 std.zig.fmtId(some),
251 std.zig.fmtId(@typeName(T)),260 std.zig.fmtId(@typeName(T)),
252 });261 });
...@@ -258,7 +267,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -258,7 +267,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
258 }267 }
259}268}
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 {
262 switch (@typeInfo(T)) {271 switch (@typeInfo(T)) {
263 .@"enum" => |info| {272 .@"enum" => |info| {
264 return try printEnum(options, out, T, info, indent);273 return try printEnum(options, out, T, info, indent);
...@@ -270,94 +279,119 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden...@@ -270,94 +279,119 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden
270 }279 }
271}280}
272281
273fn printEnum(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Enum, indent: u8) !void {282fn printEnum(
274 const gop = try options.encountered_types.getOrPut(@typeName(T));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));
275 if (gop.found_existing) return;291 if (gop.found_existing) return;
276292
277 try out.writeByteNTimes(' ', indent);293 try out.appendNTimes(gpa, ' ', indent);
278 try out.print("pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });294 try out.print(gpa, "pub const {f} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
279295
280 inline for (val.fields) |field| {296 inline for (val.fields) |field| {
281 try out.writeByteNTimes(' ', indent);297 try out.appendNTimes(gpa, ' ', indent);
282 try out.print(" {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });298 try out.print(gpa, " {f} = {d},\n", .{
299 std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true }), field.value,
300 });
283 }301 }
284302
285 if (!val.is_exhaustive) {303 if (!val.is_exhaustive) {
286 try out.writeByteNTimes(' ', indent);304 try out.appendNTimes(gpa, ' ', indent);
287 try out.writeAll(" _,\n");305 try out.appendSlice(gpa, " _,\n");
288 }306 }
289307
290 try out.writeByteNTimes(' ', indent);308 try out.appendNTimes(gpa, ' ', indent);
291 try out.writeAll("};\n");309 try out.appendSlice(gpa, "};\n");
292}310}
293311
294fn printStruct(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {312fn printStruct(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
295 const gop = try options.encountered_types.getOrPut(@typeName(T));313 const gpa = options.step.owner.allocator;
314 const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
296 if (gop.found_existing) return;315 if (gop.found_existing) return;
297316
298 try out.writeByteNTimes(' ', indent);317 try out.appendNTimes(gpa, ' ', indent);
299 try out.print("pub const {} = ", .{std.zig.fmtId(@typeName(T))});318 try out.print(gpa, "pub const {f} = ", .{std.zig.fmtId(@typeName(T))});
300319
301 switch (val.layout) {320 switch (val.layout) {
302 .@"extern" => try out.writeAll("extern struct"),321 .@"extern" => try out.appendSlice(gpa, "extern struct"),
303 .@"packed" => try out.writeAll("packed struct"),322 .@"packed" => try out.appendSlice(gpa, "packed struct"),
304 else => try out.writeAll("struct"),323 else => try out.appendSlice(gpa, "struct"),
305 }324 }
306325
307 try out.writeAll(" {\n");326 try out.appendSlice(gpa, " {\n");
308327
309 inline for (val.fields) |field| {328 inline for (val.fields) |field| {
310 try out.writeByteNTimes(' ', indent);329 try out.appendNTimes(gpa, ' ', indent);
311330
312 const type_name = @typeName(field.type);331 const type_name = @typeName(field.type);
313332
314 // If the type name doesn't contains a '.' the type is from zig builtins.333 // If the type name doesn't contains a '.' the type is from zig builtins.
315 if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {334 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 });
317 } else {339 } 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 });
319 }344 }
320345
321 if (field.defaultValue()) |default_value| {346 if (field.defaultValue()) |default_value| {
322 try out.writeAll(" = ");347 try out.appendSlice(gpa, " = ");
323 switch (@typeInfo(@TypeOf(default_value))) {348 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)}),
325 .@"struct" => |info| {350 .@"struct" => |info| {
326 try printStructValue(options, out, info, default_value, indent + 4);351 try printStructValue(options, out, info, default_value, indent + 4);
327 },352 },
328 else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),353 else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
329 }354 }
330 } else {355 } else {
331 try out.writeAll(",\n");356 try out.appendSlice(gpa, ",\n");
332 }357 }
333 }358 }
334359
335 // TODO: write declarations360 // TODO: write declarations
336361
337 try out.writeByteNTimes(' ', indent);362 try out.appendNTimes(gpa, ' ', indent);
338 try out.writeAll("};\n");363 try out.appendSlice(gpa, "};\n");
339364
340 inline for (val.fields) |field| {365 inline for (val.fields) |field| {
341 try printUserDefinedType(options, out, field.type, 0);366 try printUserDefinedType(options, out, field.type, 0);
342 }367 }
343}368}
344369
345fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.builtin.Type.Struct, val: anytype, indent: u8) !void {370fn printStructValue(
346 try out.writeAll(".{\n");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
348 if (struct_val.is_tuple) {380 if (struct_val.is_tuple) {
349 inline for (struct_val.fields) |field| {381 inline for (struct_val.fields) |field| {
350 try out.writeByteNTimes(' ', indent);382 try out.appendNTimes(gpa, ' ', indent);
351 try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);383 try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
352 }384 }
353 } else {385 } else {
354 inline for (struct_val.fields) |field| {386 inline for (struct_val.fields) |field| {
355 try out.writeByteNTimes(' ', indent);387 try out.appendNTimes(gpa, ' ', indent);
356 try out.print(" .{p_} = ", .{std.zig.fmtId(field.name)});388 try out.print(gpa, " .{f} = ", .{
389 std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true, .allow_underscore = true }),
390 });
357391
358 const field_name = @field(val, field.name);392 const field_name = @field(val, field.name);
359 switch (@typeInfo(@TypeOf(field_name))) {393 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)}),
361 .@"struct" => |struct_info| {395 .@"struct" => |struct_info| {
362 try printStructValue(options, out, struct_info, field_name, indent + 4);396 try printStructValue(options, out, struct_info, field_name, indent + 4);
363 },397 },
...@@ -367,10 +401,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu...@@ -367,10 +401,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu
367 }401 }
368402
369 if (indent == 0) {403 if (indent == 0) {
370 try out.writeAll("};\n");404 try out.appendSlice(gpa, "};\n");
371 } else {405 } else {
372 try out.writeByteNTimes(' ', indent);406 try out.appendNTimes(gpa, ' ', indent);
373 try out.writeAll("},\n");407 try out.appendSlice(gpa, "},\n");
374 }408 }
375}409}
376410
...@@ -440,7 +474,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -440,7 +474,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
440 error.FileNotFound => {474 error.FileNotFound => {
441 const sub_dirname = fs.path.dirname(sub_path).?;475 const sub_dirname = fs.path.dirname(sub_path).?;
442 b.cache_root.handle.makePath(sub_dirname) catch |e| {476 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}", .{
444 b.cache_root, sub_dirname, @errorName(e),478 b.cache_root, sub_dirname, @errorName(e),
445 });479 });
446 };480 };
...@@ -452,13 +486,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -452,13 +486,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
452 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;486 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
453487
454 b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {488 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}", .{
456 b.cache_root, tmp_sub_path_dirname, @errorName(err),490 b.cache_root, tmp_sub_path_dirname, @errorName(err),
457 });491 });
458 };492 };
459493
460 b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {494 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}", .{
462 b.cache_root, tmp_sub_path, @errorName(err),496 b.cache_root, tmp_sub_path, @errorName(err),
463 });497 });
464 };498 };
...@@ -467,7 +501,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -467,7 +501,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
467 error.PathAlreadyExists => {501 error.PathAlreadyExists => {
468 // Other process beat us to it. Clean up the temp file.502 // Other process beat us to it. Clean up the temp file.
469 b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {503 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}", .{
471 b.cache_root, tmp_sub_path, @errorName(e),505 b.cache_root, tmp_sub_path, @errorName(e),
472 });506 });
473 };507 };
...@@ -475,7 +509,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -475,7 +509,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
475 return;509 return;
476 },510 },
477 else => {511 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}", .{
479 b.cache_root, tmp_sub_path,513 b.cache_root, tmp_sub_path,
480 b.cache_root, sub_path,514 b.cache_root, sub_path,
481 @errorName(err),515 @errorName(err),
...@@ -483,7 +517,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -483,7 +517,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
483 },517 },
484 };518 };
485 },519 },
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}", .{
487 b.cache_root, sub_path, @errorName(e),521 b.cache_root, sub_path, @errorName(e),
488 }),522 }),
489 }523 }
...@@ -643,5 +677,5 @@ test Options {...@@ -643,5 +677,5 @@ test Options {
643 \\677 \\
644 , options.contents.items);678 , 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);
647}681}
lib/std/Build/Step/Run.zig+19-26
...@@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
832 else => unreachable,832 else => unreachable,
833 };833 };
834 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {834 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}", .{
836 b.cache_root, output_sub_dir_path, @errorName(err),836 b.cache_root, output_sub_dir_path, @errorName(err),
837 });837 });
838 };838 };
...@@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
864 else => unreachable,864 else => unreachable,
865 };865 };
866 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {866 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}", .{
868 b.cache_root, output_sub_dir_path, @errorName(err),868 b.cache_root, output_sub_dir_path, @errorName(err),
869 });869 });
870 };870 };
...@@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
903 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {903 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {
904 if (err == error.PathAlreadyExists) {904 if (err == error.PathAlreadyExists) {
905 b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| {905 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}", .{
907 b.cache_root,907 b.cache_root,
908 tmp_dir_path,908 tmp_dir_path,
909 @errorName(del_err),909 @errorName(del_err),
910 });910 });
911 };911 };
912 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| {912 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}", .{
914 b.cache_root, tmp_dir_path,914 b.cache_root, tmp_dir_path,
915 b.cache_root, o_sub_path,915 b.cache_root, o_sub_path,
916 @errorName(retry_err),916 @errorName(retry_err),
917 });917 });
918 };918 };
919 } else {919 } 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}", .{
921 b.cache_root, tmp_dir_path,921 b.cache_root, tmp_dir_path,
922 b.cache_root, o_sub_path,922 b.cache_root, o_sub_path,
923 @errorName(err),923 @errorName(err),
...@@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(...@@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(
964 .artifact => |pa| {964 .artifact => |pa| {
965 const artifact = pa.artifact;965 const artifact = pa.artifact;
966 const file_path: []const u8 = p: {966 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.?});
968 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;968 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
969 };969 };
970 try argv_list.append(arena, b.fmt("{s}{s}", .{970 try argv_list.append(arena, b.fmt("{s}{s}", .{
...@@ -1011,24 +1011,17 @@ fn populateGeneratedPaths(...@@ -1011,24 +1011,17 @@ fn populateGeneratedPaths(
1011 }1011 }
1012}1012}
10131013
1014fn formatTerm(1014fn formatTerm(term: ?std.process.Child.Term, w: *std.io.Writer) std.io.Writer.Error!void {
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;
1022 if (term) |t| switch (t) {1015 if (term) |t| switch (t) {
1023 .Exited => |code| try writer.print("exited with code {}", .{code}),1016 .Exited => |code| try w.print("exited with code {d}", .{code}),
1024 .Signal => |sig| try writer.print("terminated with signal {}", .{sig}),1017 .Signal => |sig| try w.print("terminated with signal {d}", .{sig}),
1025 .Stopped => |sig| try writer.print("stopped with signal {}", .{sig}),1018 .Stopped => |sig| try w.print("stopped with signal {d}", .{sig}),
1026 .Unknown => |code| try writer.print("terminated for unknown reason with code {}", .{code}),1019 .Unknown => |code| try w.print("terminated for unknown reason with code {d}", .{code}),
1027 } else {1020 } else {
1028 try writer.writeAll("exited with any code");1021 try w.writeAll("exited with any code");
1029 }1022 }
1030}1023}
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) {
1032 return .{ .data = term };1025 return .{ .data = term };
1033}1026}
10341027
...@@ -1262,12 +1255,12 @@ fn runCommand(...@@ -1262,12 +1255,12 @@ fn runCommand(
1262 const sub_path = b.pathJoin(&output_components);1255 const sub_path = b.pathJoin(&output_components);
1263 const sub_path_dirname = fs.path.dirname(sub_path).?;1256 const sub_path_dirname = fs.path.dirname(sub_path).?;
1264 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {1257 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}", .{
1266 b.cache_root, sub_path_dirname, @errorName(err),1259 b.cache_root, sub_path_dirname, @errorName(err),
1267 });1260 });
1268 };1261 };
1269 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = stream.bytes.? }) catch |err| {1262 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}", .{
1271 b.cache_root, sub_path, @errorName(err),1264 b.cache_root, sub_path, @errorName(err),
1272 });1265 });
1273 };1266 };
...@@ -1346,7 +1339,7 @@ fn runCommand(...@@ -1346,7 +1339,7 @@ fn runCommand(
1346 },1339 },
1347 .expect_term => |expected_term| {1340 .expect_term => |expected_term| {
1348 if (!termMatches(expected_term, result.term)) {1341 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}", .{
1350 fmtTerm(result.term),1343 fmtTerm(result.term),
1351 fmtTerm(expected_term),1344 fmtTerm(expected_term),
1352 try Step.allocPrintCmd(arena, cwd, final_argv),1345 try Step.allocPrintCmd(arena, cwd, final_argv),
...@@ -1366,7 +1359,7 @@ fn runCommand(...@@ -1366,7 +1359,7 @@ fn runCommand(
1366 };1359 };
1367 const expected_term: std.process.Child.Term = .{ .Exited = 0 };1360 const expected_term: std.process.Child.Term = .{ .Exited = 0 };
1368 if (!termMatches(expected_term, result.term)) {1361 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}", .{
1370 prefix,1363 prefix,
1371 fmtTerm(result.term),1364 fmtTerm(result.term),
1372 fmtTerm(expected_term),1365 fmtTerm(expected_term),
...@@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {...@@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
1797 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();1790 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
1798 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();1791 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
1799 } else {1792 } 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);
1801 }1794 }
1802 } else if (child.stderr) |stderr| {1795 } 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);
1804 }1797 }
18051798
1806 if (stderr_bytes) |bytes| if (bytes.len > 0) {1799 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 {...@@ -76,7 +76,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
76 for (usf.output_source_files.items) |output_source_file| {76 for (usf.output_source_files.items) |output_source_file| {
77 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {77 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
78 b.build_root.handle.makePath(dirname) catch |err| {78 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}", .{
80 b.build_root, dirname, @errorName(err),80 b.build_root, dirname, @errorName(err),
81 });81 });
82 };82 };
...@@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
84 switch (output_source_file.contents) {84 switch (output_source_file.contents) {
85 .bytes => |bytes| {85 .bytes => |bytes| {
86 b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {86 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}", .{
88 b.build_root, output_source_file.sub_path, @errorName(err),88 b.build_root, output_source_file.sub_path, @errorName(err),
89 });89 });
90 };90 };
...@@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
101 output_source_file.sub_path,101 output_source_file.sub_path,
102 .{},102 .{},
103 ) catch |err| {103 ) 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}", .{
105 source_path, b.build_root, output_source_file.sub_path, @errorName(err),105 source_path, b.build_root, output_source_file.sub_path, @errorName(err),
106 });106 });
107 };107 };
lib/std/Build/Step/WriteFile.zig+7-7
...@@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
217 const src_dir_path = dir.source.getPath3(b, step);217 const src_dir_path = dir.source.getPath3(b, step);
218218
219 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {219 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}", .{
221 src_dir_path, @errorName(err),221 src_dir_path, @errorName(err),
222 });222 });
223 };223 };
...@@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
258 write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });258 write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });
259259
260 var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| {260 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}", .{
262 b.cache_root, cache_path, @errorName(err),262 b.cache_root, cache_path, @errorName(err),
263 });263 });
264 };264 };
...@@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
269 for (write_file.files.items) |file| {269 for (write_file.files.items) |file| {
270 if (fs.path.dirname(file.sub_path)) |dirname| {270 if (fs.path.dirname(file.sub_path)) |dirname| {
271 cache_dir.makePath(dirname) catch |err| {271 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}", .{
273 b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),273 b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),
274 });274 });
275 };275 };
...@@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
277 switch (file.contents) {277 switch (file.contents) {
278 .bytes => |bytes| {278 .bytes => |bytes| {
279 cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| {279 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}", .{
281 b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),281 b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),
282 });282 });
283 };283 };
...@@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
291 file.sub_path,291 file.sub_path,
292 .{},292 .{},
293 ) catch |err| {293 ) 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}", .{
295 source_path,295 source_path,
296 b.cache_root,296 b.cache_root,
297 cache_path,297 cache_path,
...@@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
315315
316 if (dest_dirname.len != 0) {316 if (dest_dirname.len != 0) {
317 cache_dir.makePath(dest_dirname) catch |err| {317 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}", .{
319 b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),319 b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
320 });320 });
321 };321 };
...@@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
338 dest_path,338 dest_path,
339 .{},339 .{},
340 ) catch |err| {340 ) 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}", .{
342 src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),342 src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),
343 });343 });
344 };344 };
lib/std/Build/Watch.zig+3-3
...@@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {...@@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {
211 .ADD = true,211 .ADD = true,
212 .ONLYDIR = true,212 .ONLYDIR = true,
213 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| {213 }, 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) });
215 };215 };
216 }216 }
217 break :rs &dh_gop.value_ptr.reaction_set;217 break :rs &dh_gop.value_ptr.reaction_set;
...@@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {...@@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {
265 .ONLYDIR = true,265 .ONLYDIR = true,
266 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {266 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {
267 error.FileNotFound => {}, // Expected, harmless.267 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) }),
269 };269 };
270270
271 w.dir_table.swapRemoveAt(i);271 w.dir_table.swapRemoveAt(i);
...@@ -659,7 +659,7 @@ const Os = switch (builtin.os.tag) {...@@ -659,7 +659,7 @@ const Os = switch (builtin.os.tag) {
659 path.root_dir.handle.fd659 path.root_dir.handle.fd
660 else660 else
661 posix.openat(path.root_dir.handle.fd, path.sub_path, dir_open_flags, 0) catch |err| {661 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) });
663 };663 };
664 // Empirically the dir has to stay open or else no events are triggered.664 // Empirically the dir has to stay open or else no events are triggered.
665 errdefer if (!skip_open_dir) posix.close(dir_fd);665 errdefer if (!skip_open_dir) posix.close(dir_fd);
lib/std/Progress.zig+31
...@@ -9,6 +9,7 @@ const Progress = @This();...@@ -9,6 +9,7 @@ const Progress = @This();
9const posix = std.posix;9const posix = std.posix;
10const is_big_endian = builtin.cpu.arch.endian() == .big;10const is_big_endian = builtin.cpu.arch.endian() == .big;
11const is_windows = builtin.os.tag == .windows;11const is_windows = builtin.os.tag == .windows;
12const Writer = std.io.Writer;
1213
13/// `null` if the current node (and its children) should14/// `null` if the current node (and its children) should
14/// not print on update()15/// not print on update()
...@@ -606,6 +607,36 @@ pub fn unlockStdErr() void {...@@ -606,6 +607,36 @@ pub fn unlockStdErr() void {
606 stderr_mutex.unlock();607 stderr_mutex.unlock();
607}608}
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
609fn ipcThreadRun(fd: posix.fd_t) anyerror!void {640fn ipcThreadRun(fd: posix.fd_t) anyerror!void {
610 // Store this data in the thread so that it does not need to be part of the641 // Store this data in the thread so that it does not need to be part of the
611 // linker data of the main executable.642 // 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 {...@@ -122,7 +122,7 @@ fn mode(comptime x: comptime_int) comptime_int {
122}122}
123123
124pub fn main() !void {124pub fn main() !void {
125 const stdout = std.fs.File.stdout().writer();125 const stdout = std.fs.File.stdout().deprecatedWriter();
126126
127 var buffer: [1024]u8 = undefined;127 var buffer: [1024]u8 = undefined;
128 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);128 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 {...@@ -150,17 +150,11 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {
150 };150 };
151}151}
152152
153pub fn format(153pub fn format(self: Version, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
154 self: Version,
155 comptime fmt: []const u8,
156 options: std.fmt.FormatOptions,
157 out_stream: anytype,
158) !void {
159 _ = options;
160 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);154 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 });155 try w.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
162 if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});156 if (self.pre) |pre| try w.print("-{s}", .{pre});
163 if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});157 if (self.build) |build| try w.print("+{s}", .{build});
164}158}
165159
166const expect = std.testing.expect;160const expect = std.testing.expect;
...@@ -202,7 +196,7 @@ test format {...@@ -202,7 +196,7 @@ test format {
202 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",196 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",
203 "5.4.0-1018-raspi",197 "5.4.0-1018-raspi",
204 "5.7.123",198 "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
207 // Invalid version strings should be rejected.201 // Invalid version strings should be rejected.
208 for ([_][]const u8{202 for ([_][]const u8{
...@@ -269,12 +263,12 @@ test format {...@@ -269,12 +263,12 @@ test format {
269 // Valid version string that may overflow.263 // Valid version string that may overflow.
270 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";264 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";
271 if (parse(big_valid)) |ver| {265 if (parse(big_valid)) |ver| {
272 try std.testing.expectFmt(big_valid, "{}", .{ver});266 try std.testing.expectFmt(big_valid, "{f}", .{ver});
273 } else |err| try expect(err == error.Overflow);267 } else |err| try expect(err == error.Overflow);
274268
275 // Invalid version string that may overflow.269 // Invalid version string that may overflow.
276 const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";270 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 |_| {}
278}272}
279273
280test "precedence" {274test "precedence" {
lib/std/Target.zig+11-16
...@@ -301,29 +301,24 @@ pub const Os = struct {...@@ -301,29 +301,24 @@ pub const Os = struct {
301301
302 /// This function is defined to serialize a Zig source code representation of this302 /// This function is defined to serialize a Zig source code representation of this
303 /// type, that, when parsed, will deserialize into the same data.303 /// type, that, when parsed, will deserialize into the same data.
304 pub fn format(304 pub fn format(ver: WindowsVersion, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
305 ver: WindowsVersion,
306 comptime fmt_str: []const u8,
307 _: std.fmt.FormatOptions,
308 writer: anytype,
309 ) @TypeOf(writer).Error!void {
310 const maybe_name = std.enums.tagName(WindowsVersion, ver);305 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")) {
312 if (maybe_name) |name|307 if (maybe_name) |name|
313 try writer.print(".{s}", .{name})308 try w.print(".{s}", .{name})
314 else309 else
315 try writer.print(".{d}", .{@intFromEnum(ver)});310 try w.print(".{d}", .{@intFromEnum(ver)});
316 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {311 } else if (comptime std.mem.eql(u8, f, "c")) {
317 if (maybe_name) |name|312 if (maybe_name) |name|
318 try writer.print(".{s}", .{name})313 try w.print(".{s}", .{name})
319 else314 else
320 try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});315 try w.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
321 } else if (fmt_str.len == 0) {316 } else if (f.len == 0) {
322 if (maybe_name) |name|317 if (maybe_name) |name|
323 try writer.print("WindowsVersion.{s}", .{name})318 try w.print("WindowsVersion.{s}", .{name})
324 else319 else
325 try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});320 try w.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
326 } else std.fmt.invalidFmtError(fmt_str, ver);321 } else std.fmt.invalidFmtError(f, ver);
327 }322 }
328 };323 };
329324
lib/std/Target/Query.zig+20-21
...@@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {...@@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {
394394
395/// Formats a version with the patch component omitted if it is zero,395/// Formats a version with the patch component omitted if it is zero,
396/// unlike SemanticVersion.format which formats all its version components regardless.396/// 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 {
398 if (version.patch == 0) {398 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 });
400 } else {400 } 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 });
402 }402 }
403}403}
404404
405pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {405pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
406 if (self.isNativeTriple())406 if (self.isNativeTriple()) return gpa.dupe(u8, "native");
407 return allocator.dupe(u8, "native");
408407
409 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";408 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
410 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";409 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
411410
412 var result = std.ArrayList(u8).init(allocator);411 var result: std.ArrayListUnmanaged(u8) = .empty;
413 defer result.deinit();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
417 // The zig target syntax does not allow specifying a max os version with no min, so416 // The zig target syntax does not allow specifying a max os version with no min, so
418 // if either are present, we need the min.417 // if either are present, we need the min.
...@@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {...@@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
420 switch (min) {419 switch (min) {
421 .none => {},420 .none => {},
422 .semver => |v| {421 .semver => |v| {
423 try result.writer().writeAll(".");422 try result.appendSlice(gpa, ".");
424 try formatVersion(v, result.writer());423 try formatVersion(v, gpa, &result);
425 },424 },
426 .windows => |v| {425 .windows => |v| {
427 try result.writer().print("{s}", .{v});426 try result.print(gpa, "{d}", .{v});
428 },427 },
429 }428 }
430 }429 }
...@@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {...@@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
432 switch (max) {431 switch (max) {
433 .none => {},432 .none => {},
434 .semver => |v| {433 .semver => |v| {
435 try result.writer().writeAll("...");434 try result.appendSlice(gpa, "...");
436 try formatVersion(v, result.writer());435 try formatVersion(v, gpa, &result);
437 },436 },
438 .windows => |v| {437 .windows => |v| {
439 // This is counting on a custom format() function defined on `WindowsVersion`438 // This is counting on a custom format() function defined on `WindowsVersion`
440 // to add a prefix '.' and make there be a total of three dots.439 // 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});
442 },441 },
443 }442 }
444 }443 }
445444
446 if (self.glibc_version) |v| {445 if (self.glibc_version) |v| {
447 const name = if (self.abi) |abi| @tagName(abi) else "gnu";446 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);
449 result.appendAssumeCapacity('-');448 result.appendAssumeCapacity('-');
450 result.appendSliceAssumeCapacity(name);449 result.appendSliceAssumeCapacity(name);
451 result.appendAssumeCapacity('.');450 result.appendAssumeCapacity('.');
452 try formatVersion(v, result.writer());451 try formatVersion(v, gpa, &result);
453 } else if (self.android_api_level) |lvl| {452 } else if (self.android_api_level) |lvl| {
454 const name = if (self.abi) |abi| @tagName(abi) else "android";453 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);
456 result.appendAssumeCapacity('-');455 result.appendAssumeCapacity('-');
457 result.appendSliceAssumeCapacity(name);456 result.appendSliceAssumeCapacity(name);
458 result.appendAssumeCapacity('.');457 result.appendAssumeCapacity('.');
459 try result.writer().print("{d}", .{lvl});458 try result.print(gpa, "{d}", .{lvl});
460 } else if (self.abi) |abi| {459 } else if (self.abi) |abi| {
461 const name = @tagName(abi);460 const name = @tagName(abi);
462 try result.ensureUnusedCapacity(name.len + 1);461 try result.ensureUnusedCapacity(gpa, name.len + 1);
463 result.appendAssumeCapacity('-');462 result.appendAssumeCapacity('-');
464 result.appendSliceAssumeCapacity(name);463 result.appendSliceAssumeCapacity(name);
465 }464 }
466465
467 return result.toOwnedSlice();466 return result.toOwnedSlice(gpa);
468}467}
469468
470/// Renders the query into a textual representation that can be parsed via the469/// 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 {...@@ -167,7 +167,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
167 const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });167 const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
168 defer file.close();168 defer file.close();
169169
170 try file.writer().writeAll(name);170 try file.deprecatedWriter().writeAll(name);
171 return;171 return;
172 },172 },
173 .windows => {173 .windows => {
...@@ -281,7 +281,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co...@@ -281,7 +281,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
281 const file = try std.fs.cwd().openFile(path, .{});281 const file = try std.fs.cwd().openFile(path, .{});
282 defer file.close();282 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
286 return if (data_len >= 1) buffer[0 .. data_len - 1] else null;286 return if (data_len >= 1) buffer[0 .. data_len - 1] else null;
287 },287 },
...@@ -1163,7 +1163,7 @@ const LinuxThreadImpl = struct {...@@ -1163,7 +1163,7 @@ const LinuxThreadImpl = struct {
11631163
1164 fn getCurrentId() Id {1164 fn getCurrentId() Id {
1165 return tls_thread_id orelse {1165 return tls_thread_id orelse {
1166 const tid = @as(u32, @bitCast(linux.gettid()));1166 const tid: u32 = @bitCast(linux.gettid());
1167 tls_thread_id = tid;1167 tls_thread_id = tid;
1168 return tid;1168 return tid;
1169 };1169 };
lib/std/Uri.zig+40-58
...@@ -34,27 +34,22 @@ pub const Component = union(enum) {...@@ -34,27 +34,22 @@ pub const Component = union(enum) {
34 return switch (component) {34 return switch (component) {
35 .raw => |raw| raw,35 .raw => |raw| raw,
36 .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|36 .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})
38 else38 else
39 percent_encoded,39 percent_encoded,
40 };40 };
41 }41 }
4242
43 pub fn format(43 pub fn format(component: Component, w: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
44 component: Component,
45 comptime fmt_str: []const u8,
46 _: std.fmt.FormatOptions,
47 writer: anytype,
48 ) @TypeOf(writer).Error!void {
49 if (fmt_str.len == 0) {44 if (fmt_str.len == 0) {
50 try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{45 try w.print("std.Uri.Component{{ .{s} = \"{f}\" }}", .{
51 @tagName(component),46 @tagName(component),
52 std.zig.fmtEscapes(switch (component) {47 std.zig.fmtString(switch (component) {
53 .raw, .percent_encoded => |string| string,48 .raw, .percent_encoded => |string| string,
54 }),49 }),
55 });50 });
56 } else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) {51 } 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),
58 .percent_encoded => |percent_encoded| {53 .percent_encoded => |percent_encoded| {
59 var start: usize = 0;54 var start: usize = 0;
60 var index: usize = 0;55 var index: usize = 0;
...@@ -63,51 +58,47 @@ pub const Component = union(enum) {...@@ -63,51 +58,47 @@ pub const Component = union(enum) {
63 if (percent_encoded.len - index < 2) continue;58 if (percent_encoded.len - index < 2) continue;
64 const percent_encoded_char =59 const percent_encoded_char =
65 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;60 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
66 try writer.print("{s}{c}", .{61 try w.print("{s}{c}", .{
67 percent_encoded[start..percent],62 percent_encoded[start..percent],
68 percent_encoded_char,63 percent_encoded_char,
69 });64 });
70 start = percent + 3;65 start = percent + 3;
71 index = percent + 3;66 index = percent + 3;
72 }67 }
73 try writer.writeAll(percent_encoded[start..]);68 try w.writeAll(percent_encoded[start..]);
74 },69 },
75 } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {70 } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {
76 .raw => |raw| try percentEncode(writer, raw, isUnreserved),71 .raw => |raw| try percentEncode(w, raw, isUnreserved),
77 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),72 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
78 } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {73 } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {
79 .raw => |raw| try percentEncode(writer, raw, isUserChar),74 .raw => |raw| try percentEncode(w, raw, isUserChar),
80 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),75 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
81 } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {76 } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {
82 .raw => |raw| try percentEncode(writer, raw, isPasswordChar),77 .raw => |raw| try percentEncode(w, raw, isPasswordChar),
83 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),78 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
84 } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {79 } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {
85 .raw => |raw| try percentEncode(writer, raw, isHostChar),80 .raw => |raw| try percentEncode(w, raw, isHostChar),
86 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),81 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
87 } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {82 } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {
88 .raw => |raw| try percentEncode(writer, raw, isPathChar),83 .raw => |raw| try percentEncode(w, raw, isPathChar),
89 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),84 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
90 } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {85 } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {
91 .raw => |raw| try percentEncode(writer, raw, isQueryChar),86 .raw => |raw| try percentEncode(w, raw, isQueryChar),
92 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),87 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
93 } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {88 } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {
94 .raw => |raw| try percentEncode(writer, raw, isFragmentChar),89 .raw => |raw| try percentEncode(w, raw, isFragmentChar),
95 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),90 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
96 } else @compileError("invalid format string '" ++ fmt_str ++ "'");91 } else @compileError("invalid format string '" ++ fmt_str ++ "'");
97 }92 }
9893
99 pub fn percentEncode(94 pub fn percentEncode(w: *std.io.Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) std.io.Writer.Error!void {
100 writer: anytype,
101 raw: []const u8,
102 comptime isValidChar: fn (u8) bool,
103 ) @TypeOf(writer).Error!void {
104 var start: usize = 0;95 var start: usize = 0;
105 for (raw, 0..) |char, index| {96 for (raw, 0..) |char, index| {
106 if (isValidChar(char)) continue;97 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 });
108 start = index + 1;99 start = index + 1;
109 }100 }
110 try writer.writeAll(raw[start..]);101 try w.writeAll(raw[start..]);
111 }102 }
112};103};
113104
...@@ -247,11 +238,7 @@ pub const WriteToStreamOptions = struct {...@@ -247,11 +238,7 @@ pub const WriteToStreamOptions = struct {
247 port: bool = true,238 port: bool = true,
248};239};
249240
250pub fn writeToStream(241pub fn writeToStream(uri: Uri, writer: *std.io.Writer, options: WriteToStreamOptions) std.io.Writer.Error!void {
251 uri: Uri,
252 options: WriteToStreamOptions,
253 writer: anytype,
254) @TypeOf(writer).Error!void {
255 if (options.scheme) {242 if (options.scheme) {
256 try writer.print("{s}:", .{uri.scheme});243 try writer.print("{s}:", .{uri.scheme});
257 if (options.authority and uri.host != null) {244 if (options.authority and uri.host != null) {
...@@ -261,39 +248,34 @@ pub fn writeToStream(...@@ -261,39 +248,34 @@ pub fn writeToStream(
261 if (options.authority) {248 if (options.authority) {
262 if (options.authentication and uri.host != null) {249 if (options.authentication and uri.host != null) {
263 if (uri.user) |user| {250 if (uri.user) |user| {
264 try writer.print("{user}", .{user});251 try writer.print("{fuser}", .{user});
265 if (uri.password) |password| {252 if (uri.password) |password| {
266 try writer.print(":{password}", .{password});253 try writer.print(":{fpassword}", .{password});
267 }254 }
268 try writer.writeByte('@');255 try writer.writeByte('@');
269 }256 }
270 }257 }
271 if (uri.host) |host| {258 if (uri.host) |host| {
272 try writer.print("{host}", .{host});259 try writer.print("{fhost}", .{host});
273 if (options.port) {260 if (options.port) {
274 if (uri.port) |port| try writer.print(":{d}", .{port});261 if (uri.port) |port| try writer.print(":{d}", .{port});
275 }262 }
276 }263 }
277 }264 }
278 if (options.path) {265 if (options.path) {
279 try writer.print("{path}", .{266 try writer.print("{fpath}", .{
280 if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,267 if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,
281 });268 });
282 if (options.query) {269 if (options.query) {
283 if (uri.query) |query| try writer.print("?{query}", .{query});270 if (uri.query) |query| try writer.print("?{fquery}", .{query});
284 }271 }
285 if (options.fragment) {272 if (options.fragment) {
286 if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment});273 if (uri.fragment) |fragment| try writer.print("#{ffragment}", .{fragment});
287 }274 }
288 }275 }
289}276}
290277
291pub fn format(278pub fn format(uri: Uri, writer: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
292 uri: Uri,
293 comptime fmt_str: []const u8,
294 _: std.fmt.FormatOptions,
295 writer: anytype,
296) @TypeOf(writer).Error!void {
297 const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;279 const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;
298 const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;280 const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;
299 const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;281 const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;
...@@ -301,14 +283,14 @@ pub fn format(...@@ -301,14 +283,14 @@ pub fn format(
301 const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;283 const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;
302 const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0;284 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, .{
305 .scheme = scheme,287 .scheme = scheme,
306 .authentication = authentication,288 .authentication = authentication,
307 .authority = authority,289 .authority = authority,
308 .path = path,290 .path = path,
309 .query = query,291 .query = query,
310 .fragment = fragment,292 .fragment = fragment,
311 }, writer);293 });
312}294}
313295
314/// Parses the URI or returns an error.296/// Parses the URI or returns an error.
...@@ -447,7 +429,7 @@ test remove_dot_segments {...@@ -447,7 +429,7 @@ test remove_dot_segments {
447fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {429fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
448 var aux = std.io.fixedBufferStream(aux_buf.*);430 var aux = std.io.fixedBufferStream(aux_buf.*);
449 if (!base.isEmpty()) {431 if (!base.isEmpty()) {
450 try aux.writer().print("{path}", .{base});432 try aux.writer().print("{fpath}", .{base});
451 aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse433 aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse
452 return remove_dot_segments(new);434 return remove_dot_segments(new);
453 }435 }
...@@ -812,7 +794,7 @@ test "Special test" {...@@ -812,7 +794,7 @@ test "Special test" {
812test "URI percent encoding" {794test "URI percent encoding" {
813 try std.testing.expectFmt(795 try std.testing.expectFmt(
814 "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad",796 "%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%}",
816 .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},798 .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},
817 );799 );
818}800}
...@@ -822,7 +804,7 @@ test "URI percent decoding" {...@@ -822,7 +804,7 @@ test "URI percent decoding" {
822 const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";804 const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
823 var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*;805 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
827 var output: [expected.len]u8 = undefined;809 var output: [expected.len]u8 = undefined;
828 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);810 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
...@@ -834,7 +816,7 @@ test "URI percent decoding" {...@@ -834,7 +816,7 @@ test "URI percent decoding" {
834 const expected = "/abc%";816 const expected = "/abc%";
835 var input = expected.*;817 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
839 var output: [expected.len]u8 = undefined;821 var output: [expected.len]u8 = undefined;
840 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);822 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
...@@ -848,7 +830,7 @@ test "URI query encoding" {...@@ -848,7 +830,7 @@ test "URI query encoding" {
848 const parsed = try Uri.parse(address);830 const parsed = try Uri.parse(address);
849831
850 // format the URI to percent encode it832 // 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});
852}834}
853835
854test "format" {836test "format" {
...@@ -862,7 +844,7 @@ test "format" {...@@ -862,7 +844,7 @@ test "format" {
862 .query = null,844 .query = null,
863 .fragment = null,845 .fragment = null,
864 };846 };
865 try std.testing.expectFmt("file:/foo/bar/baz", "{;/?#}", .{uri});847 try std.testing.expectFmt("file:/foo/bar/baz", "{f;/?#}", .{uri});
866}848}
867849
868test "URI malformed input" {850test "URI malformed input" {
lib/std/ascii.zig+41
...@@ -435,3 +435,44 @@ pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {...@@ -435,3 +435,44 @@ pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {
435pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {435pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {
436 return orderIgnoreCase(lhs, rhs) == .lt;436 return orderIgnoreCase(lhs, rhs) == .lt;
437}437}
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 {...@@ -34,20 +34,14 @@ pub const StackTrace = struct {
34 index: usize,34 index: usize,
35 instruction_addresses: []usize,35 instruction_addresses: []usize,
3636
37 pub fn format(37 pub fn format(self: StackTrace, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
38 self: StackTrace,38 if (fmt.len != 0) unreachable;
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);
4439
45 // TODO: re-evaluate whether to use format() methods at all.40 // TODO: re-evaluate whether to use format() methods at all.
46 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly41 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly
47 // where it tries to call detectTTYConfig here.42 // where it tries to call detectTTYConfig here.
48 if (builtin.os.tag == .freestanding) return;43 if (builtin.os.tag == .freestanding) return;
4944
50 _ = options;
51 const debug_info = std.debug.getSelfDebugInfo() catch |err| {45 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
52 return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});46 return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
53 };47 };
lib/std/crypto/25519/curve25519.zig+2-2
...@@ -124,9 +124,9 @@ test "curve25519" {...@@ -124,9 +124,9 @@ test "curve25519" {
124 const p = try Curve25519.basePoint.clampedMul(s);124 const p = try Curve25519.basePoint.clampedMul(s);
125 try p.rejectIdentity();125 try p.rejectIdentity();
126 var buf: [128]u8 = undefined;126 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");
128 const q = try p.clampedMul(s);128 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
131 try Curve25519.rejectNonCanonical(s);131 try Curve25519.rejectNonCanonical(s);
132 s[31] |= 0x80;132 s[31] |= 0x80;
lib/std/crypto/25519/ed25519.zig+3-3
...@@ -509,8 +509,8 @@ test "key pair creation" {...@@ -509,8 +509,8 @@ test "key pair creation" {
509 _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");509 _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
510 const key_pair = try Ed25519.KeyPair.generateDeterministic(seed);510 const key_pair = try Ed25519.KeyPair.generateDeterministic(seed);
511 var buf: [256]u8 = undefined;511 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");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, "{s}", .{std.fmt.fmtSliceHexUpper(&key_pair.public_key.toBytes())}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");513 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.public_key.toBytes()}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
514}514}
515515
516test "signature" {516test "signature" {
...@@ -520,7 +520,7 @@ test "signature" {...@@ -520,7 +520,7 @@ test "signature" {
520520
521 const sig = try key_pair.sign("test", null);521 const sig = try key_pair.sign("test", null);
522 var buf: [128]u8 = undefined;522 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");
524 try sig.verify("test", key_pair.public_key);524 try sig.verify("test", key_pair.public_key);
525 try std.testing.expectError(error.SignatureVerificationFailed, sig.verify("TEST", key_pair.public_key));525 try std.testing.expectError(error.SignatureVerificationFailed, sig.verify("TEST", key_pair.public_key));
526}526}
lib/std/crypto/25519/edwards25519.zig+1-1
...@@ -546,7 +546,7 @@ test "packing/unpacking" {...@@ -546,7 +546,7 @@ test "packing/unpacking" {
546 var b = Edwards25519.basePoint;546 var b = Edwards25519.basePoint;
547 const pk = try b.mul(s);547 const pk = try b.mul(s);
548 var buf: [128]u8 = undefined;548 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
551 const small_order_ss: [7][32]u8 = .{551 const small_order_ss: [7][32]u8 = .{
552 .{552 .{
lib/std/crypto/25519/ristretto255.zig+4-4
...@@ -175,21 +175,21 @@ pub const Ristretto255 = struct {...@@ -175,21 +175,21 @@ pub const Ristretto255 = struct {
175test "ristretto255" {175test "ristretto255" {
176 const p = Ristretto255.basePoint;176 const p = Ristretto255.basePoint;
177 var buf: [256]u8 = undefined;177 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
180 var r: [Ristretto255.encoded_length]u8 = undefined;180 var r: [Ristretto255.encoded_length]u8 = undefined;
181 _ = try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");181 _ = try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");
182 var q = try Ristretto255.fromBytes(r);182 var q = try Ristretto255.fromBytes(r);
183 q = q.dbl().add(p);183 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
186 const s = [_]u8{15} ++ [_]u8{0} ** 31;186 const s = [_]u8{15} ++ [_]u8{0} ** 31;
187 const w = try p.mul(s);187 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
190 try std.testing.expect(p.dbl().dbl().dbl().dbl().equivalent(w.add(p)));190 try std.testing.expect(p.dbl().dbl().dbl().dbl().equivalent(w.add(p)));
191191
192 const h = [_]u8{69} ** 32 ++ [_]u8{42} ** 32;192 const h = [_]u8{69} ** 32 ++ [_]u8{42} ** 32;
193 const ph = Ristretto255.fromUniform(h);193 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");
195}195}
lib/std/crypto/25519/scalar.zig+3-3
...@@ -850,10 +850,10 @@ test "scalar25519" {...@@ -850,10 +850,10 @@ test "scalar25519" {
850 var y = x.toBytes();850 var y = x.toBytes();
851 try rejectNonCanonical(y);851 try rejectNonCanonical(y);
852 var buf: [128]u8 = undefined;852 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
855 const reduced = reduce(field_order_s);855 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");
857}857}
858858
859test "non-canonical scalar25519" {859test "non-canonical scalar25519" {
...@@ -867,7 +867,7 @@ test "mulAdd overflow check" {...@@ -867,7 +867,7 @@ test "mulAdd overflow check" {
867 const c: [32]u8 = [_]u8{0xff} ** 32;867 const c: [32]u8 = [_]u8{0xff} ** 32;
868 const x = mulAdd(a, b, c);868 const x = mulAdd(a, b, c);
869 var buf: [128]u8 = undefined;869 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");
871}871}
872872
873test "scalar field inversion" {873test "scalar field inversion" {
lib/std/crypto/benchmark.zig+1-1
...@@ -458,7 +458,7 @@ fn mode(comptime x: comptime_int) comptime_int {...@@ -458,7 +458,7 @@ fn mode(comptime x: comptime_int) comptime_int {
458}458}
459459
460pub fn main() !void {460pub fn main() !void {
461 const stdout = std.fs.File.stdout().writer();461 const stdout = std.fs.File.stdout().deprecatedWriter();
462462
463 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);463 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
464 defer arena.deinit();464 defer arena.deinit();
lib/std/crypto/chacha20.zig+2-2
...@@ -1145,7 +1145,7 @@ test "xchacha20" {...@@ -1145,7 +1145,7 @@ test "xchacha20" {
1145 var c: [m.len]u8 = undefined;1145 var c: [m.len]u8 = undefined;
1146 XChaCha20IETF.xor(c[0..], m[0..], 0, key, nonce);1146 XChaCha20IETF.xor(c[0..], m[0..], 0, key, nonce);
1147 var buf: [2 * c.len]u8 = undefined;1147 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");
1149 }1149 }
1150 {1150 {
1151 const ad = "Additional data";1151 const ad = "Additional data";
...@@ -1154,7 +1154,7 @@ test "xchacha20" {...@@ -1154,7 +1154,7 @@ test "xchacha20" {
1154 var out: [m.len]u8 = undefined;1154 var out: [m.len]u8 = undefined;
1155 try XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key);1155 try XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key);
1156 var buf: [2 * c.len]u8 = undefined;1156 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");
1158 try testing.expectEqualSlices(u8, out[0..], m);1158 try testing.expectEqualSlices(u8, out[0..], m);
1159 c[0] +%= 1;1159 c[0] +%= 1;
1160 try testing.expectError(error.AuthenticationFailed, XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key));1160 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" {...@@ -1737,11 +1737,11 @@ test "NIST KAT test" {
1737 var f = sha2.Sha256.init(.{});1737 var f = sha2.Sha256.init(.{});
1738 const fw = f.writer();1738 const fw = f.writer();
1739 var g = NistDRBG.init(seed);1739 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});
1741 for (0..100) |i| {1741 for (0..100) |i| {
1742 g.fill(&seed);1742 g.fill(&seed);
1743 try std.fmt.format(fw, "count = {}\n", .{i});1743 try std.fmt.deprecatedFormat(fw, "count = {}\n", .{i});
1744 try std.fmt.format(fw, "seed = {s}\n", .{std.fmt.fmtSliceHexUpper(&seed)});1744 try std.fmt.deprecatedFormat(fw, "seed = {X}\n", .{&seed});
1745 var g2 = NistDRBG.init(seed);1745 var g2 = NistDRBG.init(seed);
17461746
1747 // This is not equivalent to g2.fill(kseed[:]). As the reference1747 // This is not equivalent to g2.fill(kseed[:]). As the reference
...@@ -1756,16 +1756,16 @@ test "NIST KAT test" {...@@ -1756,16 +1756,16 @@ test "NIST KAT test" {
1756 const e = kp.public_key.encaps(eseed);1756 const e = kp.public_key.encaps(eseed);
1757 const ss2 = try kp.secret_key.decaps(&e.ciphertext);1757 const ss2 = try kp.secret_key.decaps(&e.ciphertext);
1758 try testing.expectEqual(ss2, e.shared_secret);1758 try testing.expectEqual(ss2, e.shared_secret);
1759 try std.fmt.format(fw, "pk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.public_key.toBytes())});1759 try std.fmt.deprecatedFormat(fw, "pk = {X}\n", .{&kp.public_key.toBytes()});
1760 try std.fmt.format(fw, "sk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.secret_key.toBytes())});1760 try std.fmt.deprecatedFormat(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()});
1761 try std.fmt.format(fw, "ct = {s}\n", .{std.fmt.fmtSliceHexUpper(&e.ciphertext)});1761 try std.fmt.deprecatedFormat(fw, "ct = {X}\n", .{&e.ciphertext});
1762 try std.fmt.format(fw, "ss = {s}\n\n", .{std.fmt.fmtSliceHexUpper(&e.shared_secret)});1762 try std.fmt.deprecatedFormat(fw, "ss = {X}\n\n", .{&e.shared_secret});
1763 }1763 }
17641764
1765 var out: [32]u8 = undefined;1765 var out: [32]u8 = undefined;
1766 f.final(&out);1766 f.final(&out);
1767 var outHex: [64]u8 = undefined;1767 var outHex: [64]u8 = undefined;
1768 _ = try std.fmt.bufPrint(&outHex, "{s}", .{std.fmt.fmtSliceHexLower(&out)});1768 _ = try std.fmt.bufPrint(&outHex, "{x}", .{&out});
1769 try testing.expectEqual(outHex, modeHash[1].*);1769 try testing.expectEqual(outHex, modeHash[1].*);
1770 }1770 }
1771}1771}
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...@@ -1512,11 +1512,11 @@ fn logSecrets(key_log_file: std.fs.File, context: anytype, secrets: anytype) voi
1512 const locked = if (key_log_file.lock(.exclusive)) |_| true else |_| false;1512 const locked = if (key_log_file.lock(.exclusive)) |_| true else |_| false;
1513 defer if (locked) key_log_file.unlock();1513 defer if (locked) key_log_file.unlock();
1514 key_log_file.seekFromEnd(0) catch {};1514 key_log_file.seekFromEnd(0) catch {};
1515 inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.writer().print("{s}" ++1515 inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.deprecatedWriter().print("{s}" ++
1516 (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {} {}\n", .{field.name} ++1516 (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++
1517 (if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{1517 (if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{
1518 std.fmt.fmtSliceHexLower(context.client_random),1518 context.client_random,
1519 std.fmt.fmtSliceHexLower(@field(secrets, field.name)),1519 @field(secrets, field.name),
1520 }) catch {};1520 }) catch {};
1521}1521}
15221522
lib/std/debug.zig+182-168
...@@ -12,6 +12,7 @@ const windows = std.os.windows;...@@ -12,6 +12,7 @@ const windows = std.os.windows;
12const native_arch = builtin.cpu.arch;12const native_arch = builtin.cpu.arch;
13const native_os = builtin.os.tag;13const native_os = builtin.os.tag;
14const native_endian = native_arch.endian();14const native_endian = native_arch.endian();
15const Writer = std.io.Writer;
1516
16pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");17pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
17pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");18pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
...@@ -204,13 +205,26 @@ pub fn unlockStdErr() void {...@@ -204,13 +205,26 @@ pub fn unlockStdErr() void {
204 std.Progress.unlockStdErr();205 std.Progress.unlockStdErr();
205}206}
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
207/// Print to stderr, unbuffered, and silently returning on failure. Intended222/// 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.
209pub fn print(comptime fmt: []const u8, args: anytype) void {224pub fn print(comptime fmt: []const u8, args: anytype) void {
210 lockStdErr();225 const bw = lockStderrWriter(&.{});
211 defer unlockStdErr();226 defer unlockStderrWriter();
212 const stderr = fs.File.stderr().writer();227 nosuspend bw.print(fmt, args) catch return;
213 nosuspend stderr.print(fmt, args) catch return;
214}228}
215229
216pub fn getStderrMutex() *std.Thread.Mutex {230pub fn getStderrMutex() *std.Thread.Mutex {
...@@ -232,50 +246,44 @@ pub fn getSelfDebugInfo() !*SelfInfo {...@@ -232,50 +246,44 @@ pub fn getSelfDebugInfo() !*SelfInfo {
232/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.246/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
233/// Obtains the stderr mutex while dumping.247/// Obtains the stderr mutex while dumping.
234pub fn dumpHex(bytes: []const u8) void {248pub fn dumpHex(bytes: []const u8) void {
235 lockStdErr();249 const bw = lockStderrWriter(&.{});
236 defer unlockStdErr();250 defer unlockStderrWriter();
237 dumpHexFallible(bytes) catch {};251 const ttyconf = std.io.tty.detectConfig(.stderr());
238}252 dumpHexFallible(bw, ttyconf, bytes) catch {};
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);
246}253}
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 {
249 var chunks = mem.window(u8, bytes, 16, 16);257 var chunks = mem.window(u8, bytes, 16, 16);
250 while (chunks.next()) |window| {258 while (chunks.next()) |window| {
251 // 1. Print the address.259 // 1. Print the address.
252 const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10;260 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);
254 // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.262 // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.
255 // Also, make sure all lines are aligned by padding the address.263 // Also, make sure all lines are aligned by padding the address.
256 try writer.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });264 try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
257 try ttyconf.setColor(writer, .reset);265 try ttyconf.setColor(bw, .reset);
258266
259 // 2. Print the bytes.267 // 2. Print the bytes.
260 for (window, 0..) |byte, index| {268 for (window, 0..) |byte, index| {
261 try writer.print("{X:0>2} ", .{byte});269 try bw.print("{X:0>2} ", .{byte});
262 if (index == 7) try writer.writeByte(' ');270 if (index == 7) try bw.writeByte(' ');
263 }271 }
264 try writer.writeByte(' ');272 try bw.writeByte(' ');
265 if (window.len < 16) {273 if (window.len < 16) {
266 var missing_columns = (16 - window.len) * 3;274 var missing_columns = (16 - window.len) * 3;
267 if (window.len < 8) missing_columns += 1;275 if (window.len < 8) missing_columns += 1;
268 try writer.writeByteNTimes(' ', missing_columns);276 try bw.splatByteAll(' ', missing_columns);
269 }277 }
270278
271 // 3. Print the characters.279 // 3. Print the characters.
272 for (window) |byte| {280 for (window) |byte| {
273 if (std.ascii.isPrint(byte)) {281 if (std.ascii.isPrint(byte)) {
274 try writer.writeByte(byte);282 try bw.writeByte(byte);
275 } else {283 } else {
276 // Related: https://github.com/ziglang/zig/issues/7600284 // Related: https://github.com/ziglang/zig/issues/7600
277 if (ttyconf == .windows_api) {285 if (ttyconf == .windows_api) {
278 try writer.writeByte('.');286 try bw.writeByte('.');
279 continue;287 continue;
280 }288 }
281289
...@@ -283,22 +291,23 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp...@@ -283,22 +291,23 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp
283 // We don't want to do this for all control codes because most control codes apart from291 // We don't want to do this for all control codes because most control codes apart from
284 // the ones that Zig has escape sequences for are likely not very useful to print as symbols.292 // the ones that Zig has escape sequences for are likely not very useful to print as symbols.
285 switch (byte) {293 switch (byte) {
286 '\n' => try writer.writeAll("␊"),294 '\n' => try bw.writeAll("␊"),
287 '\r' => try writer.writeAll("␍"),295 '\r' => try bw.writeAll("␍"),
288 '\t' => try writer.writeAll("␉"),296 '\t' => try bw.writeAll("␉"),
289 else => try writer.writeByte('.'),297 else => try bw.writeByte('.'),
290 }298 }
291 }299 }
292 }300 }
293 try writer.writeByte('\n');301 try bw.writeByte('\n');
294 }302 }
295}303}
296304
297test dumpHexInternal {305test dumpHexFallible {
298 const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 };306 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);307 var aw: std.io.Writer.Allocating = .init(std.testing.allocator);
300 defer output.deinit();308 defer aw.deinit();
301 try dumpHexInternal(bytes, .no_color, output.writer());309
310 try dumpHexFallible(&aw.interface, .no_color, bytes);
302 const expected = try std.fmt.allocPrint(std.testing.allocator,311 const expected = try std.fmt.allocPrint(std.testing.allocator,
303 \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........312 \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........
304 \\{x:0>[2]} 01 12 13 ...313 \\{x:0>[2]} 01 12 13 ...
...@@ -309,34 +318,36 @@ test dumpHexInternal {...@@ -309,34 +318,36 @@ test dumpHexInternal {
309 @sizeOf(usize) * 2,318 @sizeOf(usize) * 2,
310 });319 });
311 defer std.testing.allocator.free(expected);320 defer std.testing.allocator.free(expected);
312 try std.testing.expectEqualStrings(expected, output.items);321 try std.testing.expectEqualStrings(expected, aw.getWritten());
313}322}
314323
315/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.324/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
316/// TODO multithreaded awareness
317pub fn dumpCurrentStackTrace(start_addr: ?usize) void {325pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
318 nosuspend {326 const stderr = lockStderrWriter(&.{});
319 if (builtin.target.cpu.arch.isWasm()) {327 defer unlockStderrWriter();
320 if (native_os == .wasi) {328 nosuspend dumpCurrentStackTraceToWriter(start_addr, stderr) catch return;
321 const stderr = fs.File.stderr().writer();329}
322 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;330
323 }331/// Prints the current stack trace to the provided writer.
324 return;332pub fn dumpCurrentStackTraceToWriter(start_addr: ?usize, writer: *Writer) !void {
325 }333 if (builtin.target.cpu.arch.isWasm()) {
326 const stderr = fs.File.stderr().writer();334 if (native_os == .wasi) {
327 if (builtin.strip_debug_info) {335 try writer.writeAll("Unable to dump stack trace: not implemented for Wasm\n");
328 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
329 return;
330 }336 }
331 const debug_info = getSelfDebugInfo() catch |err| {337 return;
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 };
339 }338 }
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 };
340}351}
341352
342pub const have_ucontext = posix.ucontext_t != void;353pub const have_ucontext = posix.ucontext_t != void;
...@@ -402,16 +413,14 @@ pub inline fn getContext(context: *ThreadContext) bool {...@@ -402,16 +413,14 @@ pub inline fn getContext(context: *ThreadContext) bool {
402/// Tries to print the stack trace starting from the supplied base pointer to stderr,413/// Tries to print the stack trace starting from the supplied base pointer to stderr,
403/// unbuffered, and ignores any error returned.414/// unbuffered, and ignores any error returned.
404/// TODO multithreaded awareness415/// TODO multithreaded awareness
405pub fn dumpStackTraceFromBase(context: *ThreadContext) void {416pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void {
406 nosuspend {417 nosuspend {
407 if (builtin.target.cpu.arch.isWasm()) {418 if (builtin.target.cpu.arch.isWasm()) {
408 if (native_os == .wasi) {419 if (native_os == .wasi) {
409 const stderr = fs.File.stderr().writer();
410 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;420 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
411 }421 }
412 return;422 return;
413 }423 }
414 const stderr = fs.File.stderr().writer();
415 if (builtin.strip_debug_info) {424 if (builtin.strip_debug_info) {
416 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;425 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
417 return;426 return;
...@@ -420,7 +429,7 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {...@@ -420,7 +429,7 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
420 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;429 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
421 return;430 return;
422 };431 };
423 const tty_config = io.tty.detectConfig(fs.File.stderr());432 const tty_config = io.tty.detectConfig(.stderr());
424 if (native_os == .windows) {433 if (native_os == .windows) {
425 // On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context434 // On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context
426 // provided by the exception handler. On x86, RtlVirtualUnwind doesn't exist. Instead, a new backtrace435 // 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 {...@@ -510,21 +519,23 @@ pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
510 nosuspend {519 nosuspend {
511 if (builtin.target.cpu.arch.isWasm()) {520 if (builtin.target.cpu.arch.isWasm()) {
512 if (native_os == .wasi) {521 if (native_os == .wasi) {
513 const stderr = fs.File.stderr().writer();522 const stderr = lockStderrWriter(&.{});
514 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;523 defer unlockStderrWriter();
524 stderr.writeAll("Unable to dump stack trace: not implemented for Wasm\n") catch return;
515 }525 }
516 return;526 return;
517 }527 }
518 const stderr = fs.File.stderr().writer();528 const stderr = lockStderrWriter(&.{});
529 defer unlockStderrWriter();
519 if (builtin.strip_debug_info) {530 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;
521 return;532 return;
522 }533 }
523 const debug_info = getSelfDebugInfo() catch |err| {534 const debug_info = getSelfDebugInfo() catch |err| {
524 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;535 stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
525 return;536 return;
526 };537 };
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| {
528 stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;539 stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
529 return;540 return;
530 };541 };
...@@ -573,14 +584,13 @@ pub fn panicExtra(...@@ -573,14 +584,13 @@ pub fn panicExtra(
573 const size = 0x1000;584 const size = 0x1000;
574 const trunc_msg = "(msg truncated)";585 const trunc_msg = "(msg truncated)";
575 var buf: [size + trunc_msg.len]u8 = undefined;586 var buf: [size + trunc_msg.len]u8 = undefined;
587 var bw: Writer = .fixed(buf[0..size]);
576 // a minor annoyance with this is that it will result in the NoSpaceLeft588 // a minor annoyance with this is that it will result in the NoSpaceLeft
577 // error being part of the @panic stack trace (but that error should589 // error being part of the @panic stack trace (but that error should
578 // only happen rarely)590 // only happen rarely)
579 const msg = std.fmt.bufPrint(buf[0..size], format, args) catch |err| switch (err) {591 const msg = if (bw.print(format, args)) |_| bw.buffered() else |_| blk: {
580 error.NoSpaceLeft => blk: {592 @memcpy(buf[size..], trunc_msg);
581 @memcpy(buf[size..], trunc_msg);593 break :blk &buf;
582 break :blk &buf;
583 },
584 };594 };
585 std.builtin.panic.call(msg, ret_addr);595 std.builtin.panic.call(msg, ret_addr);
586}596}
...@@ -675,10 +685,9 @@ pub fn defaultPanic(...@@ -675,10 +685,9 @@ pub fn defaultPanic(
675 _ = panicking.fetchAdd(1, .seq_cst);685 _ = panicking.fetchAdd(1, .seq_cst);
676686
677 {687 {
678 lockStdErr();688 const stderr = lockStderrWriter(&.{});
679 defer unlockStdErr();689 defer unlockStderrWriter();
680690
681 const stderr = fs.File.stderr().writer();
682 if (builtin.single_threaded) {691 if (builtin.single_threaded) {
683 stderr.print("panic: ", .{}) catch posix.abort();692 stderr.print("panic: ", .{}) catch posix.abort();
684 } else {693 } else {
...@@ -688,7 +697,7 @@ pub fn defaultPanic(...@@ -688,7 +697,7 @@ pub fn defaultPanic(
688 stderr.print("{s}\n", .{msg}) catch posix.abort();697 stderr.print("{s}\n", .{msg}) catch posix.abort();
689698
690 if (@errorReturnTrace()) |t| dumpStackTrace(t.*);699 if (@errorReturnTrace()) |t| dumpStackTrace(t.*);
691 dumpCurrentStackTrace(first_trace_addr orelse @returnAddress());700 dumpCurrentStackTraceToWriter(first_trace_addr orelse @returnAddress(), stderr) catch {};
692 }701 }
693702
694 waitForOtherThreadToFinishPanicking();703 waitForOtherThreadToFinishPanicking();
...@@ -723,7 +732,7 @@ fn waitForOtherThreadToFinishPanicking() void {...@@ -723,7 +732,7 @@ fn waitForOtherThreadToFinishPanicking() void {
723732
724pub fn writeStackTrace(733pub fn writeStackTrace(
725 stack_trace: std.builtin.StackTrace,734 stack_trace: std.builtin.StackTrace,
726 out_stream: anytype,735 writer: *Writer,
727 debug_info: *SelfInfo,736 debug_info: *SelfInfo,
728 tty_config: io.tty.Config,737 tty_config: io.tty.Config,
729) !void {738) !void {
...@@ -736,15 +745,15 @@ pub fn writeStackTrace(...@@ -736,15 +745,15 @@ pub fn writeStackTrace(
736 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;745 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
737 }) {746 }) {
738 const return_address = stack_trace.instruction_addresses[frame_index];747 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);
740 }749 }
741750
742 if (stack_trace.index > stack_trace.instruction_addresses.len) {751 if (stack_trace.index > stack_trace.instruction_addresses.len) {
743 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;752 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
744753
745 tty_config.setColor(out_stream, .bold) catch {};754 tty_config.setColor(writer, .bold) catch {};
746 try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});755 try writer.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
747 tty_config.setColor(out_stream, .reset) catch {};756 tty_config.setColor(writer, .reset) catch {};
748 }757 }
749}758}
750759
...@@ -954,7 +963,7 @@ pub const StackIterator = struct {...@@ -954,7 +963,7 @@ pub const StackIterator = struct {
954};963};
955964
956pub fn writeCurrentStackTrace(965pub fn writeCurrentStackTrace(
957 out_stream: anytype,966 writer: *Writer,
958 debug_info: *SelfInfo,967 debug_info: *SelfInfo,
959 tty_config: io.tty.Config,968 tty_config: io.tty.Config,
960 start_addr: ?usize,969 start_addr: ?usize,
...@@ -962,7 +971,7 @@ pub fn writeCurrentStackTrace(...@@ -962,7 +971,7 @@ pub fn writeCurrentStackTrace(
962 if (native_os == .windows) {971 if (native_os == .windows) {
963 var context: ThreadContext = undefined;972 var context: ThreadContext = undefined;
964 assert(getContext(&context));973 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);
966 }975 }
967 var context: ThreadContext = undefined;976 var context: ThreadContext = undefined;
968 const has_context = getContext(&context);977 const has_context = getContext(&context);
...@@ -973,7 +982,7 @@ pub fn writeCurrentStackTrace(...@@ -973,7 +982,7 @@ pub fn writeCurrentStackTrace(
973 defer it.deinit();982 defer it.deinit();
974983
975 while (it.next()) |return_address| {984 while (it.next()) |return_address| {
976 printLastUnwindError(&it, debug_info, out_stream, tty_config);985 printLastUnwindError(&it, debug_info, writer, tty_config);
977986
978 // On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,987 // On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,
979 // therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid988 // therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid
...@@ -981,8 +990,8 @@ pub fn writeCurrentStackTrace(...@@ -981,8 +990,8 @@ pub fn writeCurrentStackTrace(
981 // condition on the subsequent iteration and return `null` thus terminating the loop.990 // condition on the subsequent iteration and return `null` thus terminating the loop.
982 // same behaviour for x86-windows-msvc991 // same behaviour for x86-windows-msvc
983 const address = return_address -| 1;992 const address = return_address -| 1;
984 try printSourceAtAddress(debug_info, out_stream, address, tty_config);993 try printSourceAtAddress(debug_info, writer, address, tty_config);
985 } else printLastUnwindError(&it, debug_info, out_stream, tty_config);994 } else printLastUnwindError(&it, debug_info, writer, tty_config);
986}995}
987996
988pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const windows.CONTEXT) usize {997pub 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...@@ -1042,7 +1051,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w
1042}1051}
10431052
1044pub fn writeStackTraceWindows(1053pub fn writeStackTraceWindows(
1045 out_stream: anytype,1054 writer: *Writer,
1046 debug_info: *SelfInfo,1055 debug_info: *SelfInfo,
1047 tty_config: io.tty.Config,1056 tty_config: io.tty.Config,
1048 context: *const windows.CONTEXT,1057 context: *const windows.CONTEXT,
...@@ -1058,14 +1067,14 @@ pub fn writeStackTraceWindows(...@@ -1058,14 +1067,14 @@ pub fn writeStackTraceWindows(
1058 return;1067 return;
1059 } else 0;1068 } else 0;
1060 for (addrs[start_i..]) |addr| {1069 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);
1062 }1071 }
1063}1072}
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 {
1066 const module_name = debug_info.getModuleNameForAddress(address);1075 const module_name = debug_info.getModuleNameForAddress(address);
1067 return printLineInfo(1076 return printLineInfo(
1068 out_stream,1077 writer,
1069 null,1078 null,
1070 address,1079 address,
1071 "???",1080 "???",
...@@ -1075,38 +1084,38 @@ fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize...@@ -1075,38 +1084,38 @@ fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize
1075 );1084 );
1076}1085}
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 {
1079 if (!have_ucontext) return;1088 if (!have_ucontext) return;
1080 if (it.getLastError()) |unwind_error| {1089 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 {};
1082 }1091 }
1083}1092}
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 {
1086 const module_name = debug_info.getModuleNameForAddress(address) orelse "???";1095 const module_name = debug_info.getModuleNameForAddress(address) orelse "???";
1087 try tty_config.setColor(out_stream, .dim);1096 try tty_config.setColor(writer, .dim);
1088 if (err == error.MissingDebugInfo) {1097 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 });
1090 } else {1099 } 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 });
1092 }1101 }
1093 try tty_config.setColor(out_stream, .reset);1102 try tty_config.setColor(writer, .reset);
1094}1103}
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 {
1097 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {1106 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),
1099 else => return err,1108 else => return err,
1100 };1109 };
11011110
1102 const symbol_info = module.getSymbolAtAddress(debug_info.allocator, address) catch |err| switch (err) {1111 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),
1104 else => return err,1113 else => return err,
1105 };1114 };
1106 defer if (symbol_info.source_location) |sl| debug_info.allocator.free(sl.file_name);1115 defer if (symbol_info.source_location) |sl| debug_info.allocator.free(sl.file_name);
11071116
1108 return printLineInfo(1117 return printLineInfo(
1109 out_stream,1118 writer,
1110 symbol_info.source_location,1119 symbol_info.source_location,
1111 address,1120 address,
1112 symbol_info.name,1121 symbol_info.name,
...@@ -1117,7 +1126,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address:...@@ -1117,7 +1126,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address:
1117}1126}
11181127
1119fn printLineInfo(1128fn printLineInfo(
1120 out_stream: anytype,1129 writer: *Writer,
1121 source_location: ?SourceLocation,1130 source_location: ?SourceLocation,
1122 address: usize,1131 address: usize,
1123 symbol_name: []const u8,1132 symbol_name: []const u8,
...@@ -1126,34 +1135,34 @@ fn printLineInfo(...@@ -1126,34 +1135,34 @@ fn printLineInfo(
1126 comptime printLineFromFile: anytype,1135 comptime printLineFromFile: anytype,
1127) !void {1136) !void {
1128 nosuspend {1137 nosuspend {
1129 try tty_config.setColor(out_stream, .bold);1138 try tty_config.setColor(writer, .bold);
11301139
1131 if (source_location) |*sl| {1140 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 });
1133 } else {1142 } else {
1134 try out_stream.writeAll("???:?:?");1143 try writer.writeAll("???:?:?");
1135 }1144 }
11361145
1137 try tty_config.setColor(out_stream, .reset);1146 try tty_config.setColor(writer, .reset);
1138 try out_stream.writeAll(": ");1147 try writer.writeAll(": ");
1139 try tty_config.setColor(out_stream, .dim);1148 try tty_config.setColor(writer, .dim);
1140 try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });1149 try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
1141 try tty_config.setColor(out_stream, .reset);1150 try tty_config.setColor(writer, .reset);
1142 try out_stream.writeAll("\n");1151 try writer.writeAll("\n");
11431152
1144 // Show the matching source code line if possible1153 // Show the matching source code line if possible
1145 if (source_location) |sl| {1154 if (source_location) |sl| {
1146 if (printLineFromFile(out_stream, sl)) {1155 if (printLineFromFile(writer, sl)) {
1147 if (sl.column > 0) {1156 if (sl.column > 0) {
1148 // The caret already takes one char1157 // The caret already takes one char
1149 const space_needed = @as(usize, @intCast(sl.column - 1));1158 const space_needed = @as(usize, @intCast(sl.column - 1));
11501159
1151 try out_stream.writeByteNTimes(' ', space_needed);1160 try writer.splatByteAll(' ', space_needed);
1152 try tty_config.setColor(out_stream, .green);1161 try tty_config.setColor(writer, .green);
1153 try out_stream.writeAll("^");1162 try writer.writeAll("^");
1154 try tty_config.setColor(out_stream, .reset);1163 try tty_config.setColor(writer, .reset);
1155 }1164 }
1156 try out_stream.writeAll("\n");1165 try writer.writeAll("\n");
1157 } else |err| switch (err) {1166 } else |err| switch (err) {
1158 error.EndOfFile, error.FileNotFound => {},1167 error.EndOfFile, error.FileNotFound => {},
1159 error.BadPathName => {},1168 error.BadPathName => {},
...@@ -1164,7 +1173,7 @@ fn printLineInfo(...@@ -1164,7 +1173,7 @@ fn printLineInfo(
1164 }1173 }
1165}1174}
11661175
1167fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) !void {1176fn printLineFromFileAnyOs(writer: *Writer, source_location: SourceLocation) !void {
1168 // Need this to always block even in async I/O mode, because this could potentially1177 // Need this to always block even in async I/O mode, because this could potentially
1169 // be called from e.g. the event loop code crashing.1178 // be called from e.g. the event loop code crashing.
1170 var f = try fs.cwd().openFile(source_location.file_name, .{});1179 var f = try fs.cwd().openFile(source_location.file_name, .{});
...@@ -1197,31 +1206,31 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation)...@@ -1197,31 +1206,31 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation)
1197 if (mem.indexOfScalar(u8, slice, '\n')) |pos| {1206 if (mem.indexOfScalar(u8, slice, '\n')) |pos| {
1198 const line = slice[0 .. pos + 1];1207 const line = slice[0 .. pos + 1];
1199 mem.replaceScalar(u8, line, '\t', ' ');1208 mem.replaceScalar(u8, line, '\t', ' ');
1200 return out_stream.writeAll(line);1209 return writer.writeAll(line);
1201 } else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends.1210 } else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends.
1202 mem.replaceScalar(u8, slice, '\t', ' ');1211 mem.replaceScalar(u8, slice, '\t', ' ');
1203 try out_stream.writeAll(slice);1212 try writer.writeAll(slice);
1204 while (amt_read == buf.len) {1213 while (amt_read == buf.len) {
1205 amt_read = try f.read(buf[0..]);1214 amt_read = try f.read(buf[0..]);
1206 if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| {1215 if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| {
1207 const line = buf[0 .. pos + 1];1216 const line = buf[0 .. pos + 1];
1208 mem.replaceScalar(u8, line, '\t', ' ');1217 mem.replaceScalar(u8, line, '\t', ' ');
1209 return out_stream.writeAll(line);1218 return writer.writeAll(line);
1210 } else {1219 } else {
1211 const line = buf[0..amt_read];1220 const line = buf[0..amt_read];
1212 mem.replaceScalar(u8, line, '\t', ' ');1221 mem.replaceScalar(u8, line, '\t', ' ');
1213 try out_stream.writeAll(line);1222 try writer.writeAll(line);
1214 }1223 }
1215 }1224 }
1216 // Make sure printing last line of file inserts extra newline1225 // Make sure printing last line of file inserts extra newline
1217 try out_stream.writeByte('\n');1226 try writer.writeByte('\n');
1218 }1227 }
1219}1228}
12201229
1221test printLineFromFileAnyOs {1230test printLineFromFileAnyOs {
1222 var output = std.ArrayList(u8).init(std.testing.allocator);1231 var aw: Writer.Allocating = .init(std.testing.allocator);
1223 defer output.deinit();1232 defer aw.deinit();
1224 const output_stream = output.writer();1233 const output_stream = &aw.interface;
12251234
1226 const allocator = std.testing.allocator;1235 const allocator = std.testing.allocator;
1227 const join = std.fs.path.join;1236 const join = std.fs.path.join;
...@@ -1243,8 +1252,8 @@ test printLineFromFileAnyOs {...@@ -1243,8 +1252,8 @@ test printLineFromFileAnyOs {
1243 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));1252 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
12441253
1245 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1254 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);1255 try expectEqualStrings("no new lines in this file, but one is printed anyway\n", aw.getWritten());
1247 output.clearRetainingCapacity();1256 aw.clearRetainingCapacity();
1248 }1257 }
1249 {1258 {
1250 const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" });1259 const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" });
...@@ -1259,12 +1268,12 @@ test printLineFromFileAnyOs {...@@ -1259,12 +1268,12 @@ test printLineFromFileAnyOs {
1259 });1268 });
12601269
1261 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1270 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1262 try expectEqualStrings("1\n", output.items);1271 try expectEqualStrings("1\n", aw.getWritten());
1263 output.clearRetainingCapacity();1272 aw.clearRetainingCapacity();
12641273
1265 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 3, .column = 0 });1274 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 3, .column = 0 });
1266 try expectEqualStrings("3\n", output.items);1275 try expectEqualStrings("3\n", aw.getWritten());
1267 output.clearRetainingCapacity();1276 aw.clearRetainingCapacity();
1268 }1277 }
1269 {1278 {
1270 const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{});1279 const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{});
...@@ -1273,14 +1282,15 @@ test printLineFromFileAnyOs {...@@ -1273,14 +1282,15 @@ test printLineFromFileAnyOs {
1273 defer allocator.free(path);1282 defer allocator.free(path);
12741283
1275 const overlap = 10;1284 const overlap = 10;
1276 var writer = file.writer();1285 var file_writer = file.writer(&.{});
1277 try writer.writeByteNTimes('a', std.heap.page_size_min - overlap);1286 const writer = &file_writer.interface;
1287 try writer.splatByteAll('a', std.heap.page_size_min - overlap);
1278 try writer.writeByte('\n');1288 try writer.writeByte('\n');
1279 try writer.writeByteNTimes('a', overlap);1289 try writer.splatByteAll('a', overlap);
12801290
1281 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });1291 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
1282 try expectEqualStrings(("a" ** overlap) ++ "\n", output.items);1292 try expectEqualStrings(("a" ** overlap) ++ "\n", aw.getWritten());
1283 output.clearRetainingCapacity();1293 aw.clearRetainingCapacity();
1284 }1294 }
1285 {1295 {
1286 const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});1296 const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});
...@@ -1288,12 +1298,13 @@ test printLineFromFileAnyOs {...@@ -1288,12 +1298,13 @@ test printLineFromFileAnyOs {
1288 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });1298 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });
1289 defer allocator.free(path);1299 defer allocator.free(path);
12901300
1291 var writer = file.writer();1301 var file_writer = file.writer(&.{});
1292 try writer.writeByteNTimes('a', std.heap.page_size_max);1302 const writer = &file_writer.interface;
1303 try writer.splatByteAll('a', std.heap.page_size_max);
12931304
1294 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1305 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1295 try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", output.items);1306 try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", aw.getWritten());
1296 output.clearRetainingCapacity();1307 aw.clearRetainingCapacity();
1297 }1308 }
1298 {1309 {
1299 const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});1310 const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});
...@@ -1301,24 +1312,25 @@ test printLineFromFileAnyOs {...@@ -1301,24 +1312,25 @@ test printLineFromFileAnyOs {
1301 const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });1312 const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });
1302 defer allocator.free(path);1313 defer allocator.free(path);
13031314
1304 var writer = file.writer();1315 var file_writer = file.writer(&.{});
1305 try writer.writeByteNTimes('a', 3 * std.heap.page_size_max);1316 const writer = &file_writer.interface;
1317 try writer.splatByteAll('a', 3 * std.heap.page_size_max);
13061318
1307 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));1319 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
13081320
1309 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1321 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1310 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", output.items);1322 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", aw.getWritten());
1311 output.clearRetainingCapacity();1323 aw.clearRetainingCapacity();
13121324
1313 try writer.writeAll("a\na");1325 try writer.writeAll("a\na");
13141326
1315 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1327 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);1328 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", aw.getWritten());
1317 output.clearRetainingCapacity();1329 aw.clearRetainingCapacity();
13181330
1319 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });1331 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
1320 try expectEqualStrings("a\n", output.items);1332 try expectEqualStrings("a\n", aw.getWritten());
1321 output.clearRetainingCapacity();1333 aw.clearRetainingCapacity();
1322 }1334 }
1323 {1335 {
1324 const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});1336 const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});
...@@ -1326,18 +1338,19 @@ test printLineFromFileAnyOs {...@@ -1326,18 +1338,19 @@ test printLineFromFileAnyOs {
1326 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });1338 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });
1327 defer allocator.free(path);1339 defer allocator.free(path);
13281340
1329 var writer = file.writer();1341 var file_writer = file.writer(&.{});
1342 const writer = &file_writer.interface;
1330 const real_file_start = 3 * std.heap.page_size_min;1343 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);
1332 try writer.writeAll("abc\ndef");1345 try writer.writeAll("abc\ndef");
13331346
1334 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });1347 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });
1335 try expectEqualStrings("abc\n", output.items);1348 try expectEqualStrings("abc\n", aw.getWritten());
1336 output.clearRetainingCapacity();1349 aw.clearRetainingCapacity();
13371350
1338 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });1351 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });
1339 try expectEqualStrings("def\n", output.items);1352 try expectEqualStrings("def\n", aw.getWritten());
1340 output.clearRetainingCapacity();1353 aw.clearRetainingCapacity();
1341 }1354 }
1342}1355}
13431356
...@@ -1461,7 +1474,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa...@@ -1461,7 +1474,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
1461}1474}
14621475
1463fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {1476fn 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();
1465 _ = switch (sig) {1479 _ = switch (sig) {
1466 posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL1480 posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
1467 // x86_64 doesn't have a full 64-bit virtual address space.1481 // 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)...@@ -1471,7 +1485,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
1471 // but can also happen when no addressable memory is involved;1485 // but can also happen when no addressable memory is involved;
1472 // for example when reading/writing model-specific registers1486 // for example when reading/writing model-specific registers
1473 // by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).1487 // 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")
1475 else1489 else
1476 stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),1490 stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
1477 posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),1491 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)...@@ -1509,7 +1523,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
1509 }, @ptrCast(ctx)).__mcontext_data;1523 }, @ptrCast(ctx)).__mcontext_data;
1510 }1524 }
1511 relocateContext(&new_ctx);1525 relocateContext(&new_ctx);
1512 dumpStackTraceFromBase(&new_ctx);1526 dumpStackTraceFromBase(&new_ctx, stderr);
1513 },1527 },
1514 else => {},1528 else => {},
1515 }1529 }
...@@ -1539,10 +1553,10 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:...@@ -1539,10 +1553,10 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
1539 _ = panicking.fetchAdd(1, .seq_cst);1553 _ = panicking.fetchAdd(1, .seq_cst);
15401554
1541 {1555 {
1542 lockStdErr();1556 const stderr = lockStderrWriter(&.{});
1543 defer unlockStdErr();1557 defer unlockStderrWriter();
15441558
1545 dumpSegfaultInfoWindows(info, msg, label);1559 dumpSegfaultInfoWindows(info, msg, label, stderr);
1546 }1560 }
15471561
1548 waitForOtherThreadToFinishPanicking();1562 waitForOtherThreadToFinishPanicking();
...@@ -1556,8 +1570,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:...@@ -1556,8 +1570,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
1556 posix.abort();1570 posix.abort();
1557}1571}
15581572
1559fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {1573fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *Writer) void {
1560 const stderr = fs.File.stderr().writer();
1561 _ = switch (msg) {1574 _ = switch (msg) {
1562 0 => stderr.print("{s}\n", .{label.?}),1575 0 => stderr.print("{s}\n", .{label.?}),
1563 1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),1576 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: ?[...@@ -1565,7 +1578,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[
1565 else => unreachable,1578 else => unreachable,
1566 } catch posix.abort();1579 } catch posix.abort();
15671580
1568 dumpStackTraceFromBase(info.ContextRecord);1581 dumpStackTraceFromBase(info.ContextRecord, stderr);
1569}1582}
15701583
1571pub fn dumpStackPointerAddr(prefix: []const u8) void {1584pub fn dumpStackPointerAddr(prefix: []const u8) void {
...@@ -1588,10 +1601,10 @@ test "manage resources correctly" {...@@ -1588,10 +1601,10 @@ test "manage resources correctly" {
1588 // self-hosted debug info is still too buggy1601 // self-hosted debug info is still too buggy
1589 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;1602 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
15901603
1591 const writer = std.io.null_writer;1604 var writer: std.io.Writer = .discarding(&.{});
1592 var di = try SelfInfo.open(testing.allocator);1605 var di = try SelfInfo.open(testing.allocator);
1593 defer di.deinit();1606 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()));
1595}1608}
15961609
1597noinline fn showMyTrace() usize {1610noinline fn showMyTrace() usize {
...@@ -1657,8 +1670,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1657,8 +1670,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1657 pub fn dump(t: @This()) void {1670 pub fn dump(t: @This()) void {
1658 if (!enabled) return;1671 if (!enabled) return;
16591672
1660 const tty_config = io.tty.detectConfig(std.fs.File.stderr());1673 const tty_config = io.tty.detectConfig(.stderr());
1661 const stderr = fs.File.stderr().writer();1674 const stderr = lockStderrWriter(&.{});
1675 defer unlockStderrWriter();
1662 const end = @min(t.index, size);1676 const end = @min(t.index, size);
1663 const debug_info = getSelfDebugInfo() catch |err| {1677 const debug_info = getSelfDebugInfo() catch |err| {
1664 stderr.print(1678 stderr.print(
...@@ -1688,7 +1702,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1688,7 +1702,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1688 t: @This(),1702 t: @This(),
1689 comptime fmt: []const u8,1703 comptime fmt: []const u8,
1690 options: std.fmt.FormatOptions,1704 options: std.fmt.FormatOptions,
1691 writer: anytype,1705 writer: *Writer,
1692 ) !void {1706 ) !void {
1693 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);1707 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
1694 _ = options;1708 _ = options;
lib/std/debug/Dwarf.zig+3-11
...@@ -2302,11 +2302,7 @@ pub const ElfModule = struct {...@@ -2302,11 +2302,7 @@ pub const ElfModule = struct {
2302 };2302 };
2303 defer debuginfod_dir.close();2303 defer debuginfod_dir.close();
23042304
2305 const filename = std.fmt.allocPrint(2305 const filename = std.fmt.allocPrint(gpa, "{x}/debuginfo", .{id}) catch break :blk;
2306 gpa,
2307 "{s}/debuginfo",
2308 .{std.fmt.fmtSliceHexLower(id)},
2309 ) catch break :blk;
2310 defer gpa.free(filename);2306 defer gpa.free(filename);
23112307
2312 const path: Path = .{2308 const path: Path = .{
...@@ -2330,12 +2326,8 @@ pub const ElfModule = struct {...@@ -2330,12 +2326,8 @@ pub const ElfModule = struct {
2330 var id_prefix_buf: [2]u8 = undefined;2326 var id_prefix_buf: [2]u8 = undefined;
2331 var filename_buf: [38 + extension.len]u8 = undefined;2327 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;2329 _ = std.fmt.bufPrint(&id_prefix_buf, "{x}", .{id[0..1]}) catch unreachable;
2334 const filename = std.fmt.bufPrint(2330 const filename = std.fmt.bufPrint(&filename_buf, "{x}" ++ extension, .{id[1..]}) catch break :blk;
2335 &filename_buf,
2336 "{s}" ++ extension,
2337 .{std.fmt.fmtSliceHexLower(id[1..])},
2338 ) catch break :blk;
23392331
2340 for (global_debug_directories) |global_directory| {2332 for (global_debug_directories) |global_directory| {
2341 const path: Path = .{2333 const path: Path = .{
lib/std/debug/Pdb.zig+2-2
...@@ -395,7 +395,7 @@ const Msf = struct {...@@ -395,7 +395,7 @@ const Msf = struct {
395 streams: []MsfStream,395 streams: []MsfStream,
396396
397 fn init(allocator: Allocator, file: File) !Msf {397 fn init(allocator: Allocator, file: File) !Msf {
398 const in = file.reader();398 const in = file.deprecatedReader();
399399
400 const superblock = try in.readStruct(pdb.SuperBlock);400 const superblock = try in.readStruct(pdb.SuperBlock);
401401
...@@ -514,7 +514,7 @@ const MsfStream = struct {...@@ -514,7 +514,7 @@ const MsfStream = struct {
514 var offset = self.pos % self.block_size;514 var offset = self.pos % self.block_size;
515515
516 try self.in_file.seekTo(block * self.block_size + offset);516 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
519 var size: usize = 0;519 var size: usize = 0;
520 var rem_buffer = buffer;520 var rem_buffer = buffer;
lib/std/fmt.zig+204-1445
...@@ -1,17 +1,20 @@...@@ -1,17 +1,20 @@
1//! String formatting and parsing.1//! String formatting and parsing.
22
3const std = @import("std.zig");
4const builtin = @import("builtin");3const builtin = @import("builtin");
54
5const std = @import("std.zig");
6const io = std.io;6const io = std.io;
7const math = std.math;7const math = std.math;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const mem = std.mem;9const mem = std.mem;
10const unicode = std.unicode;
11const meta = std.meta;10const meta = std.meta;
12const lossyCast = math.lossyCast;11const lossyCast = math.lossyCast;
13const expectFmt = std.testing.expectFmt;12const expectFmt = std.testing.expectFmt;
14const testing = std.testing;13const testing = std.testing;
14const Allocator = std.mem.Allocator;
15const Writer = std.io.Writer;
16
17pub const float = @import("fmt/float.zig");
1518
16pub const default_max_depth = 3;19pub const default_max_depth = 3;
1720
...@@ -24,11 +27,14 @@ pub const Alignment = enum {...@@ -24,11 +27,14 @@ pub const Alignment = enum {
24const default_alignment = .right;27const default_alignment = .right;
25const default_fill_char = ' ';28const default_fill_char = ' ';
2629
27pub const FormatOptions = struct {30/// Deprecated in favor of `Options`.
31pub const FormatOptions = Options;
32
33pub const Options = struct {
28 precision: ?usize = null,34 precision: ?usize = null,
29 width: ?usize = null,35 width: ?usize = null,
30 alignment: Alignment = default_alignment,36 alignment: Alignment = default_alignment,
31 fill: u21 = default_fill_char,37 fill: u8 = default_fill_char,
32};38};
3339
34/// Renders fmt string with args, calling `writer` with slices of bytes.40/// Renders fmt string with args, calling `writer` with slices of bytes.
...@@ -45,9 +51,10 @@ pub const FormatOptions = struct {...@@ -45,9 +51,10 @@ pub const FormatOptions = struct {
45/// - when using a field name, you are required to enclose the field name (an identifier) in square51/// - when using a field name, you are required to enclose the field name (an identifier) in square
46/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}52/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}
47/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)53/// - *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 text54/// - *fill* is a single byte which is used to pad the formatted text
49/// - *alignment* is one of the three bytes '<', '^', or '>' to make the text left-, center-, or right-aligned, respectively55/// - *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 codepoints56/// - *width* is the total width of the field in bytes. This is generally only
57/// useful for ASCII text, such as numbers.
51/// - *precision* specifies how many decimals a formatted number should have58/// - *precision* specifies how many decimals a formatted number should have
52///59///
53/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when60/// 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 {...@@ -56,16 +63,20 @@ pub const FormatOptions = struct {
56/// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*.63/// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*.
57///64///
58/// The *specifier* has several options for types:65/// The *specifier* has several options for types:
59/// - `x` and `X`: output numeric value in hexadecimal notation66/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes
60/// - `s`:67/// - `s`:
61/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination68/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
62/// - for slices of u8, print the entire slice as a string without zero-termination69/// - for slices of u8, print the entire slice as a string without zero-termination
70/// - `b64`: output string as standard base64
63/// - `e`: output floating point value in scientific notation71/// - `e`: output floating point value in scientific notation
64/// - `d`: output numeric value in decimal notation72/// - `d`: output numeric value in decimal notation
65/// - `b`: output integer value in binary notation73/// - `b`: output integer value in binary notation
66/// - `o`: output integer value in octal notation74/// - `o`: output integer value in octal notation
67/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.75/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
68/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.76/// - `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)
69/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value.80/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value.
70/// - `!`: 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.81/// - `!`: 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.
71/// - `*`: output the address of the value instead of the value itself.82/// - `*`: output the address of the value instead of the value itself.
...@@ -73,7 +84,7 @@ pub const FormatOptions = struct {...@@ -73,7 +84,7 @@ pub const FormatOptions = struct {
73///84///
74/// If a formatted user type contains a function of the type85/// If a formatted user type contains a function of the type
75/// ```86/// ```
76/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void87/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.Options, writer: anytype) !void
77/// ```88/// ```
78/// with `?` being the type formatted, this function will be called instead of the default implementation.89/// with `?` being the type formatted, this function will be called instead of the default implementation.
79/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.90/// 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 {...@@ -81,11 +92,7 @@ pub const FormatOptions = struct {
81/// A user type may be a `struct`, `vector`, `union` or `enum` type.92/// A user type may be a `struct`, `vector`, `union` or `enum` type.
82///93///
83/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.94/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
84pub fn format(95pub fn format(w: *Writer, comptime fmt: []const u8, args: anytype) Writer.Error!void {
85 writer: anytype,
86 comptime fmt: []const u8,
87 args: anytype,
88) !void {
89 const ArgsType = @TypeOf(args);96 const ArgsType = @TypeOf(args);
90 const args_type_info = @typeInfo(ArgsType);97 const args_type_info = @typeInfo(ArgsType);
91 if (args_type_info != .@"struct") {98 if (args_type_info != .@"struct") {
...@@ -97,7 +104,7 @@ pub fn format(...@@ -97,7 +104,7 @@ pub fn format(
97 @compileError("32 arguments max are supported per format call");104 @compileError("32 arguments max are supported per format call");
98 }105 }
99106
100 @setEvalBranchQuota(2000000);107 @setEvalBranchQuota(fmt.len * 1000);
101 comptime var arg_state: ArgState = .{ .args_len = fields_info.len };108 comptime var arg_state: ArgState = .{ .args_len = fields_info.len };
102 comptime var i = 0;109 comptime var i = 0;
103 comptime var literal: []const u8 = "";110 comptime var literal: []const u8 = "";
...@@ -130,7 +137,7 @@ pub fn format(...@@ -130,7 +137,7 @@ pub fn format(
130137
131 // Write out the literal138 // Write out the literal
132 if (literal.len != 0) {139 if (literal.len != 0) {
133 try writer.writeAll(literal);140 try w.writeAll(literal);
134 literal = "";141 literal = "";
135 }142 }
136143
...@@ -157,7 +164,7 @@ pub fn format(...@@ -157,7 +164,7 @@ pub fn format(
157 comptime assert(fmt[i] == '}');164 comptime assert(fmt[i] == '}');
158 i += 1;165 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].*));
161 const arg_pos = comptime switch (placeholder.arg) {168 const arg_pos = comptime switch (placeholder.arg) {
162 .none => null,169 .none => null,
163 .number => |pos| pos,170 .number => |pos| pos,
...@@ -190,16 +197,15 @@ pub fn format(...@@ -190,16 +197,15 @@ pub fn format(
190 const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse197 const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse
191 @compileError("too few arguments");198 @compileError("too few arguments");
192199
193 try formatType(200 try w.printValue(
194 @field(args, fields_info[arg_to_print].name),
195 placeholder.specifier_arg,201 placeholder.specifier_arg,
196 FormatOptions{202 .{
197 .fill = placeholder.fill,203 .fill = placeholder.fill,
198 .alignment = placeholder.alignment,204 .alignment = placeholder.alignment,
199 .width = width,205 .width = width,
200 .precision = precision,206 .precision = precision,
201 },207 },
202 writer,208 @field(args, fields_info[arg_to_print].name),
203 std.options.fmt_max_depth,209 std.options.fmt_max_depth,
204 );210 );
205 }211 }
...@@ -214,44 +220,41 @@ pub fn format(...@@ -214,44 +220,41 @@ pub fn format(
214 }220 }
215}221}
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
217fn cacheString(str: anytype) []const u8 {231fn cacheString(str: anytype) []const u8 {
218 return &str;232 return &str;
219}233}
220234
221pub const Placeholder = struct {235pub const Placeholder = struct {
222 specifier_arg: []const u8,236 specifier_arg: []const u8,
223 fill: u21,237 fill: u8,
224 alignment: Alignment,238 alignment: Alignment,
225 arg: Specifier,239 arg: Specifier,
226 width: Specifier,240 width: Specifier,
227 precision: Specifier,241 precision: Specifier,
228242
229 pub fn parse(comptime str: anytype) Placeholder {243 pub fn parse(bytes: []const u8) Placeholder {
230 const view = std.unicode.Utf8View.initComptime(&str);244 var parser: Parser = .{ .bytes = bytes, .i = 0 };
231 comptime var parser = Parser{245 const arg = parser.specifier() catch |err| @compileError(@errorName(err));
232 .iter = view.iterator(),246 const specifier_arg = parser.until(':');
233 };247 if (parser.char()) |b| {
234248 if (b != ':') @compileError("expected : or }, found '" ++ &[1]u8{b} ++ "'");
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 }
247 }249 }
248250
249 // Parse the fill character, if present.251 // Parse the fill byte, if present.
250 // When the width field is also specified, the fill character must252 //
253 // When the width field is also specified, the fill byte must
251 // be followed by an alignment specifier, unless it's '0' (zero)254 // be followed by an alignment specifier, unless it's '0' (zero)
252 // (in which case it's handled as part of the width specifier)255 // (in which case it's handled as part of the width specifier).
253 var fill: ?u21 = comptime if (parser.peek(1)) |ch|256 var fill: ?u8 = if (parser.peek(1)) |b|
254 switch (ch) {257 switch (b) {
255 '<', '^', '>' => parser.char(),258 '<', '^', '>' => parser.char(),
256 else => null,259 else => null,
257 }260 }
...@@ -259,8 +262,8 @@ pub const Placeholder = struct {...@@ -259,8 +262,8 @@ pub const Placeholder = struct {
259 null;262 null;
260263
261 // Parse the alignment parameter264 // Parse the alignment parameter
262 const alignment: ?Alignment = comptime if (parser.peek(0)) |ch| init: {265 const alignment: ?Alignment = if (parser.peek(0)) |b| init: {
263 switch (ch) {266 switch (b) {
264 '<', '^', '>' => {267 '<', '^', '>' => {
265 // consume the character268 // consume the character
266 break :init switch (parser.char().?) {269 break :init switch (parser.char().?) {
...@@ -276,29 +279,23 @@ pub const Placeholder = struct {...@@ -276,29 +279,23 @@ pub const Placeholder = struct {
276 // When none of the fill character and the alignment specifier have279 // When none of the fill character and the alignment specifier have
277 // been provided, check whether the width starts with a zero.280 // been provided, check whether the width starts with a zero.
278 if (fill == null and alignment == null) {281 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;
280 }283 }
281284
282 // Parse the width parameter285 // Parse the width parameter
283 const width = comptime parser.specifier() catch |err|286 const width = parser.specifier() catch |err| @compileError(@errorName(err));
284 @compileError(@errorName(err));
285287
286 // Skip the dot, if present288 // Skip the dot, if present
287 if (comptime parser.char()) |ch| {289 if (parser.char()) |b| {
288 if (ch != '.') {290 if (b != '.') @compileError("expected . or }, found '" ++ &[1]u8{b} ++ "'");
289 @compileError("expected . or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
290 }
291 }291 }
292292
293 // Parse the precision parameter293 // Parse the precision parameter
294 const precision = comptime parser.specifier() catch |err|294 const precision = parser.specifier() catch |err| @compileError(@errorName(err));
295 @compileError(@errorName(err));
296295
297 if (comptime parser.char()) |ch| {296 if (parser.char()) |b| @compileError("extraneous trailing character '" ++ &[1]u8{b} ++ "'");
298 @compileError("extraneous trailing character '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
299 }
300297
301 return Placeholder{298 return .{
302 .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),299 .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),
303 .fill = fill orelse default_fill_char,300 .fill = fill orelse default_fill_char,
304 .alignment = alignment orelse default_alignment,301 .alignment = alignment orelse default_alignment,
...@@ -320,88 +317,60 @@ pub const Specifier = union(enum) {...@@ -320,88 +317,60 @@ pub const Specifier = union(enum) {
320/// Allows to implement formatters compatible with std.fmt without replicating317/// Allows to implement formatters compatible with std.fmt without replicating
321/// the standard library behavior.318/// the standard library behavior.
322pub const Parser = struct {319pub 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
327 pub fn number(self: *@This()) ?usize {323 pub fn number(self: *@This()) ?usize {
328 var r: ?usize = null;324 var r: ?usize = null;
329325 while (self.peek(0)) |byte| {
330 while (self.peek(0)) |code_point| {326 switch (byte) {
331 switch (code_point) {
332 '0'...'9' => {327 '0'...'9' => {
333 if (r == null) r = 0;328 if (r == null) r = 0;
334 r.? *= 10;329 r.? *= 10;
335 r.? += code_point - '0';330 r.? += byte - '0';
336 },331 },
337 else => break,332 else => break,
338 }333 }
339 _ = self.iter.nextCodepoint();334 self.i += 1;
340 }335 }
341
342 return r;336 return r;
343 }337 }
344338
345 // Returns a substring of the input starting from the current position339 pub fn until(self: *@This(), delimiter: u8) []const u8 {
346 // and ending where `ch` is found or until the end if not found340 const start = self.i;
347 pub fn until(self: *@This(), ch: u21) []const u8 {341 self.i = std.mem.indexOfScalarPos(u8, self.bytes, self.i, delimiter) orelse self.bytes.len;
348 const start = self.iter.i;342 return self.bytes[start..self.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];
355 }343 }
356344
357 // Returns the character pointed to by the iterator if available, or345 pub fn char(self: *@This()) ?u8 {
358 // null otherwise346 const i = self.i;
359 pub fn char(self: *@This()) ?u21 {347 if (self.bytes.len - i == 0) return null;
360 if (self.iter.nextCodepoint()) |code_point| {348 self.i = i + 1;
361 return code_point;349 return self.bytes[i];
362 }
363 return null;
364 }350 }
365351
366 // Returns true if the iterator points to an existing character and352 pub fn maybe(self: *@This(), byte: u8) bool {
367 // false otherwise353 if (self.peek(0) == byte) {
368 pub fn maybe(self: *@This(), val: u21) bool {354 self.i += 1;
369 if (self.peek(0) == val) {
370 _ = self.iter.nextCodepoint();
371 return true;355 return true;
372 }356 }
373 return false;357 return false;
374 }358 }
375359
376 // Returns a decimal number or null if the current character is not a
377 // digit
378 pub fn specifier(self: *@This()) !Specifier {360 pub fn specifier(self: *@This()) !Specifier {
379 if (self.maybe('[')) {361 if (self.maybe('[')) {
380 const arg_name = self.until(']');362 const arg_name = self.until(']');
381363 if (!self.maybe(']')) return error.@"Expected closing ]";
382 if (!self.maybe(']'))364 return .{ .named = arg_name };
383 return @field(anyerror, "Expected closing ]");
384
385 return Specifier{ .named = arg_name };
386 }365 }
387 if (self.number()) |i|366 if (self.number()) |i| return .{ .number = i };
388 return Specifier{ .number = i };367 return .{ .none = {} };
389
390 return Specifier{ .none = {} };
391 }368 }
392369
393 // Returns the n-th next character or null if that's past the end370 pub fn peek(self: *@This(), i: usize) ?u8 {
394 pub fn peek(self: *@This(), n: usize) ?u21 {371 const peek_index = self.i + i;
395 const original_i = self.iter.i;372 if (peek_index >= self.bytes.len) return null;
396 defer self.iter.i = original_i;373 return self.bytes[peek_index];
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;
405 }374 }
406};375};
407376
...@@ -434,822 +403,14 @@ pub const ArgState = struct {...@@ -434,822 +403,14 @@ pub const ArgState = struct {
434 }403 }
435};404};
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
820pub const Case = enum { lower, upper };406pub const Case = enum { lower, upper };
821407
822fn SliceHex(comptime case: Case) type {408/// Asserts the rendered integer value fits in `buffer`.
823 const charset = "0123456789" ++ if (case == .upper) "ABCDEF" else "abcdef";409/// Returns the end index within `buffer`.
824410pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {
825 return struct {411 var bw: Writer = .fixed(buffer);
826 pub fn format(412 bw.printIntOptions(value, base, case, options) catch unreachable;
827 bytes: []const u8,413 return bw.end;
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;
1253}414}
1254415
1255/// Converts values in the range [0, 100) to a base 10 string.416/// Converts values in the range [0, 100) to a base 10 string.
...@@ -1261,244 +422,22 @@ pub fn digits2(value: u8) [2]u8 {...@@ -1261,244 +422,22 @@ pub fn digits2(value: u8) [2]u8 {
1261 }422 }
1262}423}
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
1472pub const ParseIntError = error{425pub const ParseIntError = error{
1473 /// The result cannot fit in the type specified426 /// The result cannot fit in the type specified.
1474 Overflow,427 Overflow,
1475428 /// The input was empty or contained an invalid character.
1476 /// The input was empty or contained an invalid character
1477 InvalidCharacter,429 InvalidCharacter,
1478};430};
1479431
1480/// Creates a Formatter type from a format function. Wrapping data in Formatter(func) causes432pub fn Formatter(
1481/// the data to be formatted using the given function `func`. `func` must be of the following433 comptime Data: type,
1482/// form:434 comptime formatFn: fn (data: Data, writer: *Writer) Writer.Error!void,
1483///435) type {
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.?;
1493 return struct {436 return struct {
1494 data: Data,437 data: Data,
1495 pub fn format(438 pub fn format(self: @This(), writer: *Writer, comptime fmt: []const u8) Writer.Error!void {
1496 self: @This(),439 comptime assert(fmt.len == 0);
1497 comptime fmt: []const u8,440 try formatFn(self.data, writer);
1498 options: std.fmt.FormatOptions,
1499 writer: anytype,
1500 ) @TypeOf(writer).Error!void {
1501 try formatFn(self.data, fmt, options, writer);
1502 }441 }
1503 };442 };
1504}443}
...@@ -1793,15 +732,13 @@ pub const BufPrintError = error{...@@ -1793,15 +732,13 @@ pub const BufPrintError = error{
1793 NoSpaceLeft,732 NoSpaceLeft,
1794};733};
1795734
1796/// Print a Formatter string into `buf`. Actually just a thin wrapper around `format` and `fixedBufferStream`.735/// Print a Formatter string into `buf`. Returns a slice of the bytes printed.
1797/// Returns a slice of the bytes printed to.
1798pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {736pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {
1799 var fbs = std.io.fixedBufferStream(buf);737 var w: Writer = .fixed(buf);
1800 format(fbs.writer().any(), fmt, args) catch |err| switch (err) {738 w.print(fmt, args) catch |err| switch (err) {
1801 error.NoSpaceLeft => return error.NoSpaceLeft,739 error.WriteFailed => return error.NoSpaceLeft,
1802 else => unreachable,
1803 };740 };
1804 return fbs.getWritten();741 return w.buffered();
1805}742}
1806743
1807pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![:0]u8 {744pub 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...@@ -1809,51 +746,37 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr
1809 return result[0 .. result.len - 1 :0];746 return result[0 .. result.len - 1 :0];
1810}747}
1811748
1812/// Count the characters needed for format. Useful for preallocating memory749/// Count the characters needed for format.
1813pub fn count(comptime fmt: []const u8, args: anytype) u64 {750pub fn count(comptime fmt: []const u8, args: anytype) usize {
1814 var counting_writer = std.io.countingWriter(std.io.null_writer);751 var trash_buffer: [64]u8 = undefined;
1815 format(counting_writer.writer().any(), fmt, args) catch unreachable;752 var w: Writer = .discarding(&trash_buffer);
1816 return counting_writer.bytes_written;753 w.print(fmt, args) catch |err| switch (err) {
1817}754 error.WriteFailed => unreachable,
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
1826 };755 };
756 return w.count;
1827}757}
1828758
1829pub fn allocPrintZ(allocator: mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![:0]u8 {759pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {
1830 const result = try allocPrint(allocator, fmt ++ "\x00", args);760 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
1831 return result[0 .. result.len - 1 :0];761 defer aw.deinit();
1832}762 aw.interface.print(fmt, args) catch |err| switch (err) {
1833763 error.WriteFailed => return error.OutOfMemory,
1834test bufPrintIntToSlice {764 };
1835 var buffer: [100]u8 = undefined;765 return aw.toOwnedSlice();
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 }));
1853}766}
1854767
1855pub fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) []u8 {768pub fn allocPrintSentinel(
1856 return buf[0..formatIntBuf(buf, value, base, case, options)];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);
1857}780}
1858781
1859pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {782pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
...@@ -1984,26 +907,22 @@ test "int.padded" {...@@ -1984,26 +907,22 @@ test "int.padded" {
1984 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});907 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});
1985 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});908 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});
1986 try expectFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});909 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}'", .{'ü'});
1991}910}
1992911
1993test "buffer" {912test "buffer" {
1994 {913 {
1995 var buf1: [32]u8 = undefined;914 var buf1: [32]u8 = undefined;
1996 var fbs = std.io.fixedBufferStream(&buf1);915 var w: Writer = .fixed(&buf1);
1997 try formatType(1234, "", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);916 try w.printValue("", .{}, 1234, std.options.fmt_max_depth);
1998 try std.testing.expectEqualStrings("1234", fbs.getWritten());917 try std.testing.expectEqualStrings("1234", w.buffered());
1999918
2000 fbs.reset();919 w = .fixed(&buf1);
2001 try formatType('a', "c", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);920 try w.printValue("c", .{}, 'a', std.options.fmt_max_depth);
2002 try std.testing.expectEqualStrings("a", fbs.getWritten());921 try std.testing.expectEqualStrings("a", w.buffered());
2003922
2004 fbs.reset();923 w = .fixed(&buf1);
2005 try formatType(0b1100, "b", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);924 try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);
2006 try std.testing.expectEqualStrings("1100", fbs.getWritten());925 try std.testing.expectEqualStrings("1100", w.buffered());
2007 }926 }
2008}927}
2009928
...@@ -2021,7 +940,7 @@ test "array" {...@@ -2021,7 +940,7 @@ test "array" {
2021 const value: [3]u8 = "abc".*;940 const value: [3]u8 = "abc".*;
2022 try expectArrayFmt("array: abc\n", "array: {s}\n", value);941 try expectArrayFmt("array: abc\n", "array: {s}\n", value);
2023 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\n", value);942 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);
2025 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);944 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
2026945
2027 var buf: [100]u8 = undefined;946 var buf: [100]u8 = undefined;
...@@ -2037,7 +956,7 @@ test "array" {...@@ -2037,7 +956,7 @@ test "array" {
2037956
2038 try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value);957 try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value);
2039 try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value);958 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);
2041 }960 }
2042}961}
2043962
...@@ -2046,7 +965,7 @@ test "slice" {...@@ -2046,7 +965,7 @@ test "slice" {
2046 const value: []const u8 = "abc";965 const value: []const u8 = "abc";
2047 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});966 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});
2048 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value});967 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});
2050 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});969 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});
2051 }970 }
2052 {971 {
...@@ -2083,22 +1002,15 @@ test "slice" {...@@ -2083,22 +1002,15 @@ test "slice" {
2083 const S2 = struct {1002 const S2 = struct {
2084 x: u8,1003 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 {
2087 try writer.print("S2({})", .{s.x});1006 try writer.print("S2({})", .{s.x});
2088 }1007 }
2089 };1008 };
2090 const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } };1009 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});
2092 }1011 }
2093}1012}
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
2102test "pointer" {1014test "pointer" {
2103 {1015 {
2104 const value = @as(*align(1) i32, @ptrFromInt(0xdeadbeef));1016 const value = @as(*align(1) i32, @ptrFromInt(0xdeadbeef));
...@@ -2129,21 +1041,6 @@ test "cstr" {...@@ -2129,21 +1041,6 @@ test "cstr" {
2129 );1041 );
2130}1042}
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
2147test "struct" {1044test "struct" {
2148 {1045 {
2149 const Struct = struct {1046 const Struct = struct {
...@@ -2176,7 +1073,7 @@ test "struct" {...@@ -2176,7 +1073,7 @@ test "struct" {
2176 // Tuples1073 // Tuples
2177 try expectFmt("{ }", "{}", .{.{}});1074 try expectFmt("{ }", "{}", .{.{}});
2178 try expectFmt("{ -1 }", "{}", .{.{-1}});1075 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 }});
2180}1077}
21811078
2182test "enum" {1079test "enum" {
...@@ -2216,10 +1113,14 @@ test "non-exhaustive enum" {...@@ -2216,10 +1113,14 @@ test "non-exhaustive enum" {
2216 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One});1113 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One});
2217 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two});1114 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two});
2218 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))});1115 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});1116 try expectFmt("enum: f\n", "enum: {x}\n", .{Enum.One});
2220 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {x}\n", .{Enum.Two});1117 try expectFmt("enum: beef\n", "enum: {x}\n", .{Enum.Two});
2221 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {X}\n", .{Enum.Two});1118 try expectFmt("enum: BEEF\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))});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))});
2223}1124}
22241125
2225test "float.scientific" {1126test "float.scientific" {
...@@ -2351,13 +1252,7 @@ test "custom" {...@@ -2351,13 +1252,7 @@ test "custom" {
2351 x: f32,1252 x: f32,
2352 y: f32,1253 y: f32,
23531254
2354 pub fn format(1255 pub fn format(self: SelfType, writer: *Writer, comptime fmt: []const u8) Writer.Error!void {
2355 self: SelfType,
2356 comptime fmt: []const u8,
2357 options: FormatOptions,
2358 writer: anytype,
2359 ) !void {
2360 _ = options;
2361 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {1256 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
2362 return std.fmt.format(writer, "({d:.3},{d:.3})", .{ self.x, self.y });1257 return std.fmt.format(writer, "({d:.3},{d:.3})", .{ self.x, self.y });
2363 } else if (comptime std.mem.eql(u8, fmt, "d")) {1258 } else if (comptime std.mem.eql(u8, fmt, "d")) {
...@@ -2368,16 +1263,16 @@ test "custom" {...@@ -2368,16 +1263,16 @@ test "custom" {
2368 }1263 }
2369 };1264 };
23701265
2371 var value = Vec2{1266 var value: Vec2 = .{
2372 .x = 10.2,1267 .x = 10.2,
2373 .y = 2.22,1268 .y = 2.22,
2374 };1269 };
2375 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});1270 try expectFmt("point: (10.200,2.220)\n", "point: {f}\n", .{&value});
2376 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});1271 try expectFmt("dim: 10.200x2.220\n", "dim: {fd}\n", .{&value});
23771272
2378 // same thing but not passing a pointer1273 // same thing but not passing a pointer
2379 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});1274 try expectFmt("point: (10.200,2.220)\n", "point: {f}\n", .{value});
2380 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});1275 try expectFmt("dim: 10.200x2.220\n", "dim: {fd}\n", .{value});
2381}1276}
23821277
2383test "union" {1278test "union" {
...@@ -2439,17 +1334,6 @@ test "struct.zero-size" {...@@ -2439,17 +1334,6 @@ test "struct.zero-size" {
2439 try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b});1334 try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b});
2440}1335}
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
2453/// Encodes a sequence of bytes as hexadecimal digits.1337/// Encodes a sequence of bytes as hexadecimal digits.
2454/// Returns an array containing the encoded bytes.1338/// Returns an array containing the encoded bytes.
2455pub fn bytesToHex(input: anytype, case: Case) [input.len * 2]u8 {1339pub fn bytesToHex(input: anytype, case: Case) [input.len * 2]u8 {
...@@ -2494,110 +1378,14 @@ test bytesToHex {...@@ -2494,110 +1378,14 @@ test bytesToHex {
24941378
2495test hexToBytes {1379test hexToBytes {
2496 var buf: [32]u8 = undefined;1380 var buf: [32]u8 = undefined;
2497 try expectFmt("90" ** 32, "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "90" ** 32))});1381 try expectFmt("90" ** 32, "{X}", .{try hexToBytes(&buf, "90" ** 32)});
2498 try expectFmt("ABCD", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "ABCD"))});1382 try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")});
2499 try expectFmt("", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, ""))});1383 try expectFmt("", "{X}", .{try hexToBytes(&buf, "")});
2500 try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));1384 try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));
2501 try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));1385 try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));
2502 try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));1386 try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));
2503}1387}
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
2601test "positional" {1389test "positional" {
2602 try expectFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });1390 try expectFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
2603 try expectFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });1391 try expectFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
...@@ -2664,23 +1452,11 @@ test "padding" {...@@ -2664,23 +1452,11 @@ test "padding" {
2664 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});1452 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});
2665 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});1453 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});
2666 try expectFmt("-", "{s:-^1}", .{""});1454 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"});
2670 try expectFmt("====a", "{c:=>5}", .{'a'});1455 try expectFmt("====a", "{c:=>5}", .{'a'});
2671 try expectFmt("==a==", "{c:=^5}", .{'a'});1456 try expectFmt("==a==", "{c:=^5}", .{'a'});
2672 try expectFmt("a====", "{c:=<5}", .{'a'});1457 try expectFmt("a====", "{c:=<5}", .{'a'});
2673}1458}
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
2684test "decimal float padding" {1460test "decimal float padding" {
2685 const number: f32 = 3.1415;1461 const number: f32 = 3.1415;
2686 try expectFmt("left-pad: **3.142\n", "left-pad: {d:*>7.3}\n", .{number});1462 try expectFmt("left-pad: **3.142\n", "left-pad: {d:*>7.3}\n", .{number});
...@@ -2742,16 +1518,16 @@ test "recursive format function" {...@@ -2742,16 +1518,16 @@ test "recursive format function" {
2742 Leaf: i32,1518 Leaf: i32,
2743 Branch: struct { left: *const R, right: *const R },1519 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 {
2746 return switch (self) {1522 return switch (self) {
2747 .Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}),1523 .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 }),
2749 };1525 };
2750 }1526 }
2751 };1527 };
27521528
2753 var r = R{ .Leaf = 1 };1529 var r: R = .{ .Leaf = 1 };
2754 try expectFmt("Leaf(1)\n", "{}\n", .{&r});1530 try expectFmt("Leaf(1)\n", "{f}\n", .{&r});
2755}1531}
27561532
2757pub const hex_charset = "0123456789abcdef";1533pub const hex_charset = "0123456789abcdef";
...@@ -2785,54 +1561,39 @@ test hex {...@@ -2785,54 +1561,39 @@ test hex {
27851561
2786test "parser until" {1562test "parser until" {
2787 { // return substring till ':'1563 { // return substring till ':'
2788 var parser: Parser = .{1564 var parser: Parser = .{ .bytes = "abc:1234", .i = 0 };
2789 .iter = .{ .bytes = "abc:1234", .i = 0 },
2790 };
2791 try testing.expectEqualStrings("abc", parser.until(':'));1565 try testing.expectEqualStrings("abc", parser.until(':'));
2792 }1566 }
27931567
2794 { // return the entire string - `ch` not found1568 { // return the entire string - `ch` not found
2795 var parser: Parser = .{1569 var parser: Parser = .{ .bytes = "abc1234", .i = 0 };
2796 .iter = .{ .bytes = "abc1234", .i = 0 },
2797 };
2798 try testing.expectEqualStrings("abc1234", parser.until(':'));1570 try testing.expectEqualStrings("abc1234", parser.until(':'));
2799 }1571 }
28001572
2801 { // substring is empty - `ch` is the only character1573 { // substring is empty - `ch` is the only character
2802 var parser: Parser = .{1574 var parser: Parser = .{ .bytes = ":", .i = 0 };
2803 .iter = .{ .bytes = ":", .i = 0 },
2804 };
2805 try testing.expectEqualStrings("", parser.until(':'));1575 try testing.expectEqualStrings("", parser.until(':'));
2806 }1576 }
28071577
2808 { // empty string and `ch` not found1578 { // empty string and `ch` not found
2809 var parser: Parser = .{1579 var parser: Parser = .{ .bytes = "", .i = 0 };
2810 .iter = .{ .bytes = "", .i = 0 },
2811 };
2812 try testing.expectEqualStrings("", parser.until(':'));1580 try testing.expectEqualStrings("", parser.until(':'));
2813 }1581 }
28141582
2815 { // substring starts at index 2 and goes upto `ch`1583 { // substring starts at index 2 and goes upto `ch`
2816 var parser: Parser = .{1584 var parser: Parser = .{ .bytes = "abc:1234", .i = 2 };
2817 .iter = .{ .bytes = "abc:1234", .i = 2 },
2818 };
2819 try testing.expectEqualStrings("c", parser.until(':'));1585 try testing.expectEqualStrings("c", parser.until(':'));
2820 }1586 }
28211587
2822 { // substring starts at index 4 and goes upto the end - `ch` not found1588 { // substring starts at index 4 and goes upto the end - `ch` not found
2823 var parser: Parser = .{1589 var parser: Parser = .{ .bytes = "abc1234", .i = 4 };
2824 .iter = .{ .bytes = "abc1234", .i = 4 },
2825 };
2826 try testing.expectEqualStrings("234", parser.until(':'));1590 try testing.expectEqualStrings("234", parser.until(':'));
2827 }1591 }
2828}1592}
28291593
2830test "parser peek" {1594test "parser peek" {
2831 { // start iteration from the first index1595 { // start iteration from the first index
2832 var parser: Parser = .{1596 var parser: Parser = .{ .bytes = "hello world", .i = 0 };
2833 .iter = .{ .bytes = "hello world", .i = 0 },
2834 };
2835
2836 try testing.expectEqual('h', parser.peek(0));1597 try testing.expectEqual('h', parser.peek(0));
2837 try testing.expectEqual('e', parser.peek(1));1598 try testing.expectEqual('e', parser.peek(1));
2838 try testing.expectEqual(' ', parser.peek(5));1599 try testing.expectEqual(' ', parser.peek(5));
...@@ -2841,9 +1602,7 @@ test "parser peek" {...@@ -2841,9 +1602,7 @@ test "parser peek" {
2841 }1602 }
28421603
2843 { // start iteration from the second last index1604 { // start iteration from the second last index
2844 var parser: Parser = .{1605 var parser: Parser = .{ .bytes = "hello world!", .i = 10 };
2845 .iter = .{ .bytes = "hello world!", .i = 10 },
2846 };
28471606
2848 try testing.expectEqual('d', parser.peek(0));1607 try testing.expectEqual('d', parser.peek(0));
2849 try testing.expectEqual('!', parser.peek(1));1608 try testing.expectEqual('!', parser.peek(1));
...@@ -2851,18 +1610,14 @@ test "parser peek" {...@@ -2851,18 +1610,14 @@ test "parser peek" {
2851 }1610 }
28521611
2853 { // start iteration beyond the length of the string1612 { // start iteration beyond the length of the string
2854 var parser: Parser = .{1613 var parser: Parser = .{ .bytes = "hello", .i = 5 };
2855 .iter = .{ .bytes = "hello", .i = 5 },
2856 };
28571614
2858 try testing.expectEqual(null, parser.peek(0));1615 try testing.expectEqual(null, parser.peek(0));
2859 try testing.expectEqual(null, parser.peek(1));1616 try testing.expectEqual(null, parser.peek(1));
2860 }1617 }
28611618
2862 { // empty string1619 { // empty string
2863 var parser: Parser = .{1620 var parser: Parser = .{ .bytes = "", .i = 0 };
2864 .iter = .{ .bytes = "", .i = 0 },
2865 };
28661621
2867 try testing.expectEqual(null, parser.peek(0));1622 try testing.expectEqual(null, parser.peek(0));
2868 try testing.expectEqual(null, parser.peek(2));1623 try testing.expectEqual(null, parser.peek(2));
...@@ -2871,78 +1626,78 @@ test "parser peek" {...@@ -2871,78 +1626,78 @@ test "parser peek" {
28711626
2872test "parser char" {1627test "parser char" {
2873 // character exists - iterator at 01628 // character exists - iterator at 0
2874 var parser: Parser = .{ .iter = .{ .bytes = "~~hello", .i = 0 } };1629 var parser: Parser = .{ .bytes = "~~hello", .i = 0 };
2875 try testing.expectEqual('~', parser.char());1630 try testing.expectEqual('~', parser.char());
28761631
2877 // character exists - iterator in the middle1632 // character exists - iterator in the middle
2878 parser = .{ .iter = .{ .bytes = "~~hello", .i = 3 } };1633 parser = .{ .bytes = "~~hello", .i = 3 };
2879 try testing.expectEqual('e', parser.char());1634 try testing.expectEqual('e', parser.char());
28801635
2881 // character exists - iterator at the end1636 // character exists - iterator at the end
2882 parser = .{ .iter = .{ .bytes = "~~hello", .i = 6 } };1637 parser = .{ .bytes = "~~hello", .i = 6 };
2883 try testing.expectEqual('o', parser.char());1638 try testing.expectEqual('o', parser.char());
28841639
2885 // character doesn't exist - iterator beyond the length of the string1640 // character doesn't exist - iterator beyond the length of the string
2886 parser = .{ .iter = .{ .bytes = "~~hello", .i = 7 } };1641 parser = .{ .bytes = "~~hello", .i = 7 };
2887 try testing.expectEqual(null, parser.char());1642 try testing.expectEqual(null, parser.char());
2888}1643}
28891644
2890test "parser maybe" {1645test "parser maybe" {
2891 // character exists - iterator at 01646 // character exists - iterator at 0
2892 var parser: Parser = .{ .iter = .{ .bytes = "hello world", .i = 0 } };1647 var parser: Parser = .{ .bytes = "hello world", .i = 0 };
2893 try testing.expect(parser.maybe('h'));1648 try testing.expect(parser.maybe('h'));
28941649
2895 // character exists - iterator at space1650 // character exists - iterator at space
2896 parser = .{ .iter = .{ .bytes = "hello world", .i = 5 } };1651 parser = .{ .bytes = "hello world", .i = 5 };
2897 try testing.expect(parser.maybe(' '));1652 try testing.expect(parser.maybe(' '));
28981653
2899 // character exists - iterator at the end1654 // character exists - iterator at the end
2900 parser = .{ .iter = .{ .bytes = "hello world", .i = 10 } };1655 parser = .{ .bytes = "hello world", .i = 10 };
2901 try testing.expect(parser.maybe('d'));1656 try testing.expect(parser.maybe('d'));
29021657
2903 // character doesn't exist - iterator beyond the length of the string1658 // 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 };
2905 try testing.expect(!parser.maybe('e'));1660 try testing.expect(!parser.maybe('e'));
2906}1661}
29071662
2908test "parser number" {1663test "parser number" {
2909 // input is a single digit natural number - iterator at 01664 // 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 };
2911 try testing.expect(7 == parser.number());1666 try testing.expect(7 == parser.number());
29121667
2913 // input is a two digit natural number - iterator at 11668 // input is a two digit natural number - iterator at 1
2914 parser = .{ .iter = .{ .bytes = "29", .i = 1 } };1669 parser = .{ .bytes = "29", .i = 1 };
2915 try testing.expect(9 == parser.number());1670 try testing.expect(9 == parser.number());
29161671
2917 // input is a two digit natural number - iterator beyond the length of the string1672 // 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 };
2919 try testing.expectEqual(null, parser.number());1674 try testing.expectEqual(null, parser.number());
29201675
2921 // input is an integer1676 // input is an integer
2922 parser = .{ .iter = .{ .bytes = "0", .i = 0 } };1677 parser = .{ .bytes = "0", .i = 0 };
2923 try testing.expect(0 == parser.number());1678 try testing.expect(0 == parser.number());
29241679
2925 // input is a negative integer1680 // input is a negative integer
2926 parser = .{ .iter = .{ .bytes = "-2", .i = 0 } };1681 parser = .{ .bytes = "-2", .i = 0 };
2927 try testing.expectEqual(null, parser.number());1682 try testing.expectEqual(null, parser.number());
29281683
2929 // input is a string1684 // input is a string
2930 parser = .{ .iter = .{ .bytes = "no_number", .i = 2 } };1685 parser = .{ .bytes = "no_number", .i = 2 };
2931 try testing.expectEqual(null, parser.number());1686 try testing.expectEqual(null, parser.number());
29321687
2933 // input is a single character string1688 // input is a single character string
2934 parser = .{ .iter = .{ .bytes = "n", .i = 0 } };1689 parser = .{ .bytes = "n", .i = 0 };
2935 try testing.expectEqual(null, parser.number());1690 try testing.expectEqual(null, parser.number());
29361691
2937 // input is an empty string1692 // input is an empty string
2938 parser = .{ .iter = .{ .bytes = "", .i = 0 } };1693 parser = .{ .bytes = "", .i = 0 };
2939 try testing.expectEqual(null, parser.number());1694 try testing.expectEqual(null, parser.number());
2940}1695}
29411696
2942test "parser specifier" {1697test "parser specifier" {
2943 { // input string is a digit; iterator at 01698 { // input string is a digit; iterator at 0
2944 const expected: Specifier = Specifier{ .number = 1 };1699 const expected: Specifier = Specifier{ .number = 1 };
2945 var parser: Parser = .{ .iter = .{ .bytes = "1", .i = 0 } };1700 var parser: Parser = .{ .bytes = "1", .i = 0 };
29461701
2947 const result = try parser.specifier();1702 const result = try parser.specifier();
2948 try testing.expect(expected.number == result.number);1703 try testing.expect(expected.number == result.number);
...@@ -2950,7 +1705,7 @@ test "parser specifier" {...@@ -2950,7 +1705,7 @@ test "parser specifier" {
29501705
2951 { // input string is a two digit number; iterator at 01706 { // input string is a two digit number; iterator at 0
2952 const digit: Specifier = Specifier{ .number = 42 };1707 const digit: Specifier = Specifier{ .number = 42 };
2953 var parser: Parser = .{ .iter = .{ .bytes = "42", .i = 0 } };1708 var parser: Parser = .{ .bytes = "42", .i = 0 };
29541709
2955 const result = try parser.specifier();1710 const result = try parser.specifier();
2956 try testing.expect(digit.number == result.number);1711 try testing.expect(digit.number == result.number);
...@@ -2958,7 +1713,7 @@ test "parser specifier" {...@@ -2958,7 +1713,7 @@ test "parser specifier" {
29581713
2959 { // input string is a two digit number digit; iterator at 11714 { // input string is a two digit number digit; iterator at 1
2960 const digit: Specifier = Specifier{ .number = 8 };1715 const digit: Specifier = Specifier{ .number = 8 };
2961 var parser: Parser = .{ .iter = .{ .bytes = "28", .i = 1 } };1716 var parser: Parser = .{ .bytes = "28", .i = 1 };
29621717
2963 const result = try parser.specifier();1718 const result = try parser.specifier();
2964 try testing.expect(digit.number == result.number);1719 try testing.expect(digit.number == result.number);
...@@ -2966,7 +1721,7 @@ test "parser specifier" {...@@ -2966,7 +1721,7 @@ test "parser specifier" {
29661721
2967 { // input string is a two digit number with square brackets; iterator at 01722 { // input string is a two digit number with square brackets; iterator at 0
2968 const digit: Specifier = Specifier{ .named = "15" };1723 const digit: Specifier = Specifier{ .named = "15" };
2969 var parser: Parser = .{ .iter = .{ .bytes = "[15]", .i = 0 } };1724 var parser: Parser = .{ .bytes = "[15]", .i = 0 };
29701725
2971 const result = try parser.specifier();1726 const result = try parser.specifier();
2972 try testing.expectEqualStrings(digit.named, result.named);1727 try testing.expectEqualStrings(digit.named, result.named);
...@@ -2974,21 +1729,21 @@ test "parser specifier" {...@@ -2974,21 +1729,21 @@ test "parser specifier" {
29741729
2975 { // input string is not a number and contains square brackets; iterator at 01730 { // input string is not a number and contains square brackets; iterator at 0
2976 const digit: Specifier = Specifier{ .named = "hello" };1731 const digit: Specifier = Specifier{ .named = "hello" };
2977 var parser: Parser = .{ .iter = .{ .bytes = "[hello]", .i = 0 } };1732 var parser: Parser = .{ .bytes = "[hello]", .i = 0 };
29781733
2979 const result = try parser.specifier();1734 const result = try parser.specifier();
2980 try testing.expectEqualStrings(digit.named, result.named);1735 try testing.expectEqualStrings(digit.named, result.named);
2981 }1736 }
29821737
2983 { // input string is not a number and doesn't contain closing square bracket; iterator at 01738 { // 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
2986 const result = parser.specifier();1741 const result = parser.specifier();
2987 try testing.expectError(@field(anyerror, "Expected closing ]"), result);1742 try testing.expectError(@field(anyerror, "Expected closing ]"), result);
2988 }1743 }
29891744
2990 { // input string is not a number and doesn't contain closing square bracket; iterator at 21745 { // 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
2993 const result = parser.specifier();1748 const result = parser.specifier();
2994 try testing.expectError(@field(anyerror, "Expected closing ]"), result);1749 try testing.expectError(@field(anyerror, "Expected closing ]"), result);
...@@ -2996,7 +1751,7 @@ test "parser specifier" {...@@ -2996,7 +1751,7 @@ test "parser specifier" {
29961751
2997 { // input string is not a number and contains unbalanced square brackets; iterator at 01752 { // input string is not a number and contains unbalanced square brackets; iterator at 0
2998 const digit: Specifier = Specifier{ .named = "[[hello" };1753 const digit: Specifier = Specifier{ .named = "[[hello" };
2999 var parser: Parser = .{ .iter = .{ .bytes = "[[[hello]", .i = 0 } };1754 var parser: Parser = .{ .bytes = "[[[hello]", .i = 0 };
30001755
3001 const result = try parser.specifier();1756 const result = try parser.specifier();
3002 try testing.expectEqualStrings(digit.named, result.named);1757 try testing.expectEqualStrings(digit.named, result.named);
...@@ -3004,7 +1759,7 @@ test "parser specifier" {...@@ -3004,7 +1759,7 @@ test "parser specifier" {
30041759
3005 { // input string is not a number and contains unbalanced square brackets; iterator at 11760 { // input string is not a number and contains unbalanced square brackets; iterator at 1
3006 const digit: Specifier = Specifier{ .named = "[[hello" };1761 const digit: Specifier = Specifier{ .named = "[[hello" };
3007 var parser: Parser = .{ .iter = .{ .bytes = "[[[[hello]]]]]", .i = 1 } };1762 var parser: Parser = .{ .bytes = "[[[[hello]]]]]", .i = 1 };
30081763
3009 const result = try parser.specifier();1764 const result = try parser.specifier();
3010 try testing.expectEqualStrings(digit.named, result.named);1765 try testing.expectEqualStrings(digit.named, result.named);
...@@ -3012,9 +1767,13 @@ test "parser specifier" {...@@ -3012,9 +1767,13 @@ test "parser specifier" {
30121767
3013 { // input string is neither a digit nor a named argument1768 { // input string is neither a digit nor a named argument
3014 const char: Specifier = Specifier{ .none = {} };1769 const char: Specifier = Specifier{ .none = {} };
3015 var parser: Parser = .{ .iter = .{ .bytes = "hello", .i = 0 } };1770 var parser: Parser = .{ .bytes = "hello", .i = 0 };
30161771
3017 const result = try parser.specifier();1772 const result = try parser.specifier();
3018 try testing.expectEqual(char.none, result.none);1773 try testing.expectEqual(char.none, result.none);
3019 }1774 }
3020}1775}
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 @@...@@ -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
1/// The OS-specific file descriptor or file handle.18/// The OS-specific file descriptor or file handle.
2handle: Handle,19handle: Handle,
320
...@@ -168,6 +185,18 @@ pub const CreateFlags = struct {...@@ -168,6 +185,18 @@ pub const CreateFlags = struct {
168 mode: Mode = default_mode,185 mode: Mode = default_mode,
169};186};
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
171/// Upon success, the stream is in an uninitialized state. To continue using it,200/// Upon success, the stream is in an uninitialized state. To continue using it,
172/// you must use the open() function.201/// you must use the open() function.
173pub fn close(self: File) void {202pub fn close(self: File) void {
...@@ -351,8 +380,10 @@ pub fn getPos(self: File) GetSeekPosError!u64 {...@@ -351,8 +380,10 @@ pub fn getPos(self: File) GetSeekPosError!u64 {
351 return posix.lseek_CUR_get(self.handle);380 return posix.lseek_CUR_get(self.handle);
352}381}
353382
383pub const GetEndPosError = std.os.windows.GetFileSizeError || StatError;
384
354/// TODO: integrate with async I/O385/// TODO: integrate with async I/O
355pub fn getEndPos(self: File) GetSeekPosError!u64 {386pub fn getEndPos(self: File) GetEndPosError!u64 {
356 if (builtin.os.tag == .windows) {387 if (builtin.os.tag == .windows) {
357 return windows.GetFileSizeEx(self.handle);388 return windows.GetFileSizeEx(self.handle);
358 }389 }
...@@ -477,7 +508,6 @@ pub const Stat = struct {...@@ -477,7 +508,6 @@ pub const Stat = struct {
477pub const StatError = posix.FStatError;508pub const StatError = posix.FStatError;
478509
479/// Returns `Stat` containing basic information about the `File`.510/// Returns `Stat` containing basic information about the `File`.
480/// Use `metadata` to retrieve more detailed information (e.g. creation time, permissions).
481/// TODO: integrate with async I/O511/// TODO: integrate with async I/O
482pub fn stat(self: File) StatError!Stat {512pub fn stat(self: File) StatError!Stat {
483 if (builtin.os.tag == .windows) {513 if (builtin.os.tag == .windows) {
...@@ -743,361 +773,6 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError!...@@ -743,361 +773,6 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError!
743 }773 }
744}774}
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
1101pub const UpdateTimesError = posix.FutimensError || windows.SetFileTimeError;776pub const UpdateTimesError = posix.FutimensError || windows.SetFileTimeError;
1102777
1103/// The underlying file system may have a different granularity than nanoseconds,778/// The underlying file system may have a different granularity than nanoseconds,
...@@ -1130,19 +805,12 @@ pub fn updateTimes(...@@ -1130,19 +805,12 @@ pub fn updateTimes(
1130 try posix.futimens(self.handle, &times);805 try posix.futimens(self.handle, &times);
1131}806}
1132807
1133/// Reads all the bytes from the current position to the end of the file.808/// Deprecated in favor of `Reader`.
1134/// On success, caller owns returned buffer.
1135/// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
1136pub fn readToEndAlloc(self: File, allocator: Allocator, max_bytes: usize) ![]u8 {809pub fn readToEndAlloc(self: File, allocator: Allocator, max_bytes: usize) ![]u8 {
1137 return self.readToEndAllocOptions(allocator, max_bytes, null, .of(u8), null);810 return self.readToEndAllocOptions(allocator, max_bytes, null, .of(u8), null);
1138}811}
1139812
1140/// Reads all the bytes from the current position to the end of the file.813/// Deprecated in favor of `Reader`.
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.
1146pub fn readToEndAllocOptions(814pub fn readToEndAllocOptions(
1147 self: File,815 self: File,
1148 allocator: Allocator,816 allocator: Allocator,
...@@ -1161,7 +829,7 @@ pub fn readToEndAllocOptions(...@@ -1161,7 +829,7 @@ pub fn readToEndAllocOptions(
1161 var array_list = try std.ArrayListAligned(u8, alignment).initCapacity(allocator, initial_cap);829 var array_list = try std.ArrayListAligned(u8, alignment).initCapacity(allocator, initial_cap);
1162 defer array_list.deinit();830 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) {
1165 error.StreamTooLong => return error.FileTooBig,833 error.StreamTooLong => return error.FileTooBig,
1166 else => |e| return e,834 else => |e| return e,
1167 };835 };
...@@ -1184,8 +852,7 @@ pub fn read(self: File, buffer: []u8) ReadError!usize {...@@ -1184,8 +852,7 @@ pub fn read(self: File, buffer: []u8) ReadError!usize {
1184 return posix.read(self.handle, buffer);852 return posix.read(self.handle, buffer);
1185}853}
1186854
1187/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it855/// Deprecated in favor of `Reader`.
1188/// means the file reached the end. Reaching the end of a file is not an error condition.
1189pub fn readAll(self: File, buffer: []u8) ReadError!usize {856pub fn readAll(self: File, buffer: []u8) ReadError!usize {
1190 var index: usize = 0;857 var index: usize = 0;
1191 while (index != buffer.len) {858 while (index != buffer.len) {
...@@ -1206,10 +873,7 @@ pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {...@@ -1206,10 +873,7 @@ pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
1206 return posix.pread(self.handle, buffer, offset);873 return posix.pread(self.handle, buffer, offset);
1207}874}
1208875
1209/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it876/// Deprecated in favor of `Reader`.
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
1213pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {877pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
1214 var index: usize = 0;878 var index: usize = 0;
1215 while (index != buffer.len) {879 while (index != buffer.len) {
...@@ -1223,8 +887,7 @@ pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {...@@ -1223,8 +887,7 @@ pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
1223/// See https://github.com/ziglang/zig/issues/7699887/// See https://github.com/ziglang/zig/issues/7699
1224pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {888pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
1225 if (is_windows) {889 if (is_windows) {
1226 // TODO improve this to use ReadFileScatter890 if (iovecs.len == 0) return 0;
1227 if (iovecs.len == 0) return @as(usize, 0);
1228 const first = iovecs[0];891 const first = iovecs[0];
1229 return windows.ReadFile(self.handle, first.base[0..first.len], null);892 return windows.ReadFile(self.handle, first.base[0..first.len], null);
1230 }893 }
...@@ -1232,19 +895,7 @@ pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {...@@ -1232,19 +895,7 @@ pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
1232 return posix.readv(self.handle, iovecs);895 return posix.readv(self.handle, iovecs);
1233}896}
1234897
1235/// Returns the number of bytes read. If the number read is smaller than the total bytes898/// Deprecated in favor of `Reader`.
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
1248pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {899pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {
1249 if (iovecs.len == 0) return 0;900 if (iovecs.len == 0) return 0;
1250901
...@@ -1279,8 +930,7 @@ pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {...@@ -1279,8 +930,7 @@ pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {
1279/// https://github.com/ziglang/zig/issues/12783930/// https://github.com/ziglang/zig/issues/12783
1280pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!usize {931pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!usize {
1281 if (is_windows) {932 if (is_windows) {
1282 // TODO improve this to use ReadFileScatter933 if (iovecs.len == 0) return 0;
1283 if (iovecs.len == 0) return @as(usize, 0);
1284 const first = iovecs[0];934 const first = iovecs[0];
1285 return windows.ReadFile(self.handle, first.base[0..first.len], offset);935 return windows.ReadFile(self.handle, first.base[0..first.len], offset);
1286 }936 }
...@@ -1288,14 +938,7 @@ pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!u...@@ -1288,14 +938,7 @@ pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!u
1288 return posix.preadv(self.handle, iovecs, offset);938 return posix.preadv(self.handle, iovecs, offset);
1289}939}
1290940
1291/// Returns the number of bytes read. If the number read is smaller than the total bytes941/// Deprecated in favor of `Reader`.
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
1299pub fn preadvAll(self: File, iovecs: []posix.iovec, offset: u64) PReadError!usize {942pub fn preadvAll(self: File, iovecs: []posix.iovec, offset: u64) PReadError!usize {
1300 if (iovecs.len == 0) return 0;943 if (iovecs.len == 0) return 0;
1301944
...@@ -1328,6 +971,7 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize {...@@ -1328,6 +971,7 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize {
1328 return posix.write(self.handle, bytes);971 return posix.write(self.handle, bytes);
1329}972}
1330973
974/// Deprecated in favor of `Writer`.
1331pub fn writeAll(self: File, bytes: []const u8) WriteError!void {975pub fn writeAll(self: File, bytes: []const u8) WriteError!void {
1332 var index: usize = 0;976 var index: usize = 0;
1333 while (index < bytes.len) {977 while (index < bytes.len) {
...@@ -1345,8 +989,7 @@ pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {...@@ -1345,8 +989,7 @@ pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
1345 return posix.pwrite(self.handle, bytes, offset);989 return posix.pwrite(self.handle, bytes, offset);
1346}990}
1347991
1348/// On Windows, this function currently does alter the file pointer.992/// Deprecated in favor of `Writer`.
1349/// https://github.com/ziglang/zig/issues/12783
1350pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {993pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {
1351 var index: usize = 0;994 var index: usize = 0;
1352 while (index < bytes.len) {995 while (index < bytes.len) {
...@@ -1355,11 +998,10 @@ pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {...@@ -1355,11 +998,10 @@ pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {
1355}998}
1356999
1357/// See https://github.com/ziglang/zig/issues/76991000/// See https://github.com/ziglang/zig/issues/7699
1358/// See equivalent function: `std.net.Stream.writev`.
1359pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {1001pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
1360 if (is_windows) {1002 if (is_windows) {
1361 // TODO improve this to use WriteFileScatter1003 // TODO improve this to use WriteFileScatter
1362 if (iovecs.len == 0) return @as(usize, 0);1004 if (iovecs.len == 0) return 0;
1363 const first = iovecs[0];1005 const first = iovecs[0];
1364 return windows.WriteFile(self.handle, first.base[0..first.len], null);1006 return windows.WriteFile(self.handle, first.base[0..first.len], null);
1365 }1007 }
...@@ -1367,15 +1009,7 @@ pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {...@@ -1367,15 +1009,7 @@ pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
1367 return posix.writev(self.handle, iovecs);1009 return posix.writev(self.handle, iovecs);
1368}1010}
13691011
1370/// The `iovecs` parameter is mutable because:1012/// Deprecated in favor of `Writer`.
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`.
1379pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {1013pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {
1380 if (iovecs.len == 0) return;1014 if (iovecs.len == 0) return;
13811015
...@@ -1405,8 +1039,7 @@ pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {...@@ -1405,8 +1039,7 @@ pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {
1405/// https://github.com/ziglang/zig/issues/127831039/// https://github.com/ziglang/zig/issues/12783
1406pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!usize {1040pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!usize {
1407 if (is_windows) {1041 if (is_windows) {
1408 // TODO improve this to use WriteFileScatter1042 if (iovecs.len == 0) return 0;
1409 if (iovecs.len == 0) return @as(usize, 0);
1410 const first = iovecs[0];1043 const first = iovecs[0];
1411 return windows.WriteFile(self.handle, first.base[0..first.len], offset);1044 return windows.WriteFile(self.handle, first.base[0..first.len], offset);
1412 }1045 }
...@@ -1414,14 +1047,9 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError...@@ -1414,14 +1047,9 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError
1414 return posix.pwritev(self.handle, iovecs, offset);1047 return posix.pwritev(self.handle, iovecs, offset);
1415}1048}
14161049
1417/// The `iovecs` parameter is mutable because this function needs to mutate the fields in1050/// Deprecated in favor of `Writer`.
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
1422pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!void {1051pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!void {
1423 if (iovecs.len == 0) return;1052 if (iovecs.len == 0) return;
1424
1425 var i: usize = 0;1053 var i: usize = 0;
1426 var off: u64 = 0;1054 var off: u64 = 0;
1427 while (true) {1055 while (true) {
...@@ -1439,14 +1067,14 @@ pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteEr...@@ -1439,14 +1067,14 @@ pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteEr
14391067
1440pub const CopyRangeError = posix.CopyFileRangeError;1068pub const CopyRangeError = posix.CopyFileRangeError;
14411069
1070/// Deprecated in favor of `Writer`.
1442pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {1071pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
1443 const adjusted_len = math.cast(usize, len) orelse maxInt(usize);1072 const adjusted_len = math.cast(usize, len) orelse maxInt(usize);
1444 const result = try posix.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0);1073 const result = try posix.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0);
1445 return result;1074 return result;
1446}1075}
14471076
1448/// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it1077/// Deprecated in favor of `Writer`.
1449/// means the in file reached the end. Reaching the end of a file is not an error condition.
1450pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {1078pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
1451 var total_bytes_copied: u64 = 0;1079 var total_bytes_copied: u64 = 0;
1452 var in_off = in_offset;1080 var in_off = in_offset;
...@@ -1461,24 +1089,18 @@ pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u...@@ -1461,24 +1089,18 @@ pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u
1461 return total_bytes_copied;1089 return total_bytes_copied;
1462}1090}
14631091
1092/// Deprecated in favor of `Writer`.
1464pub const WriteFileOptions = struct {1093pub const WriteFileOptions = struct {
1465 in_offset: u64 = 0,1094 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.
1472 in_len: ?u64 = null,1095 in_len: ?u64 = null,
1473
1474 headers_and_trailers: []posix.iovec_const = &[0]posix.iovec_const{},1096 headers_and_trailers: []posix.iovec_const = &[0]posix.iovec_const{},
1475
1476 /// The trailer count is inferred from `headers_and_trailers.len - header_count`
1477 header_count: usize = 0,1097 header_count: usize = 0,
1478};1098};
14791099
1100/// Deprecated in favor of `Writer`.
1480pub const WriteFileError = ReadError || error{EndOfStream} || WriteError;1101pub const WriteFileError = ReadError || error{EndOfStream} || WriteError;
14811102
1103/// Deprecated in favor of `Writer`.
1482pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {1104pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
1483 return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {1105 return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {
1484 error.Unseekable,1106 error.Unseekable,
...@@ -1488,35 +1110,27 @@ pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFile...@@ -1488,35 +1110,27 @@ pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFile
1488 error.NetworkUnreachable,1110 error.NetworkUnreachable,
1489 error.NetworkSubsystemFailed,1111 error.NetworkSubsystemFailed,
1490 => return self.writeFileAllUnseekable(in_file, args),1112 => return self.writeFileAllUnseekable(in_file, args),
1491
1492 else => |e| return e,1113 else => |e| return e,
1493 };1114 };
1494}1115}
14951116
1496/// Does not try seeking in either of the File parameters.1117/// Deprecated in favor of `Writer`.
1497/// See `writeFileAll` as an alternative to calling this.
1498pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {1118pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
1499 const headers = args.headers_and_trailers[0..args.header_count];1119 const headers = args.headers_and_trailers[0..args.header_count];
1500 const trailers = args.headers_and_trailers[args.header_count..];1120 const trailers = args.headers_and_trailers[args.header_count..];
1501
1502 try self.writevAll(headers);1121 try self.writevAll(headers);
15031122 try in_file.deprecatedReader().skipBytes(args.in_offset, .{ .buf_size = 4096 });
1504 try in_file.reader().skipBytes(args.in_offset, .{ .buf_size = 4096 });
1505
1506 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();1123 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
1507 if (args.in_len) |len| {1124 if (args.in_len) |len| {
1508 var stream = std.io.limitedReader(in_file.reader(), len);1125 var stream = std.io.limitedReader(in_file.deprecatedReader(), len);
1509 try fifo.pump(stream.reader(), self.writer());1126 try fifo.pump(stream.reader(), self.deprecatedWriter());
1510 } else {1127 } else {
1511 try fifo.pump(in_file.reader(), self.writer());1128 try fifo.pump(in_file.deprecatedReader(), self.deprecatedWriter());
1512 }1129 }
1513
1514 try self.writevAll(trailers);1130 try self.writevAll(trailers);
1515}1131}
15161132
1517/// Low level function which can fail for OS-specific reasons.1133/// Deprecated in favor of `Writer`.
1518/// See `writeFileAll` as an alternative to calling this.
1519/// TODO integrate with async I/O
1520fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix.SendFileError!void {1134fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix.SendFileError!void {
1521 const count = blk: {1135 const count = blk: {
1522 if (args.in_len) |l| {1136 if (args.in_len) |l| {
...@@ -1581,18 +1195,23 @@ fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix...@@ -1581,18 +1195,23 @@ fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix
1581 }1195 }
1582}1196}
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 {
1587 return .{ .context = file };1203 return .{ .context = file };
1588}1204}
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 {
1593 return .{ .context = file };1211 return .{ .context = file };
1594}1212}
15951213
1214/// Deprecated in favor of `Reader` and `Writer`.
1596pub const SeekableStream = io.SeekableStream(1215pub const SeekableStream = io.SeekableStream(
1597 File,1216 File,
1598 SeekError,1217 SeekError,
...@@ -1603,10 +1222,715 @@ pub const SeekableStream = io.SeekableStream(...@@ -1603,10 +1222,715 @@ pub const SeekableStream = io.SeekableStream(
1603 getEndPos,1222 getEndPos,
1604);1223);
16051224
1225/// Deprecated in favor of `Reader` and `Writer`.
1606pub fn seekableStream(file: File) SeekableStream {1226pub fn seekableStream(file: File) SeekableStream {
1607 return .{ .context = file };1227 return .{ .context = file };
1608}1228}
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
1610const range_off: windows.LARGE_INTEGER = 0;1934const range_off: windows.LARGE_INTEGER = 0;
1611const range_len: windows.LARGE_INTEGER = 1;1935const range_len: windows.LARGE_INTEGER = 1;
16121936
...@@ -1769,18 +2093,3 @@ pub fn downgradeLock(file: File) LockError!void {...@@ -1769,18 +2093,3 @@ pub fn downgradeLock(file: File) LockError!void {
1769 };2093 };
1770 }2094 }
1771}2095}
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 {...@@ -146,14 +146,11 @@ pub fn joinZ(allocator: Allocator, paths: []const []const u8) ![:0]u8 {
146 return out[0 .. out.len - 1 :0];146 return out[0 .. out.len - 1 :0];
147}147}
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) {
150 return .{ .data = paths };150 return .{ .data = paths };
151}151}
152152
153fn formatJoin(paths: []const []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void {153fn formatJoin(paths: []const []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
154 _ = fmt;
155 _ = options;
156
157 const first_path_idx = for (paths, 0..) |p, idx| {154 const first_path_idx = for (paths, 0..) |p, idx| {
158 if (p.len != 0) break idx;155 if (p.len != 0) break idx;
159 } else return;156 } else return;
lib/std/fs/test.zig+2-109
...@@ -1798,11 +1798,11 @@ test "walker" {...@@ -1798,11 +1798,11 @@ test "walker" {
1798 var num_walked: usize = 0;1798 var num_walked: usize = 0;
1799 while (try walker.next()) |entry| {1799 while (try walker.next()) |entry| {
1800 testing.expect(expected_basenames.has(entry.basename)) catch |err| {1800 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)});
1802 return err;1802 return err;
1803 };1803 };
1804 testing.expect(expected_paths.has(entry.path)) catch |err| {1804 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)});
1806 return err;1806 return err;
1807 };1807 };
1808 // make sure that the entry.dir is the containing dir1808 // make sure that the entry.dir is the containing dir
...@@ -1953,113 +1953,6 @@ test "chown" {...@@ -1953,113 +1953,6 @@ test "chown" {
1953 try dir.chown(null, null);1953 try dir.chown(null, null);
1954}1954}
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
2063test "delete a setAsCwd directory on Windows" {1956test "delete a setAsCwd directory on Windows" {
2064 if (native_os != .windows) return error.SkipZigTest;1957 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 {...@@ -346,7 +346,7 @@ fn mode(comptime x: comptime_int) comptime_int {
346}346}
347347
348pub fn main() !void {348pub fn main() !void {
349 const stdout = std.fs.File.stdout().writer();349 const stdout = std.fs.File.stdout().deprecatedWriter();
350350
351 var buffer: [1024]u8 = undefined;351 var buffer: [1024]u8 = undefined;
352 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);352 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 {...@@ -436,7 +436,7 @@ pub fn DebugAllocator(comptime config: Config) type {
436 const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);436 const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);
437 const page_addr = @intFromPtr(bucket) & ~(page_size - 1);437 const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
438 const addr = page_addr + slot_index * size_class;438 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 });
440 leaks = true;440 leaks = true;
441 }441 }
442 }442 }
...@@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type {
463 while (it.next()) |large_alloc| {463 while (it.next()) |large_alloc| {
464 if (config.retain_metadata and large_alloc.freed) continue;464 if (config.retain_metadata and large_alloc.freed) continue;
465 const stack_trace = large_alloc.getStackTrace(.alloc);465 const stack_trace = large_alloc.getStackTrace(.alloc);
466 log.err("memory address 0x{x} leaked: {}", .{466 log.err("memory address 0x{x} leaked: {f}", .{
467 @intFromPtr(large_alloc.bytes.ptr), stack_trace,467 @intFromPtr(large_alloc.bytes.ptr), stack_trace,
468 });468 });
469 leaks = true;469 leaks = true;
...@@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type {
522 .index = 0,522 .index = 0,
523 };523 };
524 std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);524 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}", .{
526 alloc_stack_trace, free_stack_trace, second_free_stack_trace,526 alloc_stack_trace, free_stack_trace, second_free_stack_trace,
527 });527 });
528 }528 }
...@@ -568,7 +568,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -568,7 +568,7 @@ pub fn DebugAllocator(comptime config: Config) type {
568 .index = 0,568 .index = 0,
569 };569 };
570 std.debug.captureStackTrace(ret_addr, &free_stack_trace);570 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}", .{
572 entry.value_ptr.bytes.len,572 entry.value_ptr.bytes.len,
573 old_mem.len,573 old_mem.len,
574 entry.value_ptr.getStackTrace(.alloc),574 entry.value_ptr.getStackTrace(.alloc),
...@@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type {
678 .index = 0,678 .index = 0,
679 };679 };
680 std.debug.captureStackTrace(ret_addr, &free_stack_trace);680 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}", .{
682 entry.value_ptr.bytes.len,682 entry.value_ptr.bytes.len,
683 old_mem.len,683 old_mem.len,
684 entry.value_ptr.getStackTrace(.alloc),684 entry.value_ptr.getStackTrace(.alloc),
...@@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type {
907 };907 };
908 std.debug.captureStackTrace(return_address, &free_stack_trace);908 std.debug.captureStackTrace(return_address, &free_stack_trace);
909 if (old_memory.len != requested_size) {909 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}", .{
911 requested_size,911 requested_size,
912 old_memory.len,912 old_memory.len,
913 bucketStackTrace(bucket, slot_count, slot_index, .alloc),913 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type {
915 });915 });
916 }916 }
917 if (alignment != slot_alignment) {917 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}", .{
919 slot_alignment.toByteUnits(),919 slot_alignment.toByteUnits(),
920 alignment.toByteUnits(),920 alignment.toByteUnits(),
921 bucketStackTrace(bucket, slot_count, slot_index, .alloc),921 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type {
1006 };1006 };
1007 std.debug.captureStackTrace(return_address, &free_stack_trace);1007 std.debug.captureStackTrace(return_address, &free_stack_trace);
1008 if (memory.len != requested_size) {1008 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}", .{
1010 requested_size,1010 requested_size,
1011 memory.len,1011 memory.len,
1012 bucketStackTrace(bucket, slot_count, slot_index, .alloc),1012 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type {
1014 });1014 });
1015 }1015 }
1016 if (alignment != slot_alignment) {1016 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}", .{
1018 slot_alignment.toByteUnits(),1018 slot_alignment.toByteUnits(),
1019 alignment.toByteUnits(),1019 alignment.toByteUnits(),
1020 bucketStackTrace(bucket, slot_count, slot_index, .alloc),1020 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
...@@ -1054,7 +1054,7 @@ const TraceKind = enum {...@@ -1054,7 +1054,7 @@ const TraceKind = enum {
1054 free,1054 free,
1055};1055};
10561056
1057const test_config = Config{};1057const test_config: Config = .{};
10581058
1059test "small allocations - free in same order" {1059test "small allocations - free in same order" {
1060 var gpa = DebugAllocator(test_config){};1060 var gpa = DebugAllocator(test_config){};
lib/std/http.zig+13-8
...@@ -1,3 +1,7 @@...@@ -1,3 +1,7 @@
1const builtin = @import("builtin");
2const std = @import("std.zig");
3const assert = std.debug.assert;
4
1pub const Client = @import("http/Client.zig");5pub const Client = @import("http/Client.zig");
2pub const Server = @import("http/Server.zig");6pub const Server = @import("http/Server.zig");
3pub const protocol = @import("http/protocol.zig");7pub const protocol = @import("http/protocol.zig");
...@@ -38,8 +42,9 @@ pub const Method = enum(u64) {...@@ -38,8 +42,9 @@ pub const Method = enum(u64) {
38 return x;42 return x;
39 }43 }
4044
41 pub fn write(self: Method, w: anytype) !void {45 pub fn format(self: Method, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
42 const bytes = std.mem.asBytes(&@intFromEnum(self));46 comptime assert(f.len == 0);
47 const bytes: []const u8 = @ptrCast(&@intFromEnum(self));
43 const str = std.mem.sliceTo(bytes, 0);48 const str = std.mem.sliceTo(bytes, 0);
44 try w.writeAll(str);49 try w.writeAll(str);
45 }50 }
...@@ -77,7 +82,9 @@ pub const Method = enum(u64) {...@@ -77,7 +82,9 @@ pub const Method = enum(u64) {
77 };82 };
78 }83 }
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.
81 ///88 ///
82 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent89 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
83 ///90 ///
...@@ -90,7 +97,8 @@ pub const Method = enum(u64) {...@@ -90,7 +97,8 @@ pub const Method = enum(u64) {
90 };97 };
91 }98 }
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.
94 ///102 ///
95 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable103 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable
96 ///104 ///
...@@ -282,10 +290,10 @@ pub const Status = enum(u10) {...@@ -282,10 +290,10 @@ pub const Status = enum(u10) {
282 }290 }
283};291};
284292
293/// compression is intentionally omitted here since it is handled in `ContentEncoding`.
285pub const TransferEncoding = enum {294pub const TransferEncoding = enum {
286 chunked,295 chunked,
287 none,296 none,
288 // compression is intentionally omitted here, as std.http.Client stores it as content-encoding
289};297};
290298
291pub const ContentEncoding = enum {299pub const ContentEncoding = enum {
...@@ -308,9 +316,6 @@ pub const Header = struct {...@@ -308,9 +316,6 @@ pub const Header = struct {
308 value: []const u8,316 value: []const u8,
309};317};
310318
311const builtin = @import("builtin");
312const std = @import("std.zig");
313
314test {319test {
315 if (builtin.os.tag != .wasi) {320 if (builtin.os.tag != .wasi) {
316 _ = Client;321 _ = Client;
lib/std/http/Client.zig+17-10
...@@ -823,21 +823,28 @@ pub const Request = struct {...@@ -823,21 +823,28 @@ pub const Request = struct {
823 return error.UnsupportedTransferEncoding;823 return error.UnsupportedTransferEncoding;
824824
825 const connection = req.connection.?;825 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, "");
829 try w.writeByte(' ');836 try w.writeByte(' ');
830837
831 if (req.method == .CONNECT) {838 if (req.method == .CONNECT) {
832 try req.uri.writeToStream(.{ .authority = true }, w);839 try req.uri.writeToStream(w, .{ .authority = true });
833 } else {840 } else {
834 try req.uri.writeToStream(.{841 try req.uri.writeToStream(w, .{
835 .scheme = connection.proxied,842 .scheme = connection.proxied,
836 .authentication = connection.proxied,843 .authentication = connection.proxied,
837 .authority = connection.proxied,844 .authority = connection.proxied,
838 .path = true,845 .path = true,
839 .query = true,846 .query = true,
840 }, w);847 });
841 }848 }
842 try w.writeByte(' ');849 try w.writeByte(' ');
843 try w.writeAll(@tagName(req.version));850 try w.writeAll(@tagName(req.version));
...@@ -845,7 +852,7 @@ pub const Request = struct {...@@ -845,7 +852,7 @@ pub const Request = struct {
845852
846 if (try emitOverridableHeader("host: ", req.headers.host, w)) {853 if (try emitOverridableHeader("host: ", req.headers.host, w)) {
847 try w.writeAll("host: ");854 try w.writeAll("host: ");
848 try req.uri.writeToStream(.{ .authority = true }, w);855 try req.uri.writeToStream(w, .{ .authority = true });
849 try w.writeAll("\r\n");856 try w.writeAll("\r\n");
850 }857 }
851858
...@@ -1284,10 +1291,10 @@ pub const basic_authorization = struct {...@@ -1284,10 +1291,10 @@ pub const basic_authorization = struct {
12841291
1285 pub fn valueLengthFromUri(uri: Uri) usize {1292 pub fn valueLengthFromUri(uri: Uri) usize {
1286 var stream = std.io.countingWriter(std.io.null_writer);1293 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});
1288 const user_len = stream.bytes_written;1295 const user_len = stream.bytes_written;
1289 stream.bytes_written = 0;1296 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});
1291 const password_len = stream.bytes_written;1298 const password_len = stream.bytes_written;
1292 return valueLength(@intCast(user_len), @intCast(password_len));1299 return valueLength(@intCast(user_len), @intCast(password_len));
1293 }1300 }
...@@ -1295,10 +1302,10 @@ pub const basic_authorization = struct {...@@ -1295,10 +1302,10 @@ pub const basic_authorization = struct {
1295 pub fn value(uri: Uri, out: []u8) []u8 {1302 pub fn value(uri: Uri, out: []u8) []u8 {
1296 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;1303 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
1297 var stream = std.io.fixedBufferStream(&buf);1304 var stream = std.io.fixedBufferStream(&buf);
1298 stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch1305 stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty}) catch
1299 unreachable;1306 unreachable;
1300 assert(stream.pos <= max_user_len);1307 assert(stream.pos <= max_user_len);
1301 stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch1308 stream.writer().print(":{fpassword}", .{uri.password orelse Uri.Component.empty}) catch
1302 unreachable;1309 unreachable;
13031310
1304 @memcpy(out[0..prefix.len], prefix);1311 @memcpy(out[0..prefix.len], prefix);
lib/std/http/test.zig+2-4
...@@ -385,10 +385,8 @@ test "general client/server API coverage" {...@@ -385,10 +385,8 @@ test "general client/server API coverage" {
385 fn handleRequest(request: *http.Server.Request, listen_port: u16) !void {385 fn handleRequest(request: *http.Server.Request, listen_port: u16) !void {
386 const log = std.log.scoped(.server);386 const log = std.log.scoped(.server);
387387
388 log.info("{} {s} {s}", .{388 log.info("{f} {s} {s}", .{
389 request.head.method,389 request.head.method, @tagName(request.head.version), request.head.target,
390 @tagName(request.head.version),
391 request.head.target,
392 });390 });
393391
394 const gpa = std.testing.allocator;392 const gpa = std.testing.allocator;
lib/std/io.zig+27-1
...@@ -364,6 +364,32 @@ pub fn GenericWriter(...@@ -364,6 +364,32 @@ pub fn GenericWriter(
364 const ptr: *const Context = @alignCast(@ptrCast(context));364 const ptr: *const Context = @alignCast(@ptrCast(context));
365 return writeFn(ptr.*, bytes);365 return writeFn(ptr.*, bytes);
366 }366 }
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 };
367 };393 };
368}394}
369395
...@@ -419,7 +445,7 @@ pub const tty = @import("io/tty.zig");...@@ -419,7 +445,7 @@ pub const tty = @import("io/tty.zig");
419/// A Writer that doesn't write to anything.445/// A Writer that doesn't write to anything.
420pub const null_writer: NullWriter = .{ .context = {} };446pub const null_writer: NullWriter = .{ .context = {} };
421447
422pub const NullWriter = Writer(void, error{}, dummyWrite);448pub const NullWriter = GenericWriter(void, error{}, dummyWrite);
423fn dummyWrite(context: void, data: []const u8) error{}!usize {449fn dummyWrite(context: void, data: []const u8) error{}!usize {
424 _ = context;450 _ = context;
425 return data.len;451 return data.len;
lib/std/io/DeprecatedWriter.zig+27-1
...@@ -21,7 +21,7 @@ pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {...@@ -21,7 +21,7 @@ pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {
21}21}
2222
23pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {23pub 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);
25}25}
2626
27pub fn writeByte(self: Self, byte: u8) anyerror!void {27pub fn writeByte(self: Self, byte: u8) anyerror!void {
...@@ -81,3 +81,29 @@ pub fn writeFile(self: Self, file: std.fs.File) anyerror!void {...@@ -81,3 +81,29 @@ pub fn writeFile(self: Self, file: std.fs.File) anyerror!void {
81 if (n < buf.len) return;81 if (n < buf.len) return;
82 }82 }
83}83}
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 {...@@ -26,7 +26,8 @@ pub const VTable = struct {
26 /// Returns the number of bytes written, which will be at minimum `0` and26 /// Returns the number of bytes written, which will be at minimum `0` and
27 /// at most `limit`. The number returned, including zero, does not indicate27 /// at most `limit`. The number returned, including zero, does not indicate
28 /// end of stream. `limit` is guaranteed to be at least as large as the28 /// 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.
30 ///31 ///
31 /// The reader's internal logical seek position moves forward in accordance32 /// The reader's internal logical seek position moves forward in accordance
32 /// with the number of bytes returned from this function.33 /// with the number of bytes returned from this function.
...@@ -1243,10 +1244,10 @@ test peekArray {...@@ -1243,10 +1244,10 @@ test peekArray {
12431244
1244test discardAll {1245test discardAll {
1245 var r: Reader = .fixed("foobar");1246 var r: Reader = .fixed("foobar");
1246 try r.discard(3);1247 try r.discardAll(3);
1247 try testing.expectEqualStrings("bar", try r.take(3));1248 try testing.expectEqualStrings("bar", try r.take(3));
1248 try r.discard(0);1249 try r.discardAll(0);
1249 try testing.expectError(error.EndOfStream, r.discard(1));1250 try testing.expectError(error.EndOfStream, r.discardAll(1));
1250}1251}
12511252
1252test discardRemaining {1253test discardRemaining {
...@@ -1355,9 +1356,11 @@ test readVec {...@@ -1355,9 +1356,11 @@ test readVec {
13551356
1356test "expected error.EndOfStream" {1357test "expected error.EndOfStream" {
1357 // Unit test inspired by https://github.com/ziglang/zig/issues/177331358 // Unit test inspired by https://github.com/ziglang/zig/issues/17733
1358 var r: std.io.Reader = .fixed("");1359 var buffer: [3]u8 = undefined;
1359 try std.testing.expectError(error.EndOfStream, r.readEnum(enum(u8) { a, b }, .little));1360 var r: std.io.Reader = .fixed(&buffer);
1360 try std.testing.expectError(error.EndOfStream, r.isBytes("foo"));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));
1361}1364}
13621365
1363fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {1366fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
...@@ -1389,21 +1392,30 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {...@@ -1389,21 +1392,30 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
1389test "readAlloc when the backing reader provides one byte at a time" {1392test "readAlloc when the backing reader provides one byte at a time" {
1390 const OneByteReader = struct {1393 const OneByteReader = struct {
1391 str: []const u8,1394 str: []const u8,
1392 curr: usize,1395 i: usize,
13931396 reader: Reader,
1394 fn read(self: *@This(), dest: []u8) usize {1397
1395 if (self.str.len <= self.curr or dest.len == 0)1398 fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1396 return 0;1399 assert(@intFromEnum(limit) >= 1);
13971400 const self: *@This() = @fieldParentPtr("reader", r);
1398 dest[0] = self.str[self.curr];1401 if (self.str.len - self.i == 0) return error.EndOfStream;
1399 self.curr += 1;1402 try w.writeByte(self.str[self.i]);
1403 self.i += 1;
1400 return 1;1404 return 1;
1401 }1405 }
1402 };1406 };
1403
1404 const str = "This is a test";1407 const str = "This is a test";
1405 var one_byte_stream: OneByteReader = .init(str);1408 var one_byte_stream: OneByteReader = .{
1406 const res = try one_byte_stream.reader().streamReadAlloc(std.testing.allocator, str.len + 1);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);
1407 defer std.testing.allocator.free(res);1419 defer std.testing.allocator.free(res);
1408 try std.testing.expectEqualStrings(str, res);1420 try std.testing.expectEqualStrings(str, res);
1409}1421}
lib/std/io/Writer.zig+128-133
...@@ -37,6 +37,10 @@ pub const VTable = struct {...@@ -37,6 +37,10 @@ pub const VTable = struct {
37 /// The last element of `data` is repeated as necessary so that it is37 /// The last element of `data` is repeated as necessary so that it is
38 /// written `splat` number of times, which may be zero.38 /// written `splat` number of times, which may be zero.
39 ///39 ///
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 ///
40 /// Number of bytes consumed from `data` is returned, excluding bytes from44 /// Number of bytes consumed from `data` is returned, excluding bytes from
41 /// `buffer`.45 /// `buffer`.
42 ///46 ///
...@@ -800,18 +804,13 @@ pub fn printValue(...@@ -800,18 +804,13 @@ pub fn printValue(
800) Error!void {804) Error!void {
801 const T = @TypeOf(value);805 const T = @TypeOf(value);
802806
803 if (comptime std.mem.eql(u8, fmt, "*")) {807 if (comptime std.mem.eql(u8, fmt, "*")) return w.printAddress(value);
804 return w.printAddress(value);808 if (fmt.len > 0 and fmt[0] == 'f') return value.format(w, fmt[1..]);
805 }
806809
807 const is_any = comptime std.mem.eql(u8, fmt, ANY);810 const is_any = comptime std.mem.eql(u8, fmt, ANY);
808 if (!is_any and std.meta.hasMethod(T, "format")) {811 if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) {
809 if (fmt.len > 0 and fmt[0] == 'f') {812 // after 0.15.0 is tagged, delete this compile error and its condition
810 return value.format(w, fmt[1..]);813 @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
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 }
815 }814 }
816815
817 switch (@typeInfo(T)) {816 switch (@typeInfo(T)) {
...@@ -952,9 +951,8 @@ pub fn printValue(...@@ -952,9 +951,8 @@ pub fn printValue(
952 },951 },
953 .pointer => |ptr_info| switch (ptr_info.size) {952 .pointer => |ptr_info| switch (ptr_info.size) {
954 .one => switch (@typeInfo(ptr_info.child)) {953 .one => switch (@typeInfo(ptr_info.child)) {
955 .array, .@"enum", .@"union", .@"struct" => {954 .array => |array_info| return w.printValue(fmt, options, @as([]const array_info.child, value), max_depth),
956 return w.printValue(fmt, options, value.*, max_depth);955 .@"enum", .@"union", .@"struct" => return w.printValue(fmt, options, value.*, max_depth),
957 },
958 else => {956 else => {
959 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };957 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
960 try w.writeVecAll(&buffers);958 try w.writeVecAll(&buffers);
...@@ -1120,7 +1118,12 @@ pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error...@@ -1120,7 +1118,12 @@ pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error
11201118
1121pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {1119pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {
1122 var buf: [4]u8 = undefined;1120 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 };
1124 return w.alignBufferOptions(buf[0..len], options);1127 return w.alignBufferOptions(buf[0..len], options);
1125}1128}
11261129
...@@ -1553,13 +1556,7 @@ test "formatValue max_depth" {...@@ -1553,13 +1556,7 @@ test "formatValue max_depth" {
1553 x: f32,1556 x: f32,
1554 y: f32,1557 y: f32,
15551558
1556 pub fn format(1559 pub fn format(self: SelfType, w: *Writer, comptime fmt: []const u8) Error!void {
1557 self: SelfType,
1558 comptime fmt: []const u8,
1559 options: std.fmt.Options,
1560 w: *Writer,
1561 ) Error!void {
1562 _ = options;
1563 if (fmt.len == 0) {1560 if (fmt.len == 0) {
1564 return w.print("({d:.3},{d:.3})", .{ self.x, self.y });1561 return w.print("({d:.3},{d:.3})", .{ self.x, self.y });
1565 } else {1562 } else {
...@@ -1600,131 +1597,131 @@ test "formatValue max_depth" {...@@ -1600,131 +1597,131 @@ test "formatValue max_depth" {
1600 try w.printValue("", .{}, inst, 0);1597 try w.printValue("", .{}, inst, 0);
1601 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered());1598 try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered());
16021599
1603 w.reset();1600 w = .fixed(&buf);
1604 try w.printValue("", .{}, inst, 1);1601 try w.printValue("", .{}, inst, 1);
1605 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());1602 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);
1608 try w.printValue("", .{}, inst, 2);1605 try w.printValue("", .{}, inst, 2);
1609 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());1606 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);
1612 try w.printValue("", .{}, inst, 3);1609 try w.printValue("", .{}, inst, 3);
1613 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());1610 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
1615 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };1612 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
1616 w.reset();1613 w = .fixed(&buf);
1617 try w.printValue("", .{}, vec, 0);1614 try w.printValue("", .{}, vec, 0);
1618 try testing.expectEqualStrings("{ ... }", w.buffered());1615 try testing.expectEqualStrings("{ ... }", w.buffered());
16191616
1620 w.reset();1617 w = .fixed(&buf);
1621 try w.printValue("", .{}, vec, 1);1618 try w.printValue("", .{}, vec, 1);
1622 try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());1619 try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());
1623}1620}
16241621
1625test printDuration {1622test printDuration {
1626 testDurationCase("0ns", 0);1623 try testDurationCase("0ns", 0);
1627 testDurationCase("1ns", 1);1624 try testDurationCase("1ns", 1);
1628 testDurationCase("999ns", std.time.ns_per_us - 1);1625 try testDurationCase("999ns", std.time.ns_per_us - 1);
1629 testDurationCase("1us", std.time.ns_per_us);1626 try testDurationCase("1us", std.time.ns_per_us);
1630 testDurationCase("1.45us", 1450);1627 try testDurationCase("1.45us", 1450);
1631 testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);1628 try testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
1632 testDurationCase("14.5us", 14500);1629 try testDurationCase("14.5us", 14500);
1633 testDurationCase("145us", 145000);1630 try testDurationCase("145us", 145000);
1634 testDurationCase("999.999us", std.time.ns_per_ms - 1);1631 try testDurationCase("999.999us", std.time.ns_per_ms - 1);
1635 testDurationCase("1ms", std.time.ns_per_ms + 1);1632 try testDurationCase("1ms", std.time.ns_per_ms + 1);
1636 testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);1633 try testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
1637 testDurationCase("1.11ms", 1110000);1634 try testDurationCase("1.11ms", 1110000);
1638 testDurationCase("1.111ms", 1111000);1635 try testDurationCase("1.111ms", 1111000);
1639 testDurationCase("1.111ms", 1111100);1636 try testDurationCase("1.111ms", 1111100);
1640 testDurationCase("999.999ms", std.time.ns_per_s - 1);1637 try testDurationCase("999.999ms", std.time.ns_per_s - 1);
1641 testDurationCase("1s", std.time.ns_per_s);1638 try testDurationCase("1s", std.time.ns_per_s);
1642 testDurationCase("59.999s", std.time.ns_per_min - 1);1639 try testDurationCase("59.999s", std.time.ns_per_min - 1);
1643 testDurationCase("1m", std.time.ns_per_min);1640 try testDurationCase("1m", std.time.ns_per_min);
1644 testDurationCase("1h", std.time.ns_per_hour);1641 try testDurationCase("1h", std.time.ns_per_hour);
1645 testDurationCase("1d", std.time.ns_per_day);1642 try testDurationCase("1d", std.time.ns_per_day);
1646 testDurationCase("1w", std.time.ns_per_week);1643 try testDurationCase("1w", std.time.ns_per_week);
1647 testDurationCase("1y", 365 * std.time.ns_per_day);1644 try testDurationCase("1y", 365 * std.time.ns_per_day);
1648 testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w11645 try 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);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);
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);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);
1651 testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);1648 try 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);1649 try 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);1650 try 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);1651 try testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1655 testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));1652 try testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
16561653
1657 testing.expectFmt("=======0ns", "{D:=>10}", .{0});1654 try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1658 testing.expectFmt("1ns=======", "{D:=<10}", .{1});1655 try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1659 testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});1656 try testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
1660}1657}
16611658
1662test printDurationSigned {1659test printDurationSigned {
1663 testDurationCaseSigned("0ns", 0);1660 try testDurationCaseSigned("0ns", 0);
1664 testDurationCaseSigned("1ns", 1);1661 try testDurationCaseSigned("1ns", 1);
1665 testDurationCaseSigned("-1ns", -(1));1662 try testDurationCaseSigned("-1ns", -(1));
1666 testDurationCaseSigned("999ns", std.time.ns_per_us - 1);1663 try testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
1667 testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));1664 try testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
1668 testDurationCaseSigned("1us", std.time.ns_per_us);1665 try testDurationCaseSigned("1us", std.time.ns_per_us);
1669 testDurationCaseSigned("-1us", -(std.time.ns_per_us));1666 try testDurationCaseSigned("-1us", -(std.time.ns_per_us));
1670 testDurationCaseSigned("1.45us", 1450);1667 try testDurationCaseSigned("1.45us", 1450);
1671 testDurationCaseSigned("-1.45us", -(1450));1668 try testDurationCaseSigned("-1.45us", -(1450));
1672 testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);1669 try testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
1673 testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));1670 try testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
1674 testDurationCaseSigned("14.5us", 14500);1671 try testDurationCaseSigned("14.5us", 14500);
1675 testDurationCaseSigned("-14.5us", -(14500));1672 try testDurationCaseSigned("-14.5us", -(14500));
1676 testDurationCaseSigned("145us", 145000);1673 try testDurationCaseSigned("145us", 145000);
1677 testDurationCaseSigned("-145us", -(145000));1674 try testDurationCaseSigned("-145us", -(145000));
1678 testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);1675 try testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
1679 testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));1676 try testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
1680 testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);1677 try testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
1681 testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));1678 try testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
1682 testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);1679 try testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
1683 testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));1680 try testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
1684 testDurationCaseSigned("1.11ms", 1110000);1681 try testDurationCaseSigned("1.11ms", 1110000);
1685 testDurationCaseSigned("-1.11ms", -(1110000));1682 try testDurationCaseSigned("-1.11ms", -(1110000));
1686 testDurationCaseSigned("1.111ms", 1111000);1683 try testDurationCaseSigned("1.111ms", 1111000);
1687 testDurationCaseSigned("-1.111ms", -(1111000));1684 try testDurationCaseSigned("-1.111ms", -(1111000));
1688 testDurationCaseSigned("1.111ms", 1111100);1685 try testDurationCaseSigned("1.111ms", 1111100);
1689 testDurationCaseSigned("-1.111ms", -(1111100));1686 try testDurationCaseSigned("-1.111ms", -(1111100));
1690 testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);1687 try testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
1691 testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));1688 try testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
1692 testDurationCaseSigned("1s", std.time.ns_per_s);1689 try testDurationCaseSigned("1s", std.time.ns_per_s);
1693 testDurationCaseSigned("-1s", -(std.time.ns_per_s));1690 try testDurationCaseSigned("-1s", -(std.time.ns_per_s));
1694 testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);1691 try testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
1695 testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));1692 try testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
1696 testDurationCaseSigned("1m", std.time.ns_per_min);1693 try testDurationCaseSigned("1m", std.time.ns_per_min);
1697 testDurationCaseSigned("-1m", -(std.time.ns_per_min));1694 try testDurationCaseSigned("-1m", -(std.time.ns_per_min));
1698 testDurationCaseSigned("1h", std.time.ns_per_hour);1695 try testDurationCaseSigned("1h", std.time.ns_per_hour);
1699 testDurationCaseSigned("-1h", -(std.time.ns_per_hour));1696 try testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
1700 testDurationCaseSigned("1d", std.time.ns_per_day);1697 try testDurationCaseSigned("1d", std.time.ns_per_day);
1701 testDurationCaseSigned("-1d", -(std.time.ns_per_day));1698 try testDurationCaseSigned("-1d", -(std.time.ns_per_day));
1702 testDurationCaseSigned("1w", std.time.ns_per_week);1699 try testDurationCaseSigned("1w", std.time.ns_per_week);
1703 testDurationCaseSigned("-1w", -(std.time.ns_per_week));1700 try testDurationCaseSigned("-1w", -(std.time.ns_per_week));
1704 testDurationCaseSigned("1y", 365 * std.time.ns_per_day);1701 try testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
1705 testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));1702 try testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
1706 testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d1703 try testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
1707 testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d1704 try 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);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);
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));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));
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);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);
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));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));
1712 testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);1709 try 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));1710 try 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);1711 try 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));1712 try 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);1713 try 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));1714 try 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);1715 try 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));1716 try testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
1720 testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));1717 try testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
1721 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);1718 try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
1722 testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));1719 try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
17231720
1724 testing.expectFmt("=======0ns", "{s:=>10}", .{0});1721 try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1725 testing.expectFmt("1ns=======", "{s:=<10}", .{1});1722 try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1726 testing.expectFmt("-1ns======", "{s:=<10}", .{-(1)});1723 try testing.expectFmt("-1ns======", "{D:=<10}", .{-(1)});
1727 testing.expectFmt(" -999ns ", "{s:^10}", .{-(std.time.ns_per_us - 1)});1724 try testing.expectFmt(" -999ns ", "{D:^10}", .{-(std.time.ns_per_us - 1)});
1728}1725}
17291726
1730fn testDurationCase(expected: []const u8, input: u64) !void {1727fn testDurationCase(expected: []const u8, input: u64) !void {
...@@ -1762,7 +1759,7 @@ test printIntOptions {...@@ -1762,7 +1759,7 @@ test printIntOptions {
1762test "printInt with comptime_int" {1759test "printInt with comptime_int" {
1763 var buf: [20]u8 = undefined;1760 var buf: [20]u8 = undefined;
1764 var w: Writer = .fixed(&buf);1761 var w: Writer = .fixed(&buf);
1765 try w.printInt(@as(comptime_int, 123456789123456789), "", .{});1762 try w.printInt("", .{}, @as(comptime_int, 123456789123456789));
1766 try std.testing.expectEqualStrings("123456789123456789", w.buffered());1763 try std.testing.expectEqualStrings("123456789123456789", w.buffered());
1767}1764}
17681765
...@@ -1777,7 +1774,7 @@ test "printFloat with comptime_float" {...@@ -1777,7 +1774,7 @@ test "printFloat with comptime_float" {
1777fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {1774fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
1778 var buffer: [100]u8 = undefined;1775 var buffer: [100]u8 = undefined;
1779 var w: Writer = .fixed(&buffer);1776 var w: Writer = .fixed(&buffer);
1780 w.printIntOptions(value, base, case, options);1777 try w.printIntOptions(value, base, case, options);
1781 try testing.expectEqualStrings(expected, w.buffered());1778 try testing.expectEqualStrings(expected, w.buffered());
1782}1779}
17831780
...@@ -1832,17 +1829,15 @@ test "fixed output" {...@@ -1832,17 +1829,15 @@ test "fixed output" {
1832 try w.writeAll("world");1829 try w.writeAll("world");
1833 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));1830 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("!"));
1836 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));1833 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
18371834
1838 w.reset();1835 w = .fixed(&buffer);
1836
1839 try testing.expect(w.buffered().len == 0);1837 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!"));
1842 try testing.expect(std.mem.eql(u8, w.buffered(), "Hello worl"));1840 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"));
1846}1841}
18471842
1848pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {1843pub 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 {...@@ -33,7 +33,7 @@ pub const BufferedAtomicFile = struct {
33 self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options);33 self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options);
34 errdefer self.atomic_file.deinit();34 errdefer self.atomic_file.deinit();
3535
36 self.file_writer = self.atomic_file.file.writer();36 self.file_writer = self.atomic_file.file.deprecatedWriter();
37 self.buffered_writer = .{ .unbuffered_writer = self.file_writer };37 self.buffered_writer = .{ .unbuffered_writer = self.file_writer };
38 return self;38 return self;
39 }39 }
lib/std/io/test.zig+4-4
...@@ -24,7 +24,7 @@ test "write a file, read it, then delete it" {...@@ -24,7 +24,7 @@ test "write a file, read it, then delete it" {
24 var file = try tmp.dir.createFile(tmp_file_name, .{});24 var file = try tmp.dir.createFile(tmp_file_name, .{});
25 defer file.close();25 defer file.close();
2626
27 var buf_stream = io.bufferedWriter(file.writer());27 var buf_stream = io.bufferedWriter(file.deprecatedWriter());
28 const st = buf_stream.writer();28 const st = buf_stream.writer();
29 try st.print("begin", .{});29 try st.print("begin", .{});
30 try st.writeAll(data[0..]);30 try st.writeAll(data[0..]);
...@@ -45,7 +45,7 @@ test "write a file, read it, then delete it" {...@@ -45,7 +45,7 @@ test "write a file, read it, then delete it" {
45 const expected_file_size: u64 = "begin".len + data.len + "end".len;45 const expected_file_size: u64 = "begin".len + data.len + "end".len;
46 try expectEqual(expected_file_size, file_size);46 try expectEqual(expected_file_size, file_size);
4747
48 var buf_stream = io.bufferedReader(file.reader());48 var buf_stream = io.bufferedReader(file.deprecatedReader());
49 const st = buf_stream.reader();49 const st = buf_stream.reader();
50 const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024);50 const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024);
51 defer std.testing.allocator.free(contents);51 defer std.testing.allocator.free(contents);
...@@ -66,7 +66,7 @@ test "BitStreams with File Stream" {...@@ -66,7 +66,7 @@ test "BitStreams with File Stream" {
66 var file = try tmp.dir.createFile(tmp_file_name, .{});66 var file = try tmp.dir.createFile(tmp_file_name, .{});
67 defer file.close();67 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
71 try bit_stream.writeBits(@as(u2, 1), 1);71 try bit_stream.writeBits(@as(u2, 1), 1);
72 try bit_stream.writeBits(@as(u5, 2), 2);72 try bit_stream.writeBits(@as(u5, 2), 2);
...@@ -80,7 +80,7 @@ test "BitStreams with File Stream" {...@@ -80,7 +80,7 @@ test "BitStreams with File Stream" {
80 var file = try tmp.dir.openFile(tmp_file_name, .{});80 var file = try tmp.dir.openFile(tmp_file_name, .{});
81 defer file.close();81 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
85 var out_bits: u16 = undefined;85 var out_bits: u16 = undefined;
8686
lib/std/json/dynamic.zig+1-1
...@@ -56,7 +56,7 @@ pub const Value = union(enum) {...@@ -56,7 +56,7 @@ pub const Value = union(enum) {
56 std.debug.lockStdErr();56 std.debug.lockStdErr();
57 defer std.debug.unlockStdErr();57 defer std.debug.unlockStdErr();
5858
59 const stderr = std.fs.File.stderr().writer();59 const stderr = std.fs.File.stderr().deprecatedWriter();
60 stringify(self, .{}, stderr) catch return;60 stringify(self, .{}, stderr) catch return;
61 }61 }
6262
lib/std/json/fmt.zig+4-9
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("../std.zig");
2const assert = std.debug.assert;
23
3const stringify = @import("stringify.zig").stringify;4const stringify = @import("stringify.zig").stringify;
4const StringifyOptions = @import("stringify.zig").StringifyOptions;5const StringifyOptions = @import("stringify.zig").StringifyOptions;
...@@ -14,14 +15,8 @@ pub fn Formatter(comptime T: type) type {...@@ -14,14 +15,8 @@ pub fn Formatter(comptime T: type) type {
14 value: T,15 value: T,
15 options: StringifyOptions,16 options: StringifyOptions,
1617
17 pub fn format(18 pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
18 self: @This(),19 comptime assert(f.len == 0);
19 comptime fmt_spec: []const u8,
20 options: std.fmt.FormatOptions,
21 writer: anytype,
22 ) !void {
23 _ = fmt_spec;
24 _ = options;
25 try stringify(self.value, self.options, writer);20 try stringify(self.value, self.options, writer);
26 }21 }
27 };22 };
lib/std/json/stringify.zig+6-3
...@@ -689,7 +689,8 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {...@@ -689,7 +689,8 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
689 // then it may be represented as a six-character sequence: a reverse solidus, followed689 // then it may be represented as a six-character sequence: a reverse solidus, followed
690 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.690 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
691 try out_stream.writeAll("\\u");691 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});
693 } else {694 } else {
694 assert(codepoint <= 0x10FFFF);695 assert(codepoint <= 0x10FFFF);
695 // To escape an extended character that is not in the Basic Multilingual Plane,696 // 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 {...@@ -697,9 +698,11 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
697 const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;698 const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;
698 const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;699 const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;
699 try out_stream.writeAll("\\u");700 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});
701 try out_stream.writeAll("\\u");703 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});
703 }706 }
704}707}
705708
lib/std/log.zig+2-2
...@@ -47,7 +47,7 @@...@@ -47,7 +47,7 @@
47//! // Print the message to stderr, silently ignoring any errors47//! // Print the message to stderr, silently ignoring any errors
48//! std.debug.lockStdErr();48//! std.debug.lockStdErr();
49//! defer std.debug.unlockStdErr();49//! defer std.debug.unlockStdErr();
50//! const stderr = std.fs.File.stderr().writer();50//! const stderr = std.fs.File.stderr().deprecatedWriter();
51//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;51//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
52//! }52//! }
53//!53//!
...@@ -148,7 +148,7 @@ pub fn defaultLog(...@@ -148,7 +148,7 @@ pub fn defaultLog(
148) void {148) void {
149 const level_txt = comptime message_level.asText();149 const level_txt = comptime message_level.asText();
150 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";150 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
151 const stderr = std.fs.File.stderr().writer();151 const stderr = std.fs.File.stderr().deprecatedWriter();
152 var bw = std.io.bufferedWriter(stderr);152 var bw = std.io.bufferedWriter(stderr);
153 const writer = bw.writer();153 const writer = bw.writer();
154154
lib/std/math/big/int.zig+5-16
...@@ -2322,13 +2322,7 @@ pub const Const = struct {...@@ -2322,13 +2322,7 @@ pub const Const = struct {
2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2325 pub fn format(2325 pub fn format(self: Const, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
2326 self: Const,
2327 comptime fmt: []const u8,
2328 options: std.fmt.FormatOptions,
2329 out_stream: anytype,
2330 ) !void {
2331 _ = options;
2332 comptime var base = 10;2326 comptime var base = 10;
2333 comptime var case: std.fmt.Case = .lower;2327 comptime var case: std.fmt.Case = .lower;
23342328
...@@ -2350,7 +2344,7 @@ pub const Const = struct {...@@ -2350,7 +2344,7 @@ pub const Const = struct {
23502344
2351 const available_len = 64;2345 const available_len = 64;
2352 if (self.limbs.len > available_len)2346 if (self.limbs.len > available_len)
2353 return out_stream.writeAll("(BigInt)");2347 return w.writeAll("(BigInt)");
23542348
2355 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;2349 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;
23562350
...@@ -2360,7 +2354,7 @@ pub const Const = struct {...@@ -2360,7 +2354,7 @@ pub const Const = struct {
2360 };2354 };
2361 var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;2355 var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;
2362 const len = self.toString(&buf, base, case, &limbs);2356 const len = self.toString(&buf, base, case, &limbs);
2363 return out_stream.writeAll(buf[0..len]);2357 return w.writeAll(buf[0..len]);
2364 }2358 }
23652359
2366 /// Converts self to a string in the requested base.2360 /// Converts self to a string in the requested base.
...@@ -2934,13 +2928,8 @@ pub const Managed = struct {...@@ -2934,13 +2928,8 @@ pub const Managed = struct {
2934 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2928 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2935 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2929 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2936 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2930 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2937 pub fn format(2931 pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
2938 self: Managed,2932 return self.toConst().format(w, f);
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);
2944 }2933 }
29452934
2946 /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==2935 /// 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" {...@@ -3813,10 +3813,10 @@ test "(BigInt) positive" {
3813 try a.pow(&a, 64 * @sizeOf(Limb) * 8);3813 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
3814 try b.sub(&a, &c);3814 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);
3817 defer testing.allocator.free(a_fmt);3817 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);
3820 defer testing.allocator.free(b_fmt);3820 defer testing.allocator.free(b_fmt);
38213821
3822 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));3822 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
...@@ -3838,10 +3838,10 @@ test "(BigInt) negative" {...@@ -3838,10 +3838,10 @@ test "(BigInt) negative" {
3838 a.negate();3838 a.negate();
3839 try b.add(&a, &c);3839 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);
3842 defer testing.allocator.free(a_fmt);3842 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);
3845 defer testing.allocator.free(b_fmt);3845 defer testing.allocator.free(b_fmt);
38463846
3847 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));3847 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
lib/std/multi_array_list.zig+1
...@@ -991,6 +991,7 @@ test "0 sized struct" {...@@ -991,6 +991,7 @@ test "0 sized struct" {
991test "struct with many fields" {991test "struct with many fields" {
992 const ManyFields = struct {992 const ManyFields = struct {
993 fn Type(count: comptime_int) type {993 fn Type(count: comptime_int) type {
994 @setEvalBranchQuota(50000);
994 var fields: [count]std.builtin.Type.StructField = undefined;995 var fields: [count]std.builtin.Type.StructField = undefined;
995 for (0..count) |i| {996 for (0..count) |i| {
996 fields[i] = .{997 fields[i] = .{
lib/std/net.zig+22-48
...@@ -161,22 +161,14 @@ pub const Address = extern union {...@@ -161,22 +161,14 @@ pub const Address = extern union {
161 }161 }
162 }162 }
163163
164 pub fn format(164 pub fn format(self: Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
165 self: Address,165 comptime assert(fmt.len == 0);
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);
171 switch (self.any.family) {166 switch (self.any.family) {
172 posix.AF.INET => try self.in.format(fmt, options, out_stream),167 posix.AF.INET => try self.in.format(w, fmt),
173 posix.AF.INET6 => try self.in6.format(fmt, options, out_stream),168 posix.AF.INET6 => try self.in6.format(w, fmt),
174 posix.AF.UNIX => {169 posix.AF.UNIX => {
175 if (!has_unix_sockets) {170 if (!has_unix_sockets) unreachable;
176 unreachable;171 try w.writeAll(std.mem.sliceTo(&self.un.path, 0));
177 }
178
179 try std.fmt.format(out_stream, "{s}", .{std.mem.sliceTo(&self.un.path, 0)});
180 },172 },
181 else => unreachable,173 else => unreachable,
182 }174 }
...@@ -349,22 +341,10 @@ pub const Ip4Address = extern struct {...@@ -349,22 +341,10 @@ pub const Ip4Address = extern struct {
349 self.sa.port = mem.nativeToBig(u16, port);341 self.sa.port = mem.nativeToBig(u16, port);
350 }342 }
351343
352 pub fn format(344 pub fn format(self: Ip4Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
353 self: Ip4Address,345 comptime assert(fmt.len == 0);
354 comptime fmt: []const u8,346 const bytes: *const [4]u8 = @ptrCast(&self.sa.addr);
355 options: std.fmt.FormatOptions,347 try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() });
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 });
368 }348 }
369349
370 pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {350 pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {
...@@ -653,17 +633,11 @@ pub const Ip6Address = extern struct {...@@ -653,17 +633,11 @@ pub const Ip6Address = extern struct {
653 self.sa.port = mem.nativeToBig(u16, port);633 self.sa.port = mem.nativeToBig(u16, port);
654 }634 }
655635
656 pub fn format(636 pub fn format(self: Ip6Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
657 self: Ip6Address,637 comptime assert(fmt.len == 0);
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;
664 const port = mem.bigToNative(u16, self.sa.port);638 const port = mem.bigToNative(u16, self.sa.port);
665 if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {639 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}", .{
667 self.sa.addr[12],641 self.sa.addr[12],
668 self.sa.addr[13],642 self.sa.addr[13],
669 self.sa.addr[14],643 self.sa.addr[14],
...@@ -711,14 +685,14 @@ pub const Ip6Address = extern struct {...@@ -711,14 +685,14 @@ pub const Ip6Address = extern struct {
711 longest_len = 0;685 longest_len = 0;
712 }686 }
713687
714 try out_stream.writeAll("[");688 try w.writeAll("[");
715 var i: usize = 0;689 var i: usize = 0;
716 var abbrv = false;690 var abbrv = false;
717 while (i < native_endian_parts.len) : (i += 1) {691 while (i < native_endian_parts.len) : (i += 1) {
718 if (i == longest_start) {692 if (i == longest_start) {
719 // Emit "::" for the longest zero run693 // Emit "::" for the longest zero run
720 if (!abbrv) {694 if (!abbrv) {
721 try out_stream.writeAll(if (i == 0) "::" else ":");695 try w.writeAll(if (i == 0) "::" else ":");
722 abbrv = true;696 abbrv = true;
723 }697 }
724 i += longest_len - 1; // Skip the compressed range698 i += longest_len - 1; // Skip the compressed range
...@@ -727,12 +701,12 @@ pub const Ip6Address = extern struct {...@@ -727,12 +701,12 @@ pub const Ip6Address = extern struct {
727 if (abbrv) {701 if (abbrv) {
728 abbrv = false;702 abbrv = false;
729 }703 }
730 try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});704 try w.print("{x}", .{native_endian_parts[i]});
731 if (i != native_endian_parts.len - 1) {705 if (i != native_endian_parts.len - 1) {
732 try out_stream.writeAll(":");706 try w.writeAll(":");
733 }707 }
734 }708 }
735 try std.fmt.format(out_stream, "]:{}", .{port});709 try w.print("]:{}", .{port});
736 }710 }
737711
738 pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {712 pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {
...@@ -894,7 +868,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get...@@ -894,7 +868,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
894 const name_c = try allocator.dupeZ(u8, name);868 const name_c = try allocator.dupeZ(u8, name);
895 defer allocator.free(name_c);869 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);
898 defer allocator.free(port_c);872 defer allocator.free(port_c);
899873
900 const ws2_32 = windows.ws2_32;874 const ws2_32 = windows.ws2_32;
...@@ -966,7 +940,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get...@@ -966,7 +940,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
966 const name_c = try allocator.dupeZ(u8, name);940 const name_c = try allocator.dupeZ(u8, name);
967 defer allocator.free(name_c);941 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);
970 defer allocator.free(port_c);944 defer allocator.free(port_c);
971945
972 const hints: posix.addrinfo = .{946 const hints: posix.addrinfo = .{
...@@ -1356,7 +1330,7 @@ fn linuxLookupNameFromHosts(...@@ -1356,7 +1330,7 @@ fn linuxLookupNameFromHosts(
1356 };1330 };
1357 defer file.close();1331 defer file.close();
13581332
1359 var buffered_reader = std.io.bufferedReader(file.reader());1333 var buffered_reader = std.io.bufferedReader(file.deprecatedReader());
1360 const reader = buffered_reader.reader();1334 const reader = buffered_reader.reader();
1361 var line_buf: [512]u8 = undefined;1335 var line_buf: [512]u8 = undefined;
1362 while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {1336 while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
...@@ -1557,7 +1531,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {...@@ -1557,7 +1531,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
1557 };1531 };
1558 defer file.close();1532 defer file.close();
15591533
1560 var buf_reader = std.io.bufferedReader(file.reader());1534 var buf_reader = std.io.bufferedReader(file.deprecatedReader());
1561 const stream = buf_reader.reader();1535 const stream = buf_reader.reader();
1562 var line_buf: [512]u8 = undefined;1536 var line_buf: [512]u8 = undefined;
1563 while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {1537 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;...@@ -7,18 +7,12 @@ const testing = std.testing;
7test "parse and render IP addresses at comptime" {7test "parse and render IP addresses at comptime" {
8 if (builtin.os.tag == .wasi) return error.SkipZigTest;8 if (builtin.os.tag == .wasi) return error.SkipZigTest;
9 comptime {9 comptime {
10 var ipAddrBuffer: [16]u8 = undefined;
11 // Parses IPv6 at comptime
12 const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;10 const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
13 var ipv6 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv6addr}) catch unreachable;11 try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr});
14 try std.testing.expect(std.mem.eql(u8, "::1", ipv6[1 .. ipv6.len - 3]));
1512
16 // Parses IPv4 at comptime
17 const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;13 const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;
18 var ipv4 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv4addr}) catch unreachable;14 try std.testing.expectFmt("127.0.0.1:0", "{f}", .{ipv4addr});
19 try std.testing.expect(std.mem.eql(u8, "127.0.0.1", ipv4[0 .. ipv4.len - 2]));
2015
21 // Returns error for invalid IP addresses at comptime
22 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0));16 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0));
23 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("127.01.0.1", 0));17 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("127.01.0.1", 0));
24 try testing.expectError(error.InvalidIPAddressFormat, net.Address.resolveIp("::123.123.123.123", 0));18 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" {...@@ -28,13 +22,8 @@ test "parse and render IP addresses at comptime" {
2822
29test "format IPv6 address with no zero runs" {23test "format IPv6 address with no zero runs" {
30 if (builtin.os.tag == .wasi) return error.SkipZigTest;24 if (builtin.os.tag == .wasi) return error.SkipZigTest;
31
32 const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);25 const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);
3326 try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr});
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);
38}27}
3928
40test "parse IPv6 addresses and check compressed form" {29test "parse IPv6 addresses and check compressed form" {
...@@ -111,12 +100,12 @@ test "parse and render IPv6 addresses" {...@@ -111,12 +100,12 @@ test "parse and render IPv6 addresses" {
111 };100 };
112 for (ips, 0..) |ip, i| {101 for (ips, 0..) |ip, i| {
113 const addr = net.Address.parseIp6(ip, 0) catch unreachable;102 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;
115 try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));104 try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
116105
117 if (builtin.os.tag == .linux) {106 if (builtin.os.tag == .linux) {
118 const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;107 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;
120 try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));109 try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));
121 }110 }
122 }111 }
...@@ -159,7 +148,7 @@ test "parse and render IPv4 addresses" {...@@ -159,7 +148,7 @@ test "parse and render IPv4 addresses" {
159 "127.0.0.1",148 "127.0.0.1",
160 }) |ip| {149 }) |ip| {
161 const addr = net.Address.parseIp4(ip, 0) catch unreachable;150 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;
163 try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));152 try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
164 }153 }
165154
...@@ -175,10 +164,8 @@ test "parse and render UNIX addresses" {...@@ -175,10 +164,8 @@ test "parse and render UNIX addresses" {
175 if (builtin.os.tag == .wasi) return error.SkipZigTest;164 if (builtin.os.tag == .wasi) return error.SkipZigTest;
176 if (!net.has_unix_sockets) return error.SkipZigTest;165 if (!net.has_unix_sockets) return error.SkipZigTest;
177166
178 var buffer: [14]u8 = undefined;
179 const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;167 const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;
180 const fmt_addr = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;168 try std.testing.expectFmt("/tmp/testpath", "{f}", .{addr});
181 try std.testing.expectEqualSlices(u8, "/tmp/testpath", fmt_addr);
182169
183 const too_long = [_]u8{'a'} ** 200;170 const too_long = [_]u8{'a'} ** 200;
184 try testing.expectError(error.NameTooLong, net.Address.initUnix(too_long[0..]));171 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");...@@ -31,6 +31,7 @@ pub const uefi = @import("os/uefi.zig");
31pub const wasi = @import("os/wasi.zig");31pub const wasi = @import("os/wasi.zig");
32pub const emscripten = @import("os/emscripten.zig");32pub const emscripten = @import("os/emscripten.zig");
33pub const windows = @import("os/windows.zig");33pub const windows = @import("os/windows.zig");
34pub const freebsd = @import("os/freebsd.zig");
3435
35test {36test {
36 _ = linux;37 _ = 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 {...@@ -9420,4 +9420,132 @@ pub const msghdr_const = extern struct {
9420 control: ?*const anyopaque,9420 control: ?*const anyopaque,
9421 controllen: usize,9421 controllen: usize,
9422 flags: u32,9422 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 @@...@@ -1,4 +1,5 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const assert = std.debug.assert;
23
3/// A protocol is an interface identified by a GUID.4/// A protocol is an interface identified by a GUID.
4pub const protocol = @import("uefi/protocol.zig");5pub const protocol = @import("uefi/protocol.zig");
...@@ -59,31 +60,21 @@ pub const Guid = extern struct {...@@ -59,31 +60,21 @@ pub const Guid = extern struct {
59 node: [6]u8,60 node: [6]u8,
6061
61 /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format62 /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
62 pub fn format(63 pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
63 self: @This(),64 comptime assert(f.len == 0);
64 comptime f: []const u8,65
65 options: std.fmt.FormatOptions,66 const time_low = @byteSwap(self.time_low);
66 writer: anytype,67 const time_mid = @byteSwap(self.time_mid);
67 ) !void {68 const time_high_and_version = @byteSwap(self.time_high_and_version);
68 _ = options;69
69 if (f.len == 0) {70 return std.fmt.format(writer, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
70 const fmt = std.fmt.fmtSliceHexLower;71 std.mem.asBytes(&time_low),
7172 std.mem.asBytes(&time_mid),
72 const time_low = @byteSwap(self.time_low);73 std.mem.asBytes(&time_high_and_version),
73 const time_mid = @byteSwap(self.time_mid);74 std.mem.asBytes(&self.clock_seq_high_and_reserved),
74 const time_high_and_version = @byteSwap(self.time_high_and_version);75 std.mem.asBytes(&self.clock_seq_low),
7576 std.mem.asBytes(&self.node),
76 return std.fmt.format(writer, "{:0>8}-{:0>4}-{:0>4}-{:0>2}{:0>2}-{:0>12}", .{77 });
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 }
87 }78 }
8879
89 pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {80 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 {...@@ -79,30 +79,6 @@ pub const File = extern struct {
79 VolumeFull,79 VolumeFull,
80 };80 };
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
106 pub fn open(82 pub fn open(
107 self: *const File,83 self: *const File,
108 file_name: [*:0]const u16,84 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...@@ -1690,40 +1690,6 @@ pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
1690 return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));1690 return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
1691}1691}
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
1727pub fn poll(fds: [*]ws2_32.pollfd, n: c_ulong, timeout: i32) i32 {1693pub fn poll(fds: [*]ws2_32.pollfd, n: c_ulong, timeout: i32) i32 {
1728 return ws2_32.WSAPoll(fds, n, timeout);1694 return ws2_32.WSAPoll(fds, n, timeout);
1729}1695}
lib/std/os/windows/ws2_32.zig+1-9
...@@ -1829,7 +1829,7 @@ pub extern "ws2_32" fn sendto(...@@ -1829,7 +1829,7 @@ pub extern "ws2_32" fn sendto(
1829 buf: [*]const u8,1829 buf: [*]const u8,
1830 len: i32,1830 len: i32,
1831 flags: i32,1831 flags: i32,
1832 to: *const sockaddr,1832 to: ?*const sockaddr,
1833 tolen: i32,1833 tolen: i32,
1834) callconv(.winapi) i32;1834) callconv(.winapi) i32;
18351835
...@@ -2116,14 +2116,6 @@ pub extern "ws2_32" fn WSASendMsg(...@@ -2116,14 +2116,6 @@ pub extern "ws2_32" fn WSASendMsg(
2116 lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,2116 lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
2117) callconv(.winapi) i32;2117) 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
2127pub extern "ws2_32" fn WSASendDisconnect(2119pub extern "ws2_32" fn WSASendDisconnect(
2128 s: SOCKET,2120 s: SOCKET,
2129 lpOutboundDisconnectData: ?*WSABUF,2121 lpOutboundDisconnectData: ?*WSABUF,
lib/std/posix.zig+1-1
...@@ -651,7 +651,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {...@@ -651,7 +651,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
651 }651 }
652652
653 const file: fs.File = .{ .handle = fd };653 const file: fs.File = .{ .handle = fd };
654 const stream = file.reader();654 const stream = file.deprecatedReader();
655 stream.readNoEof(buf) catch return error.Unexpected;655 stream.readNoEof(buf) catch return error.Unexpected;
656}656}
657657
lib/std/posix/test.zig+1-1
...@@ -667,7 +667,7 @@ test "mmap" {...@@ -667,7 +667,7 @@ test "mmap" {
667 const file = try tmp.dir.createFile(test_out_file, .{});667 const file = try tmp.dir.createFile(test_out_file, .{});
668 defer file.close();668 defer file.close();
669669
670 const stream = file.writer();670 const stream = file.deprecatedWriter();
671671
672 var i: u32 = 0;672 var i: u32 = 0;
673 while (i < alloc_size / @sizeOf(u32)) : (i += 1) {673 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 {...@@ -1553,7 +1553,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
1553 const file = try std.fs.openFileAbsolute("/etc/passwd", .{});1553 const file = try std.fs.openFileAbsolute("/etc/passwd", .{});
1554 defer file.close();1554 defer file.close();
15551555
1556 const reader = file.reader();1556 const reader = file.deprecatedReader();
15571557
1558 const State = enum {1558 const State = enum {
1559 Start,1559 Start,
...@@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap(...@@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap(
1895 var i: usize = 0;1895 var i: usize = 0;
18961896
1897 if (zig_progress_action == .add) {1897 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);
1899 i += 1;1899 i += 1;
1900 }1900 }
19011901
...@@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap(...@@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap(
1906 .add => unreachable,1906 .add => unreachable,
1907 .delete => continue,1907 .delete => continue,
1908 .edit => {1908 .edit => {
1909 envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={d}", .{1909 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={d}", .{
1910 pair.key_ptr.*, options.zig_progress_fd.?,1910 pair.key_ptr.*, options.zig_progress_fd.?,
1911 });1911 }, 0);
1912 i += 1;1912 i += 1;
1913 continue;1913 continue;
1914 },1914 },
1915 .nothing => {},1915 .nothing => {},
1916 };1916 };
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);
1919 i += 1;1919 i += 1;
1920 }1920 }
1921 }1921 }
...@@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting(...@@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting(
1965 var existing_index: usize = 0;1965 var existing_index: usize = 0;
19661966
1967 if (zig_progress_action == .add) {1967 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);
1969 i += 1;1969 i += 1;
1970 }1970 }
19711971
...@@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting(...@@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting(
1974 .add => unreachable,1974 .add => unreachable,
1975 .delete => continue,1975 .delete => continue,
1976 .edit => {1976 .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);
1978 i += 1;1978 i += 1;
1979 continue;1979 continue;
1980 },1980 },
lib/std/process/Child.zig+2-2
...@@ -1004,12 +1004,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {...@@ -1004,12 +1004,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
10041004
1005fn writeIntFd(fd: i32, value: ErrInt) !void {1005fn writeIntFd(fd: i32, value: ErrInt) !void {
1006 const file: File = .{ .handle = fd };1006 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;
1008}1008}
10091009
1010fn readIntFd(fd: i32) !ErrInt {1010fn readIntFd(fd: i32) !ErrInt {
1011 const file: File = .{ .handle = fd };1011 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);
1013}1013}
10141014
1015const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);1015const 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 {...@@ -105,7 +105,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
105 .error_set,105 .error_set,
106 => {106 => {
107 if (actual != expected) {107 if (actual != expected) {
108 print("expected {}, found {}\n", .{ expected, actual });108 print("expected {any}, found {any}\n", .{ expected, actual });
109 return error.TestExpectedEqual;109 return error.TestExpectedEqual;
110 }110 }
111 },111 },
...@@ -267,9 +267,13 @@ test "expectEqual null" {...@@ -267,9 +267,13 @@ test "expectEqual null" {
267267
268/// This function is intended to be used only in tests. When the formatted result of the template268/// This function is intended to be used only in tests. When the formatted result of the template
269/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how269/// 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 printing270/// they are not equal, then returns an error. It depends on `expectEqualStrings` for printing
271/// diagnostics.271/// diagnostics.
272pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {272pub 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 }
273 const actual = try std.fmt.allocPrint(allocator, template, args);277 const actual = try std.fmt.allocPrint(allocator, template, args);
274 defer allocator.free(actual);278 defer allocator.free(actual);
275 return expectEqualStrings(expected, actual);279 return expectEqualStrings(expected, actual);
...@@ -415,7 +419,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -415,7 +419,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
415 print("... truncated ...\n", .{});419 print("... truncated ...\n", .{});
416 }420 }
417 }421 }
418 differ.write(stderr.writer()) catch {};422 differ.write(stderr.deprecatedWriter()) catch {};
419 if (expected_truncated) {423 if (expected_truncated) {
420 const end_offset = window_start + expected_window.len;424 const end_offset = window_start + expected_window.len;
421 const num_missing_items = expected.len - (window_start + expected_window.len);425 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...@@ -437,7 +441,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
437 print("... truncated ...\n", .{});441 print("... truncated ...\n", .{});
438 }442 }
439 }443 }
440 differ.write(stderr.writer()) catch {};444 differ.write(stderr.deprecatedWriter()) catch {};
441 if (actual_truncated) {445 if (actual_truncated) {
442 const end_offset = window_start + actual_window.len;446 const end_offset = window_start + actual_window.len;
443 const num_missing_items = actual.len - (window_start + actual_window.len);447 const num_missing_items = actual.len - (window_start + actual_window.len);
...@@ -637,6 +641,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir {...@@ -637,6 +641,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir {
637641
638pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {642pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
639 if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| {643 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 }
640 print("\n====== expected this output: =========\n", .{});649 print("\n====== expected this output: =========\n", .{});
641 printWithVisibleNewlines(expected);650 printWithVisibleNewlines(expected);
642 print("\n======== instead found this: =========\n", .{});651 print("\n======== instead found this: =========\n", .{});
...@@ -1108,7 +1117,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime...@@ -1108,7 +1117,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
1108 const arg_i_str = comptime str: {1117 const arg_i_str = comptime str: {
1109 var str_buf: [100]u8 = undefined;1118 var str_buf: [100]u8 = undefined;
1110 const args_i = i + 1;1119 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, .{});
1112 break :str str_buf[0..str_len];1121 break :str str_buf[0..str_len];
1113 };1122 };
1114 @field(args, arg_i_str) = @field(extra_args, field.name);1123 @field(args, arg_i_str) = @field(extra_args, field.name);
...@@ -1138,7 +1147,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime...@@ -1138,7 +1147,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
1138 error.OutOfMemory => {1147 error.OutOfMemory => {
1139 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {1148 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
1140 print(1149 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}",
1142 .{1151 .{
1143 fail_index,1152 fail_index,
1144 needed_alloc_count,1153 needed_alloc_count,
lib/std/unicode.zig+23-36
...@@ -9,6 +9,7 @@ const native_endian = builtin.cpu.arch.endian();...@@ -9,6 +9,7 @@ const native_endian = builtin.cpu.arch.endian();
9///9///
10/// See also: https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character10/// See also: https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character
11pub const replacement_character: u21 = 0xFFFD;11pub const replacement_character: u21 = 0xFFFD;
12pub const replacement_character_utf8: [3]u8 = utf8EncodeComptime(replacement_character);
1213
13/// Returns how many bytes the UTF-8 representation would require14/// Returns how many bytes the UTF-8 representation would require
14/// for the given codepoint.15/// for the given codepoint.
...@@ -802,14 +803,7 @@ fn testDecode(bytes: []const u8) !u21 {...@@ -802,14 +803,7 @@ fn testDecode(bytes: []const u8) !u21 {
802/// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD)803/// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD)
803/// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of804/// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of
804/// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder805/// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder
805fn formatUtf8(806fn formatUtf8(utf8: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
806 utf8: []const u8,
807 comptime fmt: []const u8,
808 options: std.fmt.FormatOptions,
809 writer: anytype,
810) !void {
811 _ = fmt;
812 _ = options;
813 var buf: [300]u8 = undefined; // just an arbitrary size807 var buf: [300]u8 = undefined; // just an arbitrary size
814 var u8len: usize = 0;808 var u8len: usize = 0;
815809
...@@ -898,27 +892,27 @@ fn formatUtf8(...@@ -898,27 +892,27 @@ fn formatUtf8(
898/// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD)892/// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD)
899/// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of893/// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of
900/// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder894/// 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) {
902 return .{ .data = utf8 };896 return .{ .data = utf8 };
903}897}
904898
905test fmtUtf8 {899test fmtUtf8 {
906 const expectFmt = testing.expectFmt;900 const expectFmt = testing.expectFmt;
907 try expectFmt("", "{}", .{fmtUtf8("")});901 try expectFmt("", "{f}", .{fmtUtf8("")});
908 try expectFmt("foo", "{}", .{fmtUtf8("foo")});902 try expectFmt("foo", "{f}", .{fmtUtf8("foo")});
909 try expectFmt("𐐷", "{}", .{fmtUtf8("𐐷")});903 try expectFmt("𐐷", "{f}", .{fmtUtf8("𐐷")});
910904
911 // Table 3-8. U+FFFD for Non-Shortest Form Sequences905 // 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
914 // Table 3-9. U+FFFD for Ill-Formed Sequences for Surrogates908 // 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
917 // Table 3-10. U+FFFD for Other Ill-Formed Sequences911 // 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
920 // Table 3-11. U+FFFD for Truncated Sequences914 // 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")});
922}916}
923917
924fn utf16LeToUtf8ArrayListImpl(918fn utf16LeToUtf8ArrayListImpl(
...@@ -1477,14 +1471,7 @@ test calcWtf16LeLen {...@@ -1477,14 +1471,7 @@ test calcWtf16LeLen {
14771471
1478/// Print the given `utf16le` string, encoded as UTF-8 bytes.1472/// Print the given `utf16le` string, encoded as UTF-8 bytes.
1479/// Unpaired surrogates are replaced by the replacement character (U+FFFD).1473/// Unpaired surrogates are replaced by the replacement character (U+FFFD).
1480fn formatUtf16Le(1474fn formatUtf16Le(utf16le: []const u16, writer: *std.io.Writer) std.io.Writer.Error!void {
1481 utf16le: []const u16,
1482 comptime fmt: []const u8,
1483 options: std.fmt.FormatOptions,
1484 writer: anytype,
1485) !void {
1486 _ = fmt;
1487 _ = options;
1488 var buf: [300]u8 = undefined; // just an arbitrary size1475 var buf: [300]u8 = undefined; // just an arbitrary size
1489 var it = Utf16LeIterator.init(utf16le);1476 var it = Utf16LeIterator.init(utf16le);
1490 var u8len: usize = 0;1477 var u8len: usize = 0;
...@@ -1505,23 +1492,23 @@ pub const fmtUtf16le = @compileError("deprecated; renamed to fmtUtf16Le");...@@ -1505,23 +1492,23 @@ pub const fmtUtf16le = @compileError("deprecated; renamed to fmtUtf16Le");
1505/// Return a Formatter for a (potentially ill-formed) UTF-16 LE string,1492/// Return a Formatter for a (potentially ill-formed) UTF-16 LE string,
1506/// which will be converted to UTF-8 during formatting.1493/// which will be converted to UTF-8 during formatting.
1507/// Unpaired surrogates are replaced by the replacement character (U+FFFD).1494/// 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) {
1509 return .{ .data = utf16le };1496 return .{ .data = utf16le };
1510}1497}
15111498
1512test fmtUtf16Le {1499test fmtUtf16Le {
1513 const expectFmt = testing.expectFmt;1500 const expectFmt = testing.expectFmt;
1514 try expectFmt("", "{}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral(""))});1501 try expectFmt("", "{f}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral(""))});
1515 try expectFmt("", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral(""))});1502 try expectFmt("", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral(""))});
1516 try expectFmt("foo", "{}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral("foo"))});1503 try expectFmt("foo", "{f}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral("foo"))});
1517 try expectFmt("foo", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("foo"))});1504 try expectFmt("foo", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("foo"))});
1518 try expectFmt("𐐷", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("𐐷"))});1505 try expectFmt("𐐷", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("𐐷"))});
1519 try expectFmt("퟿", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xd7", native_endian)})});1506 try expectFmt("퟿", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xd7", native_endian)})});
1520 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xd8", native_endian)})});1507 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xd8", native_endian)})});
1521 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdb", native_endian)})});1508 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdb", native_endian)})});
1522 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xdc", native_endian)})});1509 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xdc", native_endian)})});
1523 try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdf", native_endian)})});1510 try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdf", native_endian)})});
1524 try expectFmt("", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xe0", native_endian)})});1511 try expectFmt("", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xe0", native_endian)})});
1525}1512}
15261513
1527fn testUtf8ToUtf16LeStringLiteral(utf8ToUtf16LeStringLiteral_: anytype) !void {1514fn testUtf8ToUtf16LeStringLiteral(utf8ToUtf16LeStringLiteral_: anytype) !void {
lib/std/unicode/throughput_test.zig+1-1
...@@ -39,7 +39,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {...@@ -39,7 +39,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
39}39}
4040
41pub fn main() !void {41pub fn main() !void {
42 const stdout = std.fs.File.stdout().writer();42 const stdout = std.fs.File.stdout().deprecatedWriter();
4343
44 try stdout.print("short ASCII strings\n", .{});44 try stdout.print("short ASCII strings\n", .{});
45 {45 {
lib/std/zig.zig+106-119
...@@ -363,149 +363,136 @@ const Allocator = std.mem.Allocator;...@@ -363,149 +363,136 @@ const Allocator = std.mem.Allocator;
363363
364/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.364/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.
365///365///
366/// - An empty `{}` format specifier escapes invalid identifiers, identifiers that shadow primitives366/// See also `fmtIdFlags`.
367/// and the reserved `_` identifier.367pub fn fmtId(bytes: []const u8) std.fmt.Formatter(FormatId, FormatId.render) {
368/// - Add `p` to the specifier to render identifiers that shadow primitives unescaped.368 return .{ .data = .{ .bytes = bytes, .flags = .{} } };
369/// - Add `_` to the specifier to render the reserved `_` identifier unescaped.369}
370/// - `p` and `_` can be combined, e.g. `{p_}`.370
371/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.
371///372///
372pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) {373/// See also `fmtId`.
373 return .{ .data = bytes };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 } } };
374}384}
375385
376test fmtId {386test fmtId {
377 const expectFmt = std.testing.expectFmt;387 const expectFmt = std.testing.expectFmt;
378 try expectFmt("@\"while\"", "{}", .{fmtId("while")});388 try expectFmt("@\"while\"", "{f}", .{fmtId("while")});
379 try expectFmt("@\"while\"", "{p}", .{fmtId("while")});389 try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_primitive = true })});
380 try expectFmt("@\"while\"", "{_}", .{fmtId("while")});390 try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_underscore = true })});
381 try expectFmt("@\"while\"", "{p_}", .{fmtId("while")});391 try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_primitive = true, .allow_underscore = true })});
382 try expectFmt("@\"while\"", "{_p}", .{fmtId("while")});392
383393 try expectFmt("hello", "{f}", .{fmtId("hello")});
384 try expectFmt("hello", "{}", .{fmtId("hello")});394 try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_primitive = true })});
385 try expectFmt("hello", "{p}", .{fmtId("hello")});395 try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_underscore = true })});
386 try expectFmt("hello", "{_}", .{fmtId("hello")});396 try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_primitive = true, .allow_underscore = true })});
387 try expectFmt("hello", "{p_}", .{fmtId("hello")});397
388 try expectFmt("hello", "{_p}", .{fmtId("hello")});398 try expectFmt("@\"type\"", "{f}", .{fmtId("type")});
389399 try expectFmt("type", "{f}", .{fmtIdFlags("type", .{ .allow_primitive = true })});
390 try expectFmt("@\"type\"", "{}", .{fmtId("type")});400 try expectFmt("@\"type\"", "{f}", .{fmtIdFlags("type", .{ .allow_underscore = true })});
391 try expectFmt("type", "{p}", .{fmtId("type")});401 try expectFmt("type", "{f}", .{fmtIdFlags("type", .{ .allow_primitive = true, .allow_underscore = true })});
392 try expectFmt("@\"type\"", "{_}", .{fmtId("type")});402
393 try expectFmt("type", "{p_}", .{fmtId("type")});403 try expectFmt("@\"_\"", "{f}", .{fmtId("_")});
394 try expectFmt("type", "{_p}", .{fmtId("type")});404 try expectFmt("@\"_\"", "{f}", .{fmtIdFlags("_", .{ .allow_primitive = true })});
395405 try expectFmt("_", "{f}", .{fmtIdFlags("_", .{ .allow_underscore = true })});
396 try expectFmt("@\"_\"", "{}", .{fmtId("_")});406 try expectFmt("_", "{f}", .{fmtIdFlags("_", .{ .allow_primitive = true, .allow_underscore = true })});
397 try expectFmt("@\"_\"", "{p}", .{fmtId("_")});407
398 try expectFmt("_", "{_}", .{fmtId("_")});408 try expectFmt("@\"i123\"", "{f}", .{fmtId("i123")});
399 try expectFmt("_", "{p_}", .{fmtId("_")});409 try expectFmt("i123", "{f}", .{fmtIdFlags("i123", .{ .allow_primitive = true })});
400 try expectFmt("_", "{_p}", .{fmtId("_")});410 try expectFmt("@\"4four\"", "{f}", .{fmtId("4four")});
401411 try expectFmt("_underscore", "{f}", .{fmtId("_underscore")});
402 try expectFmt("@\"i123\"", "{}", .{fmtId("i123")});412 try expectFmt("@\"11\\\"23\"", "{f}", .{fmtId("11\"23")});
403 try expectFmt("i123", "{p}", .{fmtId("i123")});413 try expectFmt("@\"11\\x0f23\"", "{f}", .{fmtId("11\x0F23")});
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")});
408414
409 // These are technically not currently legal in Zig.415 // These are technically not currently legal in Zig.
410 try expectFmt("@\"\"", "{}", .{fmtId("")});416 try expectFmt("@\"\"", "{f}", .{fmtId("")});
411 try expectFmt("@\"\\x00\"", "{}", .{fmtId("\x00")});417 try expectFmt("@\"\\x00\"", "{f}", .{fmtId("\x00")});
412}418}
413419
414/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.420pub const FormatId = struct {
415fn formatId(
416 bytes: []const u8,421 bytes: []const u8,
417 comptime fmt: []const u8,422 flags: Flags,
418 options: std.fmt.FormatOptions,423 pub const Flags = struct {
419 writer: anytype,424 allow_primitive: bool = false,
420) !void {425 allow_underscore: bool = false,
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 };
439 };426 };
440427
441 if (isValidId(bytes) and428 /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
442 (allow_primitive or !std.zig.isPrimitive(bytes)) and429 fn render(ctx: FormatId, writer: *std.io.Writer) std.io.Writer.Error!void {
443 (allow_underscore or !isUnderscore(bytes)))430 const bytes = ctx.bytes;
444 {431 if (isValidId(bytes) and
445 return writer.writeAll(bytes);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('"');
446 }440 }
447 try writer.writeAll("@\"");441};
448 try stringEscape(bytes, "", options, writer);442
449 try writer.writeByte('"');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 };
450}446}
451447
452/// Return a Formatter for Zig Escapes of a double quoted string.448/// Return a formatter for escaping a single quoted Zig string.
453/// The format specifier must be one of:449pub fn fmtChar(bytes: []const u8) std.fmt.Formatter([]const u8, charEscape) {
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) {
457 return .{ .data = bytes };450 return .{ .data = bytes };
458}451}
459452
460test fmtEscapes {453test fmtString {
461 const expectFmt = std.testing.expectFmt;454 try std.testing.expectFmt("\\x0f", "{f}", .{fmtString("\x0f")});
462 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});455 try std.testing.expectFmt(
463 try expectFmt(
464 \\" \\ hi \x07 \x11 " derp \'"
465 , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
466 try expectFmt(
467 \\" \\ hi \x07 \x11 \" derp '"456 \\" \\ hi \x07 \x11 \" derp '"
468 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});457 , "\"{f}\"", .{fmtString(" \\ hi \x07 \x11 \" derp '")});
469}458}
470459
471/// Print the string as escaped contents of a double quoted or single-quoted string.460test fmtChar {
472/// Format `{}` treats contents as a double-quoted string.461 try std.testing.expectFmt(
473/// Format `{'}` treats contents as a single-quoted string.462 \\" \\ hi \x07 \x11 " derp \'"
474pub fn stringEscape(463 , "\"{f}\"", .{fmtChar(" \\ hi \x07 \x11 \" derp '")});
475 bytes: []const u8,464}
476 comptime f: []const u8,465
477 options: std.fmt.FormatOptions,466/// Print the string as escaped contents of a double quoted string.
478 writer: anytype,467pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
479) !void {
480 _ = options;
481 for (bytes) |byte| switch (byte) {468 for (bytes) |byte| switch (byte) {
482 '\n' => try writer.writeAll("\\n"),469 '\n' => try w.writeAll("\\n"),
483 '\r' => try writer.writeAll("\\r"),470 '\r' => try w.writeAll("\\r"),
484 '\t' => try writer.writeAll("\\t"),471 '\t' => try w.writeAll("\\t"),
485 '\\' => try writer.writeAll("\\\\"),472 '\\' => try w.writeAll("\\\\"),
486 '"' => {473 '"' => try w.writeAll("\\\""),
487 if (f.len == 1 and f[0] == '\'') {474 '\'' => try w.writeByte('\''),
488 try writer.writeByte('"');475 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
489 } else if (f.len == 0) {476 else => {
490 try writer.writeAll("\\\"");477 try w.writeAll("\\x");
491 } else {478 try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });
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 }
503 },479 },
504 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),480 };
505 // Use hex escapes for rest any unprintable characters.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),
506 else => {493 else => {
507 try writer.writeAll("\\x");494 try w.writeAll("\\x");
508 try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, writer);495 try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });
509 },496 },
510 };497 };
511}498}
lib/std/zig/Ast.zig+2-2
...@@ -565,14 +565,14 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -565,14 +565,14 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
565565
566 .invalid_byte => {566 .invalid_byte => {
567 const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];567 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}'", .{
569 switch (tok_slice[0]) {569 switch (tok_slice[0]) {
570 '\'' => "character literal",570 '\'' => "character literal",
571 '"', '\\' => "string literal",571 '"', '\\' => "string literal",
572 '/' => "comment",572 '/' => "comment",
573 else => unreachable,573 else => unreachable,
574 },574 },
575 std.zig.fmtEscapes(tok_slice[parse_error.extra.offset..][0..1]),575 std.zig.fmtChar(tok_slice[parse_error.extra.offset..][0..1]),
576 });576 });
577 },577 },
578578
lib/std/zig/ErrorBundle.zig+1-1
...@@ -165,7 +165,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {...@@ -165,7 +165,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {
165 std.debug.lockStdErr();165 std.debug.lockStdErr();
166 defer std.debug.unlockStdErr();166 defer std.debug.unlockStdErr();
167 const stderr: std.fs.File = .stderr();167 const stderr: std.fs.File = .stderr();
168 return renderToWriter(eb, options, stderr.writer()) catch return;168 return renderToWriter(eb, options, stderr.deprecatedWriter()) catch return;
169}169}
170170
171pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void {171pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void {
lib/std/zig/ZonGen.zig+1-7
...@@ -756,13 +756,7 @@ fn lowerStrLitError(...@@ -756,13 +756,7 @@ fn lowerStrLitError(
756 raw_string: []const u8,756 raw_string: []const u8,
757 offset: u32,757 offset: u32,
758) Allocator.Error!void {758) Allocator.Error!void {
759 return ZonGen.addErrorTokOff(759 return ZonGen.addErrorTokOff(zg, token, @intCast(offset + err.offset()), "{f}", .{err.fmt(raw_string)});
760 zg,
761 token,
762 @intCast(offset + err.offset()),
763 "{}",
764 .{err.fmt(raw_string)},
765 );
766}760}
767761
768fn lowerNumberError(zg: *ZonGen, err: std.zig.number_literal.Error, token: Ast.TokenIndex, bytes: []const u8) Allocator.Error!void {762fn 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 @@...@@ -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
1gpa: Allocator,12gpa: Allocator,
2strip: bool,13strip: bool,
314
...@@ -90,31 +101,25 @@ pub const String = enum(u32) {...@@ -90,31 +101,25 @@ pub const String = enum(u32) {
90 const FormatData = struct {101 const FormatData = struct {
91 string: String,102 string: String,
92 builder: *const Builder,103 builder: *const Builder,
104 quote_behavior: ?QuoteBehavior,
93 };105 };
94 fn format(106 fn format(data: FormatData, w: *Writer) Writer.Error!void {
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 ++ "'");
102 assert(data.string != .none);107 assert(data.string != .none);
103 const string_slice = data.string.slice(data.builder) orelse108 const string_slice = data.string.slice(data.builder) orelse
104 return writer.print("{d}", .{@intFromEnum(data.string)});109 return w.print("{d}", .{@intFromEnum(data.string)});
105 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|110 const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice);
106 return writer.writeAll(string_slice);111 return printEscapedString(string_slice, quote_behavior, w);
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 );
115 }112 }
116 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {113 pub fn fmt(
117 return .{ .data = .{ .string = self, .builder = builder } };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 } };
118 }123 }
119124
120 fn fromIndex(index: ?usize) String {125 fn fromIndex(index: ?usize) String {
...@@ -228,7 +233,7 @@ pub const Type = enum(u32) {...@@ -228,7 +233,7 @@ pub const Type = enum(u32) {
228 _,233 _,
229234
230 pub const ptr_amdgpu_constant =235 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
233 pub const Tag = enum(u4) {238 pub const Tag = enum(u4) {
234 simple,239 simple,
...@@ -653,18 +658,16 @@ pub const Type = enum(u32) {...@@ -653,18 +658,16 @@ pub const Type = enum(u32) {
653 const FormatData = struct {658 const FormatData = struct {
654 type: Type,659 type: Type,
655 builder: *const Builder,660 builder: *const Builder,
661 mode: Mode,
662
663 const Mode = enum { default, m, lt, gt, percent };
656 };664 };
657 fn format(665 fn format(data: FormatData, w: *Writer) Writer.Error!void {
658 data: FormatData,
659 comptime fmt_str: []const u8,
660 fmt_opts: std.fmt.FormatOptions,
661 writer: anytype,
662 ) @TypeOf(writer).Error!void {
663 assert(data.type != .none);666 assert(data.type != .none);
664 if (comptime std.mem.eql(u8, fmt_str, "m")) {667 if (data.mode == .m) {
665 const item = data.builder.type_items.items[@intFromEnum(data.type)];668 const item = data.builder.type_items.items[@intFromEnum(data.type)];
666 switch (item.tag) {669 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))) {
668 .void => "isVoid",671 .void => "isVoid",
669 .half => "f16",672 .half => "f16",
670 .bfloat => "bf16",673 .bfloat => "bf16",
...@@ -681,29 +684,29 @@ pub const Type = enum(u32) {...@@ -681,29 +684,29 @@ pub const Type = enum(u32) {
681 .function, .vararg_function => |kind| {684 .function, .vararg_function => |kind| {
682 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);685 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
683 const params = extra.trail.next(extra.data.params_len, Type, data.builder);686 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
684 try writer.print("f_{m}", .{extra.data.ret.fmt(data.builder)});687 try w.print("f_{fm}", .{extra.data.ret.fmt(data.builder)});
685 for (params) |param| try writer.print("{m}", .{param.fmt(data.builder)});688 for (params) |param| try w.print("{fm}", .{param.fmt(data.builder)});
686 switch (kind) {689 switch (kind) {
687 .function => {},690 .function => {},
688 .vararg_function => try writer.writeAll("vararg"),691 .vararg_function => try w.writeAll("vararg"),
689 else => unreachable,692 else => unreachable,
690 }693 }
691 try writer.writeByte('f');694 try w.writeByte('f');
692 },695 },
693 .integer => try writer.print("i{d}", .{item.data}),696 .integer => try w.print("i{d}", .{item.data}),
694 .pointer => try writer.print("p{d}", .{item.data}),697 .pointer => try w.print("p{d}", .{item.data}),
695 .target => {698 .target => {
696 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);699 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
697 const types = extra.trail.next(extra.data.types_len, Type, data.builder);700 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
698 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);701 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
699 try writer.print("t{s}", .{extra.data.name.slice(data.builder).?});702 try w.print("t{s}", .{extra.data.name.slice(data.builder).?});
700 for (types) |ty| try writer.print("_{m}", .{ty.fmt(data.builder)});703 for (types) |ty| try w.print("_{fm}", .{ty.fmt(data.builder)});
701 for (ints) |int| try writer.print("_{d}", .{int});704 for (ints) |int| try w.print("_{d}", .{int});
702 try writer.writeByte('t');705 try w.writeByte('t');
703 },706 },
704 .vector, .scalable_vector => |kind| {707 .vector, .scalable_vector => |kind| {
705 const extra = data.builder.typeExtraData(Type.Vector, item.data);708 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}", .{
707 switch (kind) {710 switch (kind) {
708 .vector => "",711 .vector => "",
709 .scalable_vector => "nx",712 .scalable_vector => "nx",
...@@ -719,65 +722,65 @@ pub const Type = enum(u32) {...@@ -719,65 +722,65 @@ pub const Type = enum(u32) {
719 .array => Type.Array,722 .array => Type.Array,
720 else => unreachable,723 else => unreachable,
721 }, item.data);724 }, 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) });
723 },726 },
724 .structure, .packed_structure => {727 .structure, .packed_structure => {
725 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);728 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
726 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);729 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
727 try writer.writeAll("sl_");730 try w.writeAll("sl_");
728 for (fields) |field| try writer.print("{m}", .{field.fmt(data.builder)});731 for (fields) |field| try w.print("{fm}", .{field.fmt(data.builder)});
729 try writer.writeByte('s');732 try w.writeByte('s');
730 },733 },
731 .named_structure => {734 .named_structure => {
732 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);735 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
733 try writer.writeAll("s_");736 try w.writeAll("s_");
734 if (extra.id.slice(data.builder)) |id| try writer.writeAll(id);737 if (extra.id.slice(data.builder)) |id| try w.writeAll(id);
735 },738 },
736 }739 }
737 return;740 return;
738 }741 }
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);
740 const item = data.builder.type_items.items[@intFromEnum(data.type)];743 const item = data.builder.type_items.items[@intFromEnum(data.type)];
741 switch (item.tag) {744 switch (item.tag) {
742 .simple => unreachable,745 .simple => unreachable,
743 .function, .vararg_function => |kind| {746 .function, .vararg_function => |kind| {
744 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);747 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
745 const params = extra.trail.next(extra.data.params_len, Type, data.builder);748 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
746 if (!comptime std.mem.eql(u8, fmt_str, ">"))749 if (data.mode != .gt)
747 try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)});750 try w.print("{f%} ", .{extra.data.ret.fmt(data.builder)});
748 if (!comptime std.mem.eql(u8, fmt_str, "<")) {751 if (data.mode != .lt) {
749 try writer.writeByte('(');752 try w.writeByte('(');
750 for (params, 0..) |param, index| {753 for (params, 0..) |param, index| {
751 if (index > 0) try writer.writeAll(", ");754 if (index > 0) try w.writeAll(", ");
752 try writer.print("{%}", .{param.fmt(data.builder)});755 try w.print("{f%}", .{param.fmt(data.builder)});
753 }756 }
754 switch (kind) {757 switch (kind) {
755 .function => {},758 .function => {},
756 .vararg_function => {759 .vararg_function => {
757 if (params.len > 0) try writer.writeAll(", ");760 if (params.len > 0) try w.writeAll(", ");
758 try writer.writeAll("...");761 try w.writeAll("...");
759 },762 },
760 else => unreachable,763 else => unreachable,
761 }764 }
762 try writer.writeByte(')');765 try w.writeByte(')');
763 }766 }
764 },767 },
765 .integer => try writer.print("i{d}", .{item.data}),768 .integer => try w.print("i{d}", .{item.data}),
766 .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}),769 .pointer => try w.print("ptr{f }", .{@as(AddrSpace, @enumFromInt(item.data))}),
767 .target => {770 .target => {
768 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);771 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
769 const types = extra.trail.next(extra.data.types_len, Type, data.builder);772 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
770 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);773 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
771 try writer.print(774 try w.print(
772 \\target({"}775 \\target({f"}
773 , .{extra.data.name.fmt(data.builder)});776 , .{extra.data.name.fmt(data.builder)});
774 for (types) |ty| try writer.print(", {%}", .{ty.fmt(data.builder)});777 for (types) |ty| try w.print(", {f%}", .{ty.fmt(data.builder)});
775 for (ints) |int| try writer.print(", {d}", .{int});778 for (ints) |int| try w.print(", {d}", .{int});
776 try writer.writeByte(')');779 try w.writeByte(')');
777 },780 },
778 .vector, .scalable_vector => |kind| {781 .vector, .scalable_vector => |kind| {
779 const extra = data.builder.typeExtraData(Type.Vector, item.data);782 const extra = data.builder.typeExtraData(Type.Vector, item.data);
780 try writer.print("<{s}{d} x {%}>", .{783 try w.print("<{s}{d} x {f%}>", .{
781 switch (kind) {784 switch (kind) {
782 .vector => "",785 .vector => "",
783 .scalable_vector => "vscale x ",786 .scalable_vector => "vscale x ",
...@@ -793,44 +796,45 @@ pub const Type = enum(u32) {...@@ -793,44 +796,45 @@ pub const Type = enum(u32) {
793 .array => Type.Array,796 .array => Type.Array,
794 else => unreachable,797 else => unreachable,
795 }, item.data);798 }, 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) });
797 },800 },
798 .structure, .packed_structure => |kind| {801 .structure, .packed_structure => |kind| {
799 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);802 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
800 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);803 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
801 switch (kind) {804 switch (kind) {
802 .structure => {},805 .structure => {},
803 .packed_structure => try writer.writeByte('<'),806 .packed_structure => try w.writeByte('<'),
804 else => unreachable,807 else => unreachable,
805 }808 }
806 try writer.writeAll("{ ");809 try w.writeAll("{ ");
807 for (fields, 0..) |field, index| {810 for (fields, 0..) |field, index| {
808 if (index > 0) try writer.writeAll(", ");811 if (index > 0) try w.writeAll(", ");
809 try writer.print("{%}", .{field.fmt(data.builder)});812 try w.print("{f%}", .{field.fmt(data.builder)});
810 }813 }
811 try writer.writeAll(" }");814 try w.writeAll(" }");
812 switch (kind) {815 switch (kind) {
813 .structure => {},816 .structure => {},
814 .packed_structure => try writer.writeByte('>'),817 .packed_structure => try w.writeByte('>'),
815 else => unreachable,818 else => unreachable,
816 }819 }
817 },820 },
818 .named_structure => {821 .named_structure => {
819 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);822 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}", .{
821 extra.id.fmt(data.builder),824 extra.id.fmt(data.builder),
822 }) else switch (extra.body) {825 }) else switch (extra.body) {
823 .none => try writer.writeAll("opaque"),826 .none => try w.writeAll("opaque"),
824 else => try format(.{827 else => try format(.{
825 .type = extra.body,828 .type = extra.body,
826 .builder = data.builder,829 .builder = data.builder,
827 }, fmt_str, fmt_opts, writer),830 .mode = data.mode,
831 }, w),
828 }832 }
829 },833 },
830 }834 }
831 }835 }
832 pub fn fmt(self: Type, builder: *const Builder) std.fmt.Formatter(format) {836 pub fn fmt(self: Type, builder: *const Builder, mode: FormatData.Mode) std.fmt.Formatter(FormatData, format) {
833 return .{ .data = .{ .type = self, .builder = builder } };837 return .{ .data = .{ .type = self, .builder = builder, .mode = mode } };
834 }838 }
835839
836 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);840 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);
...@@ -1138,15 +1142,10 @@ pub const Attribute = union(Kind) {...@@ -1138,15 +1142,10 @@ pub const Attribute = union(Kind) {
1138 const FormatData = struct {1142 const FormatData = struct {
1139 attribute_index: Index,1143 attribute_index: Index,
1140 builder: *const Builder,1144 builder: *const Builder,
1145 mode: Mode,
1146 const Mode = enum { default, quote, pound };
1141 };1147 };
1142 fn format(1148 fn format(data: FormatData, w: *Writer) Writer.Error!void {
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 ++ "'");
1150 const attribute = data.attribute_index.toAttribute(data.builder);1149 const attribute = data.attribute_index.toAttribute(data.builder);
1151 switch (attribute) {1150 switch (attribute) {
1152 .zeroext,1151 .zeroext,
...@@ -1219,97 +1218,94 @@ pub const Attribute = union(Kind) {...@@ -1219,97 +1218,94 @@ pub const Attribute = union(Kind) {
1219 .no_sanitize_address,1218 .no_sanitize_address,
1220 .no_sanitize_hwaddress,1219 .no_sanitize_hwaddress,
1221 .sanitize_address_dyninit,1220 .sanitize_address_dyninit,
1222 => try writer.print(" {s}", .{@tagName(attribute)}),1221 => try w.print(" {s}", .{@tagName(attribute)}),
1223 .byval,1222 .byval,
1224 .byref,1223 .byref,
1225 .preallocated,1224 .preallocated,
1226 .inalloca,1225 .inalloca,
1227 .sret,1226 .sret,
1228 .elementtype,1227 .elementtype,
1229 => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),1228 => |ty| try w.print(" {s}({f%})", .{ @tagName(attribute), ty.fmt(data.builder) }),
1230 .@"align" => |alignment| try writer.print("{ }", .{alignment}),1229 .@"align" => |alignment| try w.print("{f }", .{alignment}),
1231 .dereferenceable,1230 .dereferenceable,
1232 .dereferenceable_or_null,1231 .dereferenceable_or_null,
1233 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),1232 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
1234 .nofpclass => |fpclass| {1233 .nofpclass => |fpclass| {
1235 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;1234 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
1236 try writer.print(" {s}(", .{@tagName(attribute)});1235 try w.print(" {s}(", .{@tagName(attribute)});
1237 var any = false;1236 var any = false;
1238 var remaining: Int = @bitCast(fpclass);1237 var remaining: Int = @bitCast(fpclass);
1239 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {1238 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {
1240 const pattern: Int = @bitCast(@field(FpClass, decl.name));1239 const pattern: Int = @bitCast(@field(FpClass, decl.name));
1241 if (remaining & pattern == pattern) {1240 if (remaining & pattern == pattern) {
1242 if (!any) {1241 if (!any) {
1243 try writer.writeByte(' ');1242 try w.writeByte(' ');
1244 any = true;1243 any = true;
1245 }1244 }
1246 try writer.writeAll(decl.name);1245 try w.writeAll(decl.name);
1247 remaining &= ~pattern;1246 remaining &= ~pattern;
1248 }1247 }
1249 }1248 }
1250 try writer.writeByte(')');1249 try w.writeByte(')');
1251 },1250 },
1252 .alignstack => |alignment| try writer.print(1251 .alignstack => |alignment| try w.print(
1253 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)1252 if (data.mode == .pound) " {s}={d}" else " {s}({d})",
1254 " {s}={d}"
1255 else
1256 " {s}({d})",
1257 .{ @tagName(attribute), alignment.toByteUnits() orelse return },1253 .{ @tagName(attribute), alignment.toByteUnits() orelse return },
1258 ),1254 ),
1259 .allockind => |allockind| {1255 .allockind => |allockind| {
1260 try writer.print(" {s}(\"", .{@tagName(attribute)});1256 try w.print(" {s}(\"", .{@tagName(attribute)});
1261 var any = false;1257 var any = false;
1262 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {1258 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {
1263 if (comptime std.mem.eql(u8, field.name, "_")) continue;1259 if (comptime std.mem.eql(u8, field.name, "_")) continue;
1264 if (@field(allockind, field.name)) {1260 if (@field(allockind, field.name)) {
1265 if (!any) {1261 if (!any) {
1266 try writer.writeByte(',');1262 try w.writeByte(',');
1267 any = true;1263 any = true;
1268 }1264 }
1269 try writer.writeAll(field.name);1265 try w.writeAll(field.name);
1270 }1266 }
1271 }1267 }
1272 try writer.writeAll("\")");1268 try w.writeAll("\")");
1273 },1269 },
1274 .allocsize => |allocsize| {1270 .allocsize => |allocsize| {
1275 try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });1271 try w.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
1276 if (allocsize.num_elems != AllocSize.none)1272 if (allocsize.num_elems != AllocSize.none)
1277 try writer.print(",{d}", .{allocsize.num_elems});1273 try w.print(",{d}", .{allocsize.num_elems});
1278 try writer.writeByte(')');1274 try w.writeByte(')');
1279 },1275 },
1280 .memory => |memory| {1276 .memory => |memory| {
1281 try writer.print(" {s}(", .{@tagName(attribute)});1277 try w.print(" {s}(", .{@tagName(attribute)});
1282 var any = memory.other != .none or1278 var any = memory.other != .none or
1283 (memory.argmem == .none and memory.inaccessiblemem == .none);1279 (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));
1285 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {1281 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
1286 if (@field(memory, kind) != memory.other) {1282 if (@field(memory, kind) != memory.other) {
1287 if (any) try writer.writeAll(", ");1283 if (any) try w.writeAll(", ");
1288 try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });1284 try w.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
1289 any = true;1285 any = true;
1290 }1286 }
1291 }1287 }
1292 try writer.writeByte(')');1288 try w.writeByte(')');
1293 },1289 },
1294 .uwtable => |uwtable| if (uwtable != .none) {1290 .uwtable => |uwtable| if (uwtable != .none) {
1295 try writer.print(" {s}", .{@tagName(attribute)});1291 try w.print(" {s}", .{@tagName(attribute)});
1296 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});1292 if (uwtable != UwTable.default) try w.print("({s})", .{@tagName(uwtable)});
1297 },1293 },
1298 .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{1294 .vscale_range => |vscale_range| try w.print(" {s}({d},{d})", .{
1299 @tagName(attribute),1295 @tagName(attribute),
1300 vscale_range.min.toByteUnits().?,1296 vscale_range.min.toByteUnits().?,
1301 vscale_range.max.toByteUnits() orelse 0,1297 vscale_range.max.toByteUnits() orelse 0,
1302 }),1298 }),
1303 .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) {1299 .string => |string_attr| if (data.mode == .quote) {
1304 try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)});1300 try w.print(" {f\"}", .{string_attr.kind.fmt(data.builder)});
1305 if (string_attr.value != .empty)1301 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)});
1307 },1303 },
1308 .none => unreachable,1304 .none => unreachable,
1309 }1305 }
1310 }1306 }
1311 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {1307 pub fn fmt(self: Index, builder: *const Builder, mode: FormatData.mode) std.fmt.Formatter(FormatData, format) {
1312 return .{ .data = .{ .attribute_index = self, .builder = builder } };1308 return .{ .data = .{ .attribute_index = self, .builder = builder, .mode = mode } };
1313 }1309 }
13141310
1315 fn toStorage(self: Index, builder: *const Builder) Storage {1311 fn toStorage(self: Index, builder: *const Builder) Storage {
...@@ -1583,18 +1579,13 @@ pub const Attributes = enum(u32) {...@@ -1583,18 +1579,13 @@ pub const Attributes = enum(u32) {
1583 attributes: Attributes,1579 attributes: Attributes,
1584 builder: *const Builder,1580 builder: *const Builder,
1585 };1581 };
1586 fn format(1582 fn format(data: FormatData, w: *Writer) Writer.Error!void {
1587 data: FormatData,
1588 comptime fmt_str: []const u8,
1589 fmt_opts: std.fmt.FormatOptions,
1590 writer: anytype,
1591 ) @TypeOf(writer).Error!void {
1592 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{1583 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{
1593 .attribute_index = attribute_index,1584 .attribute_index = attribute_index,
1594 .builder = data.builder,1585 .builder = data.builder,
1595 }, fmt_str, fmt_opts, writer);1586 }, w);
1596 }1587 }
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) {
1598 return .{ .data = .{ .attributes = self, .builder = builder } };1589 return .{ .data = .{ .attributes = self, .builder = builder } };
1599 }1590 }
1600};1591};
...@@ -1781,24 +1772,15 @@ pub const Linkage = enum(u4) {...@@ -1781,24 +1772,15 @@ pub const Linkage = enum(u4) {
1781 extern_weak = 7,1772 extern_weak = 7,
1782 external = 0,1773 external = 0,
17831774
1784 pub fn format(1775 pub fn format(self: Linkage, w: *Writer, comptime f: []const u8) Writer.Error!void {
1785 self: Linkage,1776 comptime assert(f.len == 0);
1786 comptime _: []const u8,1777 if (self != .external) try w.print(" {s}", .{@tagName(self)});
1787 _: std.fmt.FormatOptions,
1788 writer: anytype,
1789 ) @TypeOf(writer).Error!void {
1790 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1791 }1778 }
17921779
1793 fn formatOptional(1780 fn formatOptional(data: ?Linkage, w: *Writer) Writer.Error!void {
1794 data: ?Linkage,1781 if (data) |linkage| try w.print(" {s}", .{@tagName(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)});
1800 }1782 }
1801 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {1783 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(?Linkage, formatOptional) {
1802 return .{ .data = self };1784 return .{ .data = self };
1803 }1785 }
1804};1786};
...@@ -1808,13 +1790,8 @@ pub const Preemption = enum {...@@ -1808,13 +1790,8 @@ pub const Preemption = enum {
1808 dso_local,1790 dso_local,
1809 implicit_dso_local,1791 implicit_dso_local,
18101792
1811 pub fn format(1793 pub fn format(self: Preemption, w: *Writer, comptime _: []const u8) Writer.Error!void {
1812 self: Preemption,1794 if (self == .dso_local) try w.print(" {s}", .{@tagName(self)});
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)});
1818 }1795 }
1819};1796};
18201797
...@@ -1831,12 +1808,8 @@ pub const Visibility = enum(u2) {...@@ -1831,12 +1808,8 @@ pub const Visibility = enum(u2) {
1831 };1808 };
1832 }1809 }
18331810
1834 pub fn format(1811 pub fn format(self: Visibility, comptime format_string: []const u8, writer: *Writer) Writer.Error!void {
1835 self: Visibility,1812 comptime assert(format_string.len == 0);
1836 comptime _: []const u8,
1837 _: std.fmt.FormatOptions,
1838 writer: anytype,
1839 ) @TypeOf(writer).Error!void {
1840 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1813 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1841 }1814 }
1842};1815};
...@@ -1846,13 +1819,8 @@ pub const DllStorageClass = enum(u2) {...@@ -1846,13 +1819,8 @@ pub const DllStorageClass = enum(u2) {
1846 dllimport = 1,1819 dllimport = 1,
1847 dllexport = 2,1820 dllexport = 2,
18481821
1849 pub fn format(1822 pub fn format(self: DllStorageClass, w: *Writer, comptime _: []const u8) Writer.Error!void {
1850 self: DllStorageClass,1823 if (self != .default) try w.print(" {s}", .{@tagName(self)});
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)});
1856 }1824 }
1857};1825};
18581826
...@@ -1863,15 +1831,10 @@ pub const ThreadLocal = enum(u3) {...@@ -1863,15 +1831,10 @@ pub const ThreadLocal = enum(u3) {
1863 initialexec = 3,1831 initialexec = 3,
1864 localexec = 4,1832 localexec = 4,
18651833
1866 pub fn format(1834 pub fn format(self: ThreadLocal, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
1867 self: ThreadLocal,
1868 comptime prefix: []const u8,
1869 _: std.fmt.FormatOptions,
1870 writer: anytype,
1871 ) @TypeOf(writer).Error!void {
1872 if (self == .default) return;1835 if (self == .default) return;
1873 try writer.print("{s}thread_local", .{prefix});1836 try w.print("{s}thread_local", .{prefix});
1874 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});1837 if (self != .generaldynamic) try w.print("({s})", .{@tagName(self)});
1875 }1838 }
1876};1839};
18771840
...@@ -1882,13 +1845,8 @@ pub const UnnamedAddr = enum(u2) {...@@ -1882,13 +1845,8 @@ pub const UnnamedAddr = enum(u2) {
1882 unnamed_addr = 1,1845 unnamed_addr = 1,
1883 local_unnamed_addr = 2,1846 local_unnamed_addr = 2,
18841847
1885 pub fn format(1848 pub fn format(self: UnnamedAddr, w: *Writer, comptime _: []const u8) Writer.Error!void {
1886 self: UnnamedAddr,1849 if (self != .default) try w.print(" {s}", .{@tagName(self)});
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)});
1892 }1850 }
1893};1851};
18941852
...@@ -1981,13 +1939,8 @@ pub const AddrSpace = enum(u24) {...@@ -1981,13 +1939,8 @@ pub const AddrSpace = enum(u24) {
1981 pub const funcref: AddrSpace = @enumFromInt(20);1939 pub const funcref: AddrSpace = @enumFromInt(20);
1982 };1940 };
19831941
1984 pub fn format(1942 pub fn format(self: AddrSpace, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
1985 self: AddrSpace,1943 if (self != .default) try w.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
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) });
1991 }1944 }
1992};1945};
19931946
...@@ -1995,15 +1948,8 @@ pub const ExternallyInitialized = enum {...@@ -1995,15 +1948,8 @@ pub const ExternallyInitialized = enum {
1995 default,1948 default,
1996 externally_initialized,1949 externally_initialized,
19971950
1998 pub fn format(1951 pub fn format(self: ExternallyInitialized, w: *Writer, comptime _: []const u8) Writer.Error!void {
1999 self: ExternallyInitialized,1952 if (self != .default) try w.print(" {s}", .{@tagName(self)});
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));
2007 }1953 }
2008};1954};
20091955
...@@ -2026,13 +1972,8 @@ pub const Alignment = enum(u6) {...@@ -2026,13 +1972,8 @@ pub const Alignment = enum(u6) {
2026 return if (self == .default) 0 else (@intFromEnum(self) + 1);1972 return if (self == .default) 0 else (@intFromEnum(self) + 1);
2027 }1973 }
20281974
2029 pub fn format(1975 pub fn format(self: Alignment, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
2030 self: Alignment,1976 try w.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
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 });
2036 }1977 }
2037};1978};
20381979
...@@ -2105,12 +2046,7 @@ pub const CallConv = enum(u10) {...@@ -2105,12 +2046,7 @@ pub const CallConv = enum(u10) {
21052046
2106 pub const default = CallConv.ccc;2047 pub const default = CallConv.ccc;
21072048
2108 pub fn format(2049 pub fn format(self: CallConv, w: *Writer, comptime _: []const u8) Writer.Error!void {
2109 self: CallConv,
2110 comptime _: []const u8,
2111 _: std.fmt.FormatOptions,
2112 writer: anytype,
2113 ) @TypeOf(writer).Error!void {
2114 switch (self) {2050 switch (self) {
2115 default => {},2051 default => {},
2116 .fastcc,2052 .fastcc,
...@@ -2164,8 +2100,8 @@ pub const CallConv = enum(u10) {...@@ -2164,8 +2100,8 @@ pub const CallConv = enum(u10) {
2164 .aarch64_sme_preservemost_from_x2,2100 .aarch64_sme_preservemost_from_x2,
2165 .m68k_rtdcc,2101 .m68k_rtdcc,
2166 .riscv_vectorcallcc,2102 .riscv_vectorcallcc,
2167 => try writer.print(" {s}", .{@tagName(self)}),2103 => try w.print(" {s}", .{@tagName(self)}),
2168 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2104 _ => try w.print(" cc{d}", .{@intFromEnum(self)}),
2169 }2105 }
2170 }2106 }
2171};2107};
...@@ -2190,31 +2126,25 @@ pub const StrtabString = enum(u32) {...@@ -2190,31 +2126,25 @@ pub const StrtabString = enum(u32) {
2190 const FormatData = struct {2126 const FormatData = struct {
2191 string: StrtabString,2127 string: StrtabString,
2192 builder: *const Builder,2128 builder: *const Builder,
2129 quote_behavior: ?QuoteBehavior,
2193 };2130 };
2194 fn format(2131 fn format(data: FormatData, w: *Writer) Writer.Error!void {
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 ++ "'");
2202 assert(data.string != .none);2132 assert(data.string != .none);
2203 const string_slice = data.string.slice(data.builder) orelse2133 const string_slice = data.string.slice(data.builder) orelse
2204 return writer.print("{d}", .{@intFromEnum(data.string)});2134 return w.print("{d}", .{@intFromEnum(data.string)});
2205 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|2135 const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice);
2206 return writer.writeAll(string_slice);2136 return printEscapedString(string_slice, quote_behavior, w);
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 );
2215 }2137 }
2216 pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) {2138 pub fn fmt(
2217 return .{ .data = .{ .string = self, .builder = builder } };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 } };
2218 }2148 }
22192149
2220 fn fromIndex(index: ?usize) StrtabString {2150 fn fromIndex(index: ?usize) StrtabString {
...@@ -2264,7 +2194,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a...@@ -2264,7 +2194,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a
2264}2194}
22652195
2266pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString {2196pub 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);
2268 return self.trailingStrtabStringAssumeCapacity();2198 return self.trailingStrtabStringAssumeCapacity();
2269}2199}
22702200
...@@ -2383,17 +2313,12 @@ pub const Global = struct {...@@ -2383,17 +2313,12 @@ pub const Global = struct {
2383 global: Index,2313 global: Index,
2384 builder: *const Builder,2314 builder: *const Builder,
2385 };2315 };
2386 fn format(2316 fn format(data: FormatData, w: *Writer) Writer.Error!void {
2387 data: FormatData,2317 try w.print("@{f}", .{
2388 comptime _: []const u8,
2389 _: std.fmt.FormatOptions,
2390 writer: anytype,
2391 ) @TypeOf(writer).Error!void {
2392 try writer.print("@{}", .{
2393 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),2318 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),
2394 });2319 });
2395 }2320 }
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) {
2397 return .{ .data = .{ .global = self, .builder = builder } };2322 return .{ .data = .{ .global = self, .builder = builder } };
2398 }2323 }
23992324
...@@ -4833,29 +4758,28 @@ pub const Function = struct {...@@ -4833,29 +4758,28 @@ pub const Function = struct {
4833 instruction: Instruction.Index,4758 instruction: Instruction.Index,
4834 function: Function.Index,4759 function: Function.Index,
4835 builder: *Builder,4760 builder: *Builder,
4761 flags: Flags,
4762 const Flags = struct {
4763 comma: bool = false,
4764 space: bool = false,
4765 percent: bool = false,
4766 };
4836 };4767 };
4837 fn format(4768 fn format(data: FormatData, w: *Writer) Writer.Error!void {
4838 data: FormatData,4769 if (data.flags.comma) {
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) {
4846 if (data.instruction == .none) return;4770 if (data.instruction == .none) return;
4847 try writer.writeByte(',');4771 try w.writeByte(',');
4848 }4772 }
4849 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {4773 if (data.flags.space) {
4850 if (data.instruction == .none) return;4774 if (data.instruction == .none) return;
4851 try writer.writeByte(' ');4775 try w.writeByte(' ');
4852 }4776 }
4853 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null) try writer.print(4777 if (data.flags.percent) try w.print(
4854 "{%} ",4778 "{f%} ",
4855 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},4779 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},
4856 );4780 );
4857 assert(data.instruction != .none);4781 assert(data.instruction != .none);
4858 try writer.print("%{}", .{4782 try w.print("%{f}", .{
4859 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),4783 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),
4860 });4784 });
4861 }4785 }
...@@ -4863,8 +4787,14 @@ pub const Function = struct {...@@ -4863,8 +4787,14 @@ pub const Function = struct {
4863 self: Instruction.Index,4787 self: Instruction.Index,
4864 function: Function.Index,4788 function: Function.Index,
4865 builder: *Builder,4789 builder: *Builder,
4866 ) std.fmt.Formatter(format) {4790 flags: FormatData.Flags,
4867 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };4791 ) std.fmt.Formatter(FormatData, format) {
4792 return .{ .data = .{
4793 .instruction = self,
4794 .function = function,
4795 .builder = builder,
4796 .flags = flags,
4797 } };
4868 }4798 }
4869 };4799 };
48704800
...@@ -6361,7 +6291,7 @@ pub const WipFunction = struct {...@@ -6361,7 +6291,7 @@ pub const WipFunction = struct {
63616291
6362 while (true) {6292 while (true) {
6363 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);6293 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}", .{
6365 name.fmt(wip_name.builder),6295 name.fmt(wip_name.builder),
6366 sep,6296 sep,
6367 gop.value_ptr.fmt(wip_name.builder),6297 gop.value_ptr.fmt(wip_name.builder),
...@@ -7031,13 +6961,8 @@ pub const MemoryAccessKind = enum(u1) {...@@ -7031,13 +6961,8 @@ pub const MemoryAccessKind = enum(u1) {
7031 normal,6961 normal,
7032 @"volatile",6962 @"volatile",
70336963
7034 pub fn format(6964 pub fn format(self: MemoryAccessKind, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
7035 self: MemoryAccessKind,6965 if (self != .normal) try w.print("{s}{s}", .{ prefix, @tagName(self) });
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) });
7041 }6966 }
7042};6967};
70436968
...@@ -7045,13 +6970,8 @@ pub const SyncScope = enum(u1) {...@@ -7045,13 +6970,8 @@ pub const SyncScope = enum(u1) {
7045 singlethread,6970 singlethread,
7046 system,6971 system,
70476972
7048 pub fn format(6973 pub fn format(self: SyncScope, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
7049 self: SyncScope,6974 if (self != .system) try w.print(
7050 comptime prefix: []const u8,
7051 _: std.fmt.FormatOptions,
7052 writer: anytype,
7053 ) @TypeOf(writer).Error!void {
7054 if (self != .system) try writer.print(
7055 \\{s}syncscope("{s}")6975 \\{s}syncscope("{s}")
7056 , .{ prefix, @tagName(self) });6976 , .{ prefix, @tagName(self) });
7057 }6977 }
...@@ -7066,13 +6986,8 @@ pub const AtomicOrdering = enum(u3) {...@@ -7066,13 +6986,8 @@ pub const AtomicOrdering = enum(u3) {
7066 acq_rel = 5,6986 acq_rel = 5,
7067 seq_cst = 6,6987 seq_cst = 6,
70686988
7069 pub fn format(6989 pub fn format(self: AtomicOrdering, w: *Writer, comptime prefix: []const u8) Writer.Error!void {
7070 self: AtomicOrdering,6990 if (self != .none) try w.print("{s}{s}", .{ prefix, @tagName(self) });
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) });
7076 }6991 }
7077};6992};
70786993
...@@ -7486,27 +7401,26 @@ pub const Constant = enum(u32) {...@@ -7486,27 +7401,26 @@ pub const Constant = enum(u32) {
7486 const FormatData = struct {7401 const FormatData = struct {
7487 constant: Constant,7402 constant: Constant,
7488 builder: *Builder,7403 builder: *Builder,
7404 flags: Flags,
7405 const Flags = struct {
7406 comma: bool = false,
7407 space: bool = false,
7408 percent: bool = false,
7409 };
7489 };7410 };
7490 fn format(7411 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7491 data: FormatData,7412 if (data.flags.comma) {
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) {
7499 if (data.constant == .no_init) return;7413 if (data.constant == .no_init) return;
7500 try writer.writeByte(',');7414 try w.writeByte(',');
7501 }7415 }
7502 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {7416 if (data.flags.space) {
7503 if (data.constant == .no_init) return;7417 if (data.constant == .no_init) return;
7504 try writer.writeByte(' ');7418 try w.writeByte(' ');
7505 }7419 }
7506 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null)7420 if (data.flags.percent)
7507 try writer.print("{%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});7421 try w.print("{f%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});
7508 assert(data.constant != .no_init);7422 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);
7510 switch (data.constant.unwrap()) {7424 switch (data.constant.unwrap()) {
7511 .constant => |constant| {7425 .constant => |constant| {
7512 const item = data.builder.constant_items.get(constant);7426 const item = data.builder.constant_items.get(constant);
...@@ -7545,11 +7459,11 @@ pub const Constant = enum(u32) {...@@ -7545,11 +7459,11 @@ pub const Constant = enum(u32) {
7545 const allocator = stack.get();7459 const allocator = stack.get();
7546 const str = try bigint.toStringAlloc(allocator, 10, undefined);7460 const str = try bigint.toStringAlloc(allocator, 10, undefined);
7547 defer allocator.free(str);7461 defer allocator.free(str);
7548 try writer.writeAll(str);7462 try w.writeAll(str);
7549 },7463 },
7550 .half,7464 .half,
7551 .bfloat,7465 .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) {
7553 .half => 'H',7467 .half => 'H',
7554 .bfloat => 'R',7468 .bfloat => 'R',
7555 else => unreachable,7469 else => unreachable,
...@@ -7580,7 +7494,7 @@ pub const Constant = enum(u32) {...@@ -7580,7 +7494,7 @@ pub const Constant = enum(u32) {
7580 ) + 1,7494 ) + 1,
7581 else => 0,7495 else => 0,
7582 };7496 };
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){
7584 .mantissa = std.math.shl(7498 .mantissa = std.math.shl(
7585 Mantissa64,7499 Mantissa64,
7586 repr.mantissa,7500 repr.mantissa,
...@@ -7602,13 +7516,13 @@ pub const Constant = enum(u32) {...@@ -7602,13 +7516,13 @@ pub const Constant = enum(u32) {
7602 },7516 },
7603 .double => {7517 .double => {
7604 const extra = data.builder.constantExtraData(Double, item.data);7518 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 });
7606 },7520 },
7607 .fp128,7521 .fp128,
7608 .ppc_fp128,7522 .ppc_fp128,
7609 => |tag| {7523 => |tag| {
7610 const extra = data.builder.constantExtraData(Fp128, item.data);7524 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}", .{
7612 @as(u8, switch (tag) {7526 @as(u8, switch (tag) {
7613 .fp128 => 'L',7527 .fp128 => 'L',
7614 .ppc_fp128 => 'M',7528 .ppc_fp128 => 'M',
...@@ -7622,7 +7536,7 @@ pub const Constant = enum(u32) {...@@ -7622,7 +7536,7 @@ pub const Constant = enum(u32) {
7622 },7536 },
7623 .x86_fp80 => {7537 .x86_fp80 => {
7624 const extra = data.builder.constantExtraData(Fp80, item.data);7538 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}", .{
7626 extra.hi, extra.lo_hi, extra.lo_lo,7540 extra.hi, extra.lo_hi, extra.lo_lo,
7627 });7541 });
7628 },7542 },
...@@ -7631,7 +7545,7 @@ pub const Constant = enum(u32) {...@@ -7631,7 +7545,7 @@ pub const Constant = enum(u32) {
7631 .zeroinitializer,7545 .zeroinitializer,
7632 .undef,7546 .undef,
7633 .poison,7547 .poison,
7634 => |tag| try writer.writeAll(@tagName(tag)),7548 => |tag| try w.writeAll(@tagName(tag)),
7635 .structure,7549 .structure,
7636 .packed_structure,7550 .packed_structure,
7637 .array,7551 .array,
...@@ -7640,7 +7554,7 @@ pub const Constant = enum(u32) {...@@ -7640,7 +7554,7 @@ pub const Constant = enum(u32) {
7640 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);7554 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);
7641 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));7555 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));
7642 const vals = extra.trail.next(len, Constant, data.builder);7556 const vals = extra.trail.next(len, Constant, data.builder);
7643 try writer.writeAll(switch (tag) {7557 try w.writeAll(switch (tag) {
7644 .structure => "{ ",7558 .structure => "{ ",
7645 .packed_structure => "<{ ",7559 .packed_structure => "<{ ",
7646 .array => "[",7560 .array => "[",
...@@ -7648,10 +7562,10 @@ pub const Constant = enum(u32) {...@@ -7648,10 +7562,10 @@ pub const Constant = enum(u32) {
7648 else => unreachable,7562 else => unreachable,
7649 });7563 });
7650 for (vals, 0..) |val, index| {7564 for (vals, 0..) |val, index| {
7651 if (index > 0) try writer.writeAll(", ");7565 if (index > 0) try w.writeAll(", ");
7652 try writer.print("{%}", .{val.fmt(data.builder)});7566 try w.print("{f%}", .{val.fmt(data.builder)});
7653 }7567 }
7654 try writer.writeAll(switch (tag) {7568 try w.writeAll(switch (tag) {
7655 .structure => " }",7569 .structure => " }",
7656 .packed_structure => " }>",7570 .packed_structure => " }>",
7657 .array => "]",7571 .array => "]",
...@@ -7662,20 +7576,20 @@ pub const Constant = enum(u32) {...@@ -7662,20 +7576,20 @@ pub const Constant = enum(u32) {
7662 .splat => {7576 .splat => {
7663 const extra = data.builder.constantExtraData(Splat, item.data);7577 const extra = data.builder.constantExtraData(Splat, item.data);
7664 const len = extra.type.vectorLen(data.builder);7578 const len = extra.type.vectorLen(data.builder);
7665 try writer.writeByte('<');7579 try w.writeByte('<');
7666 for (0..len) |index| {7580 for (0..len) |index| {
7667 if (index > 0) try writer.writeAll(", ");7581 if (index > 0) try w.writeAll(", ");
7668 try writer.print("{%}", .{extra.value.fmt(data.builder)});7582 try w.print("{f%}", .{extra.value.fmt(data.builder)});
7669 }7583 }
7670 try writer.writeByte('>');7584 try w.writeByte('>');
7671 },7585 },
7672 .string => try writer.print("c{\"}", .{7586 .string => try w.print("c{f\"}", .{
7673 @as(String, @enumFromInt(item.data)).fmt(data.builder),7587 @as(String, @enumFromInt(item.data)).fmt(data.builder),
7674 }),7588 }),
7675 .blockaddress => |tag| {7589 .blockaddress => |tag| {
7676 const extra = data.builder.constantExtraData(BlockAddress, item.data);7590 const extra = data.builder.constantExtraData(BlockAddress, item.data);
7677 const function = extra.function.ptrConst(data.builder);7591 const function = extra.function.ptrConst(data.builder);
7678 try writer.print("{s}({}, {})", .{7592 try w.print("{s}({f}, {f})", .{
7679 @tagName(tag),7593 @tagName(tag),
7680 function.global.fmt(data.builder),7594 function.global.fmt(data.builder),
7681 extra.block.toInst(function).fmt(extra.function, data.builder),7595 extra.block.toInst(function).fmt(extra.function, data.builder),
...@@ -7685,7 +7599,7 @@ pub const Constant = enum(u32) {...@@ -7685,7 +7599,7 @@ pub const Constant = enum(u32) {
7685 .no_cfi,7599 .no_cfi,
7686 => |tag| {7600 => |tag| {
7687 const function: Function.Index = @enumFromInt(item.data);7601 const function: Function.Index = @enumFromInt(item.data);
7688 try writer.print("{s} {}", .{7602 try w.print("{s} {f}", .{
7689 @tagName(tag),7603 @tagName(tag),
7690 function.ptrConst(data.builder).global.fmt(data.builder),7604 function.ptrConst(data.builder).global.fmt(data.builder),
7691 });7605 });
...@@ -7697,7 +7611,7 @@ pub const Constant = enum(u32) {...@@ -7697,7 +7611,7 @@ pub const Constant = enum(u32) {
7697 .addrspacecast,7611 .addrspacecast,
7698 => |tag| {7612 => |tag| {
7699 const extra = data.builder.constantExtraData(Cast, item.data);7613 const extra = data.builder.constantExtraData(Cast, item.data);
7700 try writer.print("{s} ({%} to {%})", .{7614 try w.print("{s} ({f%} to {f%})", .{
7701 @tagName(tag),7615 @tagName(tag),
7702 extra.val.fmt(data.builder),7616 extra.val.fmt(data.builder),
7703 extra.type.fmt(data.builder),7617 extra.type.fmt(data.builder),
...@@ -7709,13 +7623,13 @@ pub const Constant = enum(u32) {...@@ -7709,13 +7623,13 @@ pub const Constant = enum(u32) {
7709 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);7623 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);
7710 const indices =7624 const indices =
7711 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);7625 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);
7712 try writer.print("{s} ({%}, {%}", .{7626 try w.print("{s} ({f%}, {f%}", .{
7713 @tagName(tag),7627 @tagName(tag),
7714 extra.data.type.fmt(data.builder),7628 extra.data.type.fmt(data.builder),
7715 extra.data.base.fmt(data.builder),7629 extra.data.base.fmt(data.builder),
7716 });7630 });
7717 for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});7631 for (indices) |index| try w.print(", {f%}", .{index.fmt(data.builder)});
7718 try writer.writeByte(')');7632 try w.writeByte(')');
7719 },7633 },
7720 .add,7634 .add,
7721 .@"add nsw",7635 .@"add nsw",
...@@ -7727,7 +7641,7 @@ pub const Constant = enum(u32) {...@@ -7727,7 +7641,7 @@ pub const Constant = enum(u32) {
7727 .xor,7641 .xor,
7728 => |tag| {7642 => |tag| {
7729 const extra = data.builder.constantExtraData(Binary, item.data);7643 const extra = data.builder.constantExtraData(Binary, item.data);
7730 try writer.print("{s} ({%}, {%})", .{7644 try w.print("{s} ({f%}, {f%})", .{
7731 @tagName(tag),7645 @tagName(tag),
7732 extra.lhs.fmt(data.builder),7646 extra.lhs.fmt(data.builder),
7733 extra.rhs.fmt(data.builder),7647 extra.rhs.fmt(data.builder),
...@@ -7751,7 +7665,7 @@ pub const Constant = enum(u32) {...@@ -7751,7 +7665,7 @@ pub const Constant = enum(u32) {
7751 .@"asm sideeffect alignstack inteldialect unwind",7665 .@"asm sideeffect alignstack inteldialect unwind",
7752 => |tag| {7666 => |tag| {
7753 const extra = data.builder.constantExtraData(Assembly, item.data);7667 const extra = data.builder.constantExtraData(Assembly, item.data);
7754 try writer.print("{s} {\"}, {\"}", .{7668 try w.print("{s} {f\"}, {f\"}", .{
7755 @tagName(tag),7669 @tagName(tag),
7756 extra.assembly.fmt(data.builder),7670 extra.assembly.fmt(data.builder),
7757 extra.constraints.fmt(data.builder),7671 extra.constraints.fmt(data.builder),
...@@ -7759,11 +7673,15 @@ pub const Constant = enum(u32) {...@@ -7759,11 +7673,15 @@ pub const Constant = enum(u32) {
7759 },7673 },
7760 }7674 }
7761 },7675 },
7762 .global => |global| try writer.print("{}", .{global.fmt(data.builder)}),7676 .global => |global| try w.print("{f}", .{global.fmt(data.builder)}),
7763 }7677 }
7764 }7678 }
7765 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {7679 pub fn fmt(self: Constant, builder: *Builder, flags: FormatData.Flags) std.fmt.Formatter(FormatData, format) {
7766 return .{ .data = .{ .constant = self, .builder = builder } };7680 return .{ .data = .{
7681 .constant = self,
7682 .builder = builder,
7683 .flags = flags,
7684 } };
7767 }7685 }
7768};7686};
77697687
...@@ -7819,26 +7737,21 @@ pub const Value = enum(u32) {...@@ -7819,26 +7737,21 @@ pub const Value = enum(u32) {
7819 function: Function.Index,7737 function: Function.Index,
7820 builder: *Builder,7738 builder: *Builder,
7821 };7739 };
7822 fn format(7740 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7823 data: FormatData,
7824 comptime fmt_str: []const u8,
7825 fmt_opts: std.fmt.FormatOptions,
7826 writer: anytype,
7827 ) @TypeOf(writer).Error!void {
7828 switch (data.value.unwrap()) {7741 switch (data.value.unwrap()) {
7829 .instruction => |instruction| try Function.Instruction.Index.format(.{7742 .instruction => |instruction| try Function.Instruction.Index.format(.{
7830 .instruction = instruction,7743 .instruction = instruction,
7831 .function = data.function,7744 .function = data.function,
7832 .builder = data.builder,7745 .builder = data.builder,
7833 }, fmt_str, fmt_opts, writer),7746 }, w),
7834 .constant => |constant| try Constant.format(.{7747 .constant => |constant| try Constant.format(.{
7835 .constant = constant,7748 .constant = constant,
7836 .builder = data.builder,7749 .builder = data.builder,
7837 }, fmt_str, fmt_opts, writer),7750 }, w),
7838 .metadata => unreachable,7751 .metadata => unreachable,
7839 }7752 }
7840 }7753 }
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) {
7842 return .{ .data = .{ .value = self, .function = function, .builder = builder } };7755 return .{ .data = .{ .value = self, .function = function, .builder = builder } };
7843 }7756 }
7844};7757};
...@@ -7869,15 +7782,10 @@ pub const MetadataString = enum(u32) {...@@ -7869,15 +7782,10 @@ pub const MetadataString = enum(u32) {
7869 metadata_string: MetadataString,7782 metadata_string: MetadataString,
7870 builder: *const Builder,7783 builder: *const Builder,
7871 };7784 };
7872 fn format(7785 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7873 data: FormatData,7786 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, w);
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);
7879 }7787 }
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) {
7881 return .{ .data = .{ .metadata_string = self, .builder = builder } };7789 return .{ .data = .{ .metadata_string = self, .builder = builder } };
7882 }7790 }
7883};7791};
...@@ -8039,29 +7947,24 @@ pub const Metadata = enum(u32) {...@@ -8039,29 +7947,24 @@ pub const Metadata = enum(u32) {
8039 AllCallsDescribed: bool = false,7947 AllCallsDescribed: bool = false,
8040 Unused: u2 = 0,7948 Unused: u2 = 0,
80417949
8042 pub fn format(7950 pub fn format(self: DIFlags, w: *Writer, comptime _: []const u8) Writer.Error!void {
8043 self: DIFlags,
8044 comptime _: []const u8,
8045 _: std.fmt.FormatOptions,
8046 writer: anytype,
8047 ) @TypeOf(writer).Error!void {
8048 var need_pipe = false;7951 var need_pipe = false;
8049 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {7952 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {
8050 switch (@typeInfo(field.type)) {7953 switch (@typeInfo(field.type)) {
8051 .bool => if (@field(self, field.name)) {7954 .bool => if (@field(self, field.name)) {
8052 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;7955 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8053 try writer.print("DIFlag{s}", .{field.name});7956 try w.print("DIFlag{s}", .{field.name});
8054 },7957 },
8055 .@"enum" => if (@field(self, field.name) != .Zero) {7958 .@"enum" => if (@field(self, field.name) != .Zero) {
8056 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;7959 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8057 try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))});7960 try w.print("DIFlag{s}", .{@tagName(@field(self, field.name))});
8058 },7961 },
8059 .int => assert(@field(self, field.name) == 0),7962 .int => assert(@field(self, field.name) == 0),
8060 else => @compileError("bad field type: " ++ field.name ++ ": " ++7963 else => @compileError("bad field type: " ++ field.name ++ ": " ++
8061 @typeName(field.type)),7964 @typeName(field.type)),
8062 }7965 }
8063 }7966 }
8064 if (!need_pipe) try writer.writeByte('0');7967 if (!need_pipe) try w.writeByte('0');
8065 }7968 }
8066 };7969 };
80677970
...@@ -8101,29 +8004,24 @@ pub const Metadata = enum(u32) {...@@ -8101,29 +8004,24 @@ pub const Metadata = enum(u32) {
8101 ObjCDirect: bool = false,8004 ObjCDirect: bool = false,
8102 Unused: u20 = 0,8005 Unused: u20 = 0,
81038006
8104 pub fn format(8007 pub fn format(self: DISPFlags, w: *Writer, comptime _: []const u8) Writer.Error!void {
8105 self: DISPFlags,
8106 comptime _: []const u8,
8107 _: std.fmt.FormatOptions,
8108 writer: anytype,
8109 ) @TypeOf(writer).Error!void {
8110 var need_pipe = false;8008 var need_pipe = false;
8111 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {8009 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {
8112 switch (@typeInfo(field.type)) {8010 switch (@typeInfo(field.type)) {
8113 .bool => if (@field(self, field.name)) {8011 .bool => if (@field(self, field.name)) {
8114 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;8012 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8115 try writer.print("DISPFlag{s}", .{field.name});8013 try w.print("DISPFlag{s}", .{field.name});
8116 },8014 },
8117 .@"enum" => if (@field(self, field.name) != .Zero) {8015 .@"enum" => if (@field(self, field.name) != .Zero) {
8118 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;8016 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8119 try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});8017 try w.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});
8120 },8018 },
8121 .int => assert(@field(self, field.name) == 0),8019 .int => assert(@field(self, field.name) == 0),
8122 else => @compileError("bad field type: " ++ field.name ++ ": " ++8020 else => @compileError("bad field type: " ++ field.name ++ ": " ++
8123 @typeName(field.type)),8021 @typeName(field.type)),
8124 }8022 }
8125 }8023 }
8126 if (!need_pipe) try writer.writeByte('0');8024 if (!need_pipe) try w.writeByte('0');
8127 }8025 }
8128 };8026 };
81298027
...@@ -8298,6 +8196,9 @@ pub const Metadata = enum(u32) {...@@ -8298,6 +8196,9 @@ pub const Metadata = enum(u32) {
8298 formatter: *Formatter,8196 formatter: *Formatter,
8299 prefix: []const u8 = "",8197 prefix: []const u8 = "",
8300 node: Node,8198 node: Node,
8199 specialized: ?TODO,
8200
8201 const TODO = opaque {};
83018202
8302 const Node = union(enum) {8203 const Node = union(enum) {
8303 none,8204 none,
...@@ -8323,20 +8224,15 @@ pub const Metadata = enum(u32) {...@@ -8323,20 +8224,15 @@ pub const Metadata = enum(u32) {
8323 };8224 };
8324 };8225 };
8325 };8226 };
8326 fn format(8227 fn format(data: FormatData, w: *Writer) Writer.Error!void {
8327 data: FormatData,
8328 comptime fmt_str: []const u8,
8329 fmt_opts: std.fmt.FormatOptions,
8330 writer: anytype,
8331 ) @TypeOf(writer).Error!void {
8332 if (data.node == .none) return;8228 if (data.node == .none) return;
83338229
8334 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';8230 const is_specialized = data.specialized != null;
8335 const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str;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(", ");
8338 defer data.formatter.need_comma = true;8234 defer data.formatter.need_comma = true;
8339 try writer.writeAll(data.prefix);8235 try w.writeAll(data.prefix);
83408236
8341 const builder = data.formatter.builder;8237 const builder = data.formatter.builder;
8342 switch (data.node) {8238 switch (data.node) {
...@@ -8351,54 +8247,50 @@ pub const Metadata = enum(u32) {...@@ -8351,54 +8247,50 @@ pub const Metadata = enum(u32) {
8351 .expression => {8247 .expression => {
8352 var extra = builder.metadataExtraDataTrail(Expression, item.data);8248 var extra = builder.metadataExtraDataTrail(Expression, item.data);
8353 const elements = extra.trail.next(extra.data.elements_len, u32, builder);8249 const elements = extra.trail.next(extra.data.elements_len, u32, builder);
8354 try writer.writeAll("!DIExpression(");8250 try w.writeAll("!DIExpression(");
8355 for (elements) |element| try format(.{8251 for (elements) |element| try format(.{
8356 .formatter = data.formatter,8252 .formatter = data.formatter,
8357 .node = .{ .u64 = element },8253 .node = .{ .u64 = element },
8358 }, "%", fmt_opts, writer);8254 }, w, "%");
8359 try writer.writeByte(')');8255 try w.writeByte(')');
8360 },8256 },
8361 .constant => try Constant.format(.{8257 .constant => try Constant.format(.{
8362 .constant = @enumFromInt(item.data),8258 .constant = @enumFromInt(item.data),
8363 .builder = builder,8259 .builder = builder,
8364 }, recurse_fmt_str, fmt_opts, writer),8260 }, w, recurse_fmt_str),
8365 else => unreachable,8261 else => unreachable,
8366 }8262 }
8367 },8263 },
8368 .index => |node| try writer.print("!{d}", .{node}),8264 .index => |node| try w.print("!{d}", .{node}),
8369 inline .local_value, .local_metadata => |node, tag| try Value.format(.{8265 inline .local_value, .local_metadata => |node, tag| try Value.format(.{
8370 .value = node.value,8266 .value = node.value,
8371 .function = node.function,8267 .function = node.function,
8372 .builder = builder,8268 .builder = builder,
8373 }, switch (tag) {8269 }, w, switch (tag) {
8374 .local_value => recurse_fmt_str,8270 .local_value => recurse_fmt_str,
8375 .local_metadata => "%",8271 .local_metadata => "%",
8376 else => unreachable,8272 else => unreachable,
8377 }, fmt_opts, writer),8273 }),
8378 inline .local_inline, .local_index => |node, tag| {8274 inline .local_inline, .local_index => |node, tag| {
8379 if (comptime std.mem.eql(u8, recurse_fmt_str, "%"))8275 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)});
8381 try format(.{8277 try format(.{
8382 .formatter = data.formatter,8278 .formatter = data.formatter,
8383 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),8279 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),
8384 }, "%", fmt_opts, writer);8280 }, w, "%");
8385 },8281 },
8386 .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{8282 .string => |node| try w.print((if (is_specialized) "" else "!") ++ "{f}", .{
8387 node.fmt(builder),8283 node.fmt(builder),
8388 }),8284 }),
8389 inline .bool,8285 inline .bool, .u32, .u64 => |node| try w.print("{}", .{node}),
8390 .u32,8286 inline .di_flags, .sp_flags => |node| try w.print("{f}", .{node}),
8391 .u64,8287 .raw => |node| try w.writeAll(node),
8392 .di_flags,
8393 .sp_flags,
8394 => |node| try writer.print("{}", .{node}),
8395 .raw => |node| try writer.writeAll(node),
8396 }8288 }
8397 }8289 }
8398 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {8290 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {
8399 Metadata => Allocator.Error,8291 Metadata => Allocator.Error,
8400 else => error{},8292 else => error{},
8401 }!std.fmt.Formatter(format) {8293 }!std.fmt.Formatter(FormatData, format) {
8402 const Node = @TypeOf(node);8294 const Node = @TypeOf(node);
8403 const MaybeNode = switch (@typeInfo(Node)) {8295 const MaybeNode = switch (@typeInfo(Node)) {
8404 .optional => Node,8296 .optional => Node,
...@@ -8442,7 +8334,7 @@ pub const Metadata = enum(u32) {...@@ -8442,7 +8334,7 @@ pub const Metadata = enum(u32) {
8442 prefix: []const u8,8334 prefix: []const u8,
8443 value: Value,8335 value: Value,
8444 function: Function.Index,8336 function: Function.Index,
8445 ) Allocator.Error!std.fmt.Formatter(format) {8337 ) Allocator.Error!std.fmt.Formatter(FormatData, format) {
8446 return .{ .data = .{8338 return .{ .data = .{
8447 .formatter = formatter,8339 .formatter = formatter,
8448 .prefix = prefix,8340 .prefix = prefix,
...@@ -8506,7 +8398,7 @@ pub const Metadata = enum(u32) {...@@ -8506,7 +8398,7 @@ pub const Metadata = enum(u32) {
8506 DIGlobalVariableExpression,8398 DIGlobalVariableExpression,
8507 },8399 },
8508 nodes: anytype,8400 nodes: anytype,
8509 writer: anytype,8401 w: *Writer,
8510 ) !void {8402 ) !void {
8511 comptime var fmt_str: []const u8 = "";8403 comptime var fmt_str: []const u8 = "";
8512 const names = comptime std.meta.fieldNames(@TypeOf(nodes));8404 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
...@@ -8523,10 +8415,10 @@ pub const Metadata = enum(u32) {...@@ -8523,10 +8415,10 @@ pub const Metadata = enum(u32) {
8523 }8415 }
8524 fmt_str = fmt_str ++ "(";8416 fmt_str = fmt_str ++ "(";
8525 inline for (fields[2..], names) |*field, name| {8417 inline for (fields[2..], names) |*field, name| {
8526 fmt_str = fmt_str ++ "{[" ++ name ++ "]S}";8418 fmt_str = fmt_str ++ "{[" ++ name ++ "]fS}";
8527 field.* = .{8419 field.* = .{
8528 .name = name,8420 .name = name,
8529 .type = std.fmt.Formatter(format),8421 .type = std.fmt.Formatter(FormatData, format),
8530 .default_value_ptr = null,8422 .default_value_ptr = null,
8531 .is_comptime = false,8423 .is_comptime = false,
8532 .alignment = 0,8424 .alignment = 0,
...@@ -8546,7 +8438,7 @@ pub const Metadata = enum(u32) {...@@ -8546,7 +8438,7 @@ pub const Metadata = enum(u32) {
8546 name ++ ": ",8438 name ++ ": ",
8547 @field(nodes, name),8439 @field(nodes, name),
8548 );8440 );
8549 try writer.print(fmt_str, fmt_args);8441 try w.print(fmt_str, fmt_args);
8550 }8442 }
8551 };8443 };
8552};8444};
...@@ -8636,7 +8528,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8636,7 +8528,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8636 inline for (.{ 0, 4 }) |addr_space_index| {8528 inline for (.{ 0, 4 }) |addr_space_index| {
8637 const addr_space: AddrSpace = @enumFromInt(addr_space_index);8529 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8638 assert(self.ptrTypeAssumeCapacity(addr_space) ==8530 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8639 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));8531 @field(Type, std.fmt.comptimePrint("ptr{f }", .{addr_space})));
8640 }8532 }
8641 }8533 }
86428534
...@@ -8759,16 +8651,8 @@ pub fn deinit(self: *Builder) void {...@@ -8759,16 +8651,8 @@ pub fn deinit(self: *Builder) void {
8759 self.* = undefined;8651 self.* = undefined;
8760}8652}
87618653
8762pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {8654pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {
8763 self.module_asm.clearRetainingCapacity();8655 self.module_asm = aw.toArrayList();
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 {
8772 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')8656 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')
8773 try self.module_asm.append(self.gpa, '\n');8657 try self.module_asm.append(self.gpa, '\n');
8774}8658}
...@@ -8804,7 +8688,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo...@@ -8804,7 +8688,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo
8804}8688}
88058689
8806pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {8690pub 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);
8808 return self.trailingStringAssumeCapacity();8692 return self.trailingStringAssumeCapacity();
8809}8693}
88108694
...@@ -9076,9 +8960,13 @@ pub fn getIntrinsic(...@@ -9076,9 +8960,13 @@ pub fn getIntrinsic(
9076 const allocator = stack.get();8960 const allocator = stack.get();
90778961
9078 const name = name: {8962 const name = name: {
9079 const writer = self.strtab_string_bytes.writer(self.gpa);8963 {
9080 try writer.print("llvm.{s}", .{@tagName(id)});8964 var aw: Writer.Allocating = .fromArrayList(self.gpa, &self.strtab_string_bytes);
9081 for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)});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 }
9082 break :name try self.trailingStrtabString();8970 break :name try self.trailingStrtabString();
9083 };8971 };
9084 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;8972 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
...@@ -9492,110 +9380,74 @@ pub fn asmValue(...@@ -9492,110 +9380,74 @@ pub fn asmValue(
9492 return (try self.asmConst(ty, info, assembly, constraints)).toValue();9380 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
9493}9381}
94949382
9495pub fn dump(self: *Builder) void {9383pub fn dump(b: *Builder) void {
9384 var buffer: [4000]u8 = undefined;
9496 const stderr: std.fs.File = .stderr();9385 const stderr: std.fs.File = .stderr();
9497 self.print(stderr.writer()) catch {};9386 b.printToFile(stderr, &buffer) catch {};
9498}9387}
94999388
9500pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool {9389pub fn printToFilePath(b: *Builder, dir: std.fs.Dir, path: []const u8) !void {
9501 var file = std.fs.cwd().createFile(path, .{}) catch |err| {9390 var buffer: [4000]u8 = undefined;
9502 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });9391 const file = try dir.createFile(path, .{});
9503 return false;
9504 };
9505 defer file.close();9392 defer file.close();
9506 self.print(file.writer()) catch |err| {9393 try b.printToFile(file, &buffer);
9507 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9508 return false;
9509 };
9510 return true;
9511}9394}
95129395
9513pub fn print(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator.Error)!void {9396pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void {
9514 var bw = std.io.bufferedWriter(writer);9397 var fw = file.writer(buffer);
9515 try self.printUnbuffered(bw.writer());9398 try print(b, &fw.interface);
9516 try bw.flush();9399 try fw.interface.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 };
9536}9400}
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 {
9551 var need_newline = false;9403 var need_newline = false;
9552 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };9404 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
9553 defer metadata_formatter.map.deinit(self.gpa);9405 defer metadata_formatter.map.deinit(self.gpa);
95549406
9555 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {9407 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;9408 if (need_newline) try w.writeByte('\n') else need_newline = true;
9557 if (self.source_filename != .none) try writer.print(9409 if (self.source_filename != .none) try w.print(
9558 \\; ModuleID = '{s}'9410 \\; ModuleID = '{s}'
9559 \\source_filename = {"}9411 \\source_filename = {f"}
9560 \\9412 \\
9561 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });9413 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
9562 if (self.data_layout != .none) try writer.print(9414 if (self.data_layout != .none) try w.print(
9563 \\target datalayout = {"}9415 \\target datalayout = {f"}
9564 \\9416 \\
9565 , .{self.data_layout.fmt(self)});9417 , .{self.data_layout.fmt(self)});
9566 if (self.target_triple != .none) try writer.print(9418 if (self.target_triple != .none) try w.print(
9567 \\target triple = {"}9419 \\target triple = {f"}
9568 \\9420 \\
9569 , .{self.target_triple.fmt(self)});9421 , .{self.target_triple.fmt(self)});
9570 }9422 }
95719423
9572 if (self.module_asm.items.len > 0) {9424 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;
9574 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');9426 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
9575 while (line_it.next()) |line| {9427 while (line_it.next()) |line| {
9576 try writer.writeAll("module asm ");9428 try w.writeAll("module asm ");
9577 try printEscapedString(line, .always_quote, writer);9429 try printEscapedString(line, .always_quote, w);
9578 try writer.writeByte('\n');9430 try w.writeByte('\n');
9579 }9431 }
9580 }9432 }
95819433
9582 if (self.types.count() > 0) {9434 if (self.types.count() > 0) {
9583 if (need_newline) try writer.writeByte('\n') else need_newline = true;9435 if (need_newline) try w.writeByte('\n') else need_newline = true;
9584 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(9436 for (self.types.keys(), self.types.values()) |id, ty| try w.print(
9585 \\%{} = type {}9437 \\%{f} = type {f}
9586 \\9438 \\
9587 , .{ id.fmt(self), ty.fmt(self) });9439 , .{ id.fmt(self), ty.fmt(self) });
9588 }9440 }
95899441
9590 if (self.variables.items.len > 0) {9442 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;
9592 for (self.variables.items) |variable| {9444 for (self.variables.items) |variable| {
9593 if (variable.global.getReplacement(self) != .none) continue;9445 if (variable.global.getReplacement(self) != .none) continue;
9594 const global = variable.global.ptrConst(self);9446 const global = variable.global.ptrConst(self);
9595 metadata_formatter.need_comma = true;9447 metadata_formatter.need_comma = true;
9596 defer metadata_formatter.need_comma = undefined;9448 defer metadata_formatter.need_comma = undefined;
9597 try writer.print(9449 try w.print(
9598 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{}9450 \\{f} ={f}{f}{f}{f}{f }{f}{f }{f} {s} {f%}{f }{f, }{f}
9599 \\9451 \\
9600 , .{9452 , .{
9601 variable.global.fmt(self),9453 variable.global.fmt(self),
...@@ -9618,14 +9470,14 @@ pub fn printUnbuffered(...@@ -9618,14 +9470,14 @@ pub fn printUnbuffered(
9618 }9470 }
96199471
9620 if (self.aliases.items.len > 0) {9472 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;
9622 for (self.aliases.items) |alias| {9474 for (self.aliases.items) |alias| {
9623 if (alias.global.getReplacement(self) != .none) continue;9475 if (alias.global.getReplacement(self) != .none) continue;
9624 const global = alias.global.ptrConst(self);9476 const global = alias.global.ptrConst(self);
9625 metadata_formatter.need_comma = true;9477 metadata_formatter.need_comma = true;
9626 defer metadata_formatter.need_comma = undefined;9478 defer metadata_formatter.need_comma = undefined;
9627 try writer.print(9479 try w.print(
9628 \\{} ={}{}{}{}{ }{} alias {%}, {%}{}9480 \\{f} ={f}{f}{f}{f}{f }{f} alias {f%}, {f%}{f}
9629 \\9481 \\
9630 , .{9482 , .{
9631 alias.global.fmt(self),9483 alias.global.fmt(self),
...@@ -9647,17 +9499,17 @@ pub fn printUnbuffered(...@@ -9647,17 +9499,17 @@ pub fn printUnbuffered(
96479499
9648 for (0.., self.functions.items) |function_i, function| {9500 for (0.., self.functions.items) |function_i, function| {
9649 if (function.global.getReplacement(self) != .none) continue;9501 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;
9651 const function_index: Function.Index = @enumFromInt(function_i);9503 const function_index: Function.Index = @enumFromInt(function_i);
9652 const global = function.global.ptrConst(self);9504 const global = function.global.ptrConst(self);
9653 const params_len = global.type.functionParameters(self).len;9505 const params_len = global.type.functionParameters(self).len;
9654 const function_attributes = function.attributes.func(self);9506 const function_attributes = function.attributes.func(self);
9655 if (function_attributes != .none) try writer.print(9507 if (function_attributes != .none) try w.print(
9656 \\; Function Attrs:{}9508 \\; Function Attrs:{f}
9657 \\9509 \\
9658 , .{function_attributes.fmt(self)});9510 , .{function_attributes.fmt(self)});
9659 try writer.print(9511 try w.print(
9660 \\{s}{}{}{}{}{}{"} {%} {}(9512 \\{s}{f}{f}{f}{f}{f}{f"} {f%} {f}(
9661 , .{9513 , .{
9662 if (function.instructions.len > 0) "define" else "declare",9514 if (function.instructions.len > 0) "define" else "declare",
9663 global.linkage,9515 global.linkage,
...@@ -9670,40 +9522,40 @@ pub fn printUnbuffered(...@@ -9670,40 +9522,40 @@ pub fn printUnbuffered(
9670 function.global.fmt(self),9522 function.global.fmt(self),
9671 });9523 });
9672 for (0..params_len) |arg| {9524 for (0..params_len) |arg| {
9673 if (arg > 0) try writer.writeAll(", ");9525 if (arg > 0) try w.writeAll(", ");
9674 try writer.print(9526 try w.print(
9675 \\{%}{"}9527 \\{f%}{f"}
9676 , .{9528 , .{
9677 global.type.functionParameters(self)[arg].fmt(self),9529 global.type.functionParameters(self)[arg].fmt(self),
9678 function.attributes.param(arg, self).fmt(self),9530 function.attributes.param(arg, self).fmt(self),
9679 });9531 });
9680 if (function.instructions.len > 0)9532 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)})
9682 else9534 else
9683 try writer.print(" %{d}", .{arg});9535 try w.print(" %{d}", .{arg});
9684 }9536 }
9685 switch (global.type.functionKind(self)) {9537 switch (global.type.functionKind(self)) {
9686 .normal => {},9538 .normal => {},
9687 .vararg => {9539 .vararg => {
9688 if (params_len > 0) try writer.writeAll(", ");9540 if (params_len > 0) try w.writeAll(", ");
9689 try writer.writeAll("...");9541 try w.writeAll("...");
9690 },9542 },
9691 }9543 }
9692 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });9544 try w.print("){f}{f }", .{ global.unnamed_addr, global.addr_space });
9693 if (function_attributes != .none) try writer.print(" #{d}", .{9545 if (function_attributes != .none) try w.print(" #{d}", .{
9694 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,9546 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9695 });9547 });
9696 {9548 {
9697 metadata_formatter.need_comma = false;9549 metadata_formatter.need_comma = false;
9698 defer metadata_formatter.need_comma = undefined;9550 defer metadata_formatter.need_comma = undefined;
9699 try writer.print("{ }{}", .{9551 try w.print("{f }{f}", .{
9700 function.alignment,9552 function.alignment,
9701 try metadata_formatter.fmt(" !dbg ", global.dbg),9553 try metadata_formatter.fmt(" !dbg ", global.dbg),
9702 });9554 });
9703 }9555 }
9704 if (function.instructions.len > 0) {9556 if (function.instructions.len > 0) {
9705 var block_incoming_len: u32 = undefined;9557 var block_incoming_len: u32 = undefined;
9706 try writer.writeAll(" {\n");9558 try w.writeAll(" {\n");
9707 var maybe_dbg_index: ?u32 = null;9559 var maybe_dbg_index: ?u32 = null;
9708 for (params_len..function.instructions.len) |instruction_i| {9560 for (params_len..function.instructions.len) |instruction_i| {
9709 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);9561 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
...@@ -9801,7 +9653,7 @@ pub fn printUnbuffered(...@@ -9801,7 +9653,7 @@ pub fn printUnbuffered(
9801 .xor,9653 .xor,
9802 => |tag| {9654 => |tag| {
9803 const extra = function.extraData(Function.Instruction.Binary, instruction.data);9655 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9804 try writer.print(" %{} = {s} {%}, {}", .{9656 try w.print(" %{f} = {s} {f%}, {f}", .{
9805 instruction_index.name(&function).fmt(self),9657 instruction_index.name(&function).fmt(self),
9806 @tagName(tag),9658 @tagName(tag),
9807 extra.lhs.fmt(function_index, self),9659 extra.lhs.fmt(function_index, self),
...@@ -9823,7 +9675,7 @@ pub fn printUnbuffered(...@@ -9823,7 +9675,7 @@ pub fn printUnbuffered(
9823 .zext,9675 .zext,
9824 => |tag| {9676 => |tag| {
9825 const extra = function.extraData(Function.Instruction.Cast, instruction.data);9677 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9826 try writer.print(" %{} = {s} {%} to {%}", .{9678 try w.print(" %{f} = {s} {f%} to {f%}", .{
9827 instruction_index.name(&function).fmt(self),9679 instruction_index.name(&function).fmt(self),
9828 @tagName(tag),9680 @tagName(tag),
9829 extra.val.fmt(function_index, self),9681 extra.val.fmt(function_index, self),
...@@ -9834,7 +9686,7 @@ pub fn printUnbuffered(...@@ -9834,7 +9686,7 @@ pub fn printUnbuffered(
9834 .@"alloca inalloca",9686 .@"alloca inalloca",
9835 => |tag| {9687 => |tag| {
9836 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);9688 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9837 try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{9689 try w.print(" %{f} = {s} {f%}{f,%}{f, }{f, }", .{
9838 instruction_index.name(&function).fmt(self),9690 instruction_index.name(&function).fmt(self),
9839 @tagName(tag),9691 @tagName(tag),
9840 extra.type.fmt(self),9692 extra.type.fmt(self),
...@@ -9850,7 +9702,7 @@ pub fn printUnbuffered(...@@ -9850,7 +9702,7 @@ pub fn printUnbuffered(
9850 .atomicrmw => |tag| {9702 .atomicrmw => |tag| {
9851 const extra =9703 const extra =
9852 function.extraData(Function.Instruction.AtomicRmw, instruction.data);9704 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, }", .{
9854 instruction_index.name(&function).fmt(self),9706 instruction_index.name(&function).fmt(self),
9855 @tagName(tag),9707 @tagName(tag),
9856 extra.info.access_kind,9708 extra.info.access_kind,
...@@ -9866,19 +9718,19 @@ pub fn printUnbuffered(...@@ -9866,19 +9718,19 @@ pub fn printUnbuffered(
9866 block_incoming_len = instruction.data;9718 block_incoming_len = instruction.data;
9867 const name = instruction_index.name(&function);9719 const name = instruction_index.name(&function);
9868 if (@intFromEnum(instruction_index) > params_len)9720 if (@intFromEnum(instruction_index) > params_len)
9869 try writer.writeByte('\n');9721 try w.writeByte('\n');
9870 try writer.print("{}:\n", .{name.fmt(self)});9722 try w.print("{f}:\n", .{name.fmt(self)});
9871 continue;9723 continue;
9872 },9724 },
9873 .br => |tag| {9725 .br => |tag| {
9874 const target: Function.Block.Index = @enumFromInt(instruction.data);9726 const target: Function.Block.Index = @enumFromInt(instruction.data);
9875 try writer.print(" {s} {%}", .{9727 try w.print(" {s} {f%}", .{
9876 @tagName(tag), target.toInst(&function).fmt(function_index, self),9728 @tagName(tag), target.toInst(&function).fmt(function_index, self),
9877 });9729 });
9878 },9730 },
9879 .br_cond => {9731 .br_cond => {
9880 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);9732 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9881 try writer.print(" br {%}, {%}, {%}", .{9733 try w.print(" br {f%}, {f%}, {f%}", .{
9882 extra.cond.fmt(function_index, self),9734 extra.cond.fmt(function_index, self),
9883 extra.then.toInst(&function).fmt(function_index, self),9735 extra.then.toInst(&function).fmt(function_index, self),
9884 extra.@"else".toInst(&function).fmt(function_index, self),9736 extra.@"else".toInst(&function).fmt(function_index, self),
...@@ -9887,8 +9739,8 @@ pub fn printUnbuffered(...@@ -9887,8 +9739,8 @@ pub fn printUnbuffered(
9887 defer metadata_formatter.need_comma = undefined;9739 defer metadata_formatter.need_comma = undefined;
9888 switch (extra.weights) {9740 switch (extra.weights) {
9889 .none => {},9741 .none => {},
9890 .unpredictable => try writer.writeAll("!unpredictable !{}"),9742 .unpredictable => try w.writeAll("!unpredictable !{}"),
9891 _ => try writer.print("{}", .{9743 _ => try w.print("{f}", .{
9892 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),9744 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),
9893 }),9745 }),
9894 }9746 }
...@@ -9905,16 +9757,16 @@ pub fn printUnbuffered(...@@ -9905,16 +9757,16 @@ pub fn printUnbuffered(
9905 var extra =9757 var extra =
9906 function.extraDataTrail(Function.Instruction.Call, instruction.data);9758 function.extraDataTrail(Function.Instruction.Call, instruction.data);
9907 const args = extra.trail.next(extra.data.args_len, Value, &function);9759 const args = extra.trail.next(extra.data.args_len, Value, &function);
9908 try writer.writeAll(" ");9760 try w.writeAll(" ");
9909 const ret_ty = extra.data.ty.functionReturn(self);9761 const ret_ty = extra.data.ty.functionReturn(self);
9910 switch (ret_ty) {9762 switch (ret_ty) {
9911 .void => {},9763 .void => {},
9912 else => try writer.print("%{} = ", .{9764 else => try w.print("%{f} = ", .{
9913 instruction_index.name(&function).fmt(self),9765 instruction_index.name(&function).fmt(self),
9914 }),9766 }),
9915 .none => unreachable,9767 .none => unreachable,
9916 }9768 }
9917 try writer.print("{s}{}{}{} {%} {}(", .{9769 try w.print("{s}{f}{f}{f} {f%} {f}(", .{
9918 @tagName(tag),9770 @tagName(tag),
9919 extra.data.info.call_conv,9771 extra.data.info.call_conv,
9920 extra.data.attributes.ret(self).fmt(self),9772 extra.data.attributes.ret(self).fmt(self),
...@@ -9926,21 +9778,21 @@ pub fn printUnbuffered(...@@ -9926,21 +9778,21 @@ pub fn printUnbuffered(
9926 extra.data.callee.fmt(function_index, self),9778 extra.data.callee.fmt(function_index, self),
9927 });9779 });
9928 for (0.., args) |arg_index, arg| {9780 for (0.., args) |arg_index, arg| {
9929 if (arg_index > 0) try writer.writeAll(", ");9781 if (arg_index > 0) try w.writeAll(", ");
9930 metadata_formatter.need_comma = false;9782 metadata_formatter.need_comma = false;
9931 defer metadata_formatter.need_comma = undefined;9783 defer metadata_formatter.need_comma = undefined;
9932 try writer.print("{%}{}{}", .{9784 try w.print("{f%}{f}{f}", .{
9933 arg.typeOf(function_index, self).fmt(self),9785 arg.typeOf(function_index, self).fmt(self),
9934 extra.data.attributes.param(arg_index, self).fmt(self),9786 extra.data.attributes.param(arg_index, self).fmt(self),
9935 try metadata_formatter.fmtLocal(" ", arg, function_index),9787 try metadata_formatter.fmtLocal(" ", arg, function_index),
9936 });9788 });
9937 }9789 }
9938 try writer.writeByte(')');9790 try w.writeByte(')');
9939 if (extra.data.info.has_op_bundle_cold) {9791 if (extra.data.info.has_op_bundle_cold) {
9940 try writer.writeAll(" [ \"cold\"() ]");9792 try w.writeAll(" [ \"cold\"() ]");
9941 }9793 }
9942 const call_function_attributes = extra.data.attributes.func(self);9794 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}", .{
9944 (try attribute_groups.getOrPutValue(9796 (try attribute_groups.getOrPutValue(
9945 self.gpa,9797 self.gpa,
9946 call_function_attributes,9798 call_function_attributes,
...@@ -9953,7 +9805,7 @@ pub fn printUnbuffered(...@@ -9953,7 +9805,7 @@ pub fn printUnbuffered(
9953 => |tag| {9805 => |tag| {
9954 const extra =9806 const extra =
9955 function.extraData(Function.Instruction.CmpXchg, instruction.data);9807 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, }", .{
9957 instruction_index.name(&function).fmt(self),9809 instruction_index.name(&function).fmt(self),
9958 @tagName(tag),9810 @tagName(tag),
9959 extra.info.access_kind,9811 extra.info.access_kind,
...@@ -9969,7 +9821,7 @@ pub fn printUnbuffered(...@@ -9969,7 +9821,7 @@ pub fn printUnbuffered(
9969 .extractelement => |tag| {9821 .extractelement => |tag| {
9970 const extra =9822 const extra =
9971 function.extraData(Function.Instruction.ExtractElement, instruction.data);9823 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9972 try writer.print(" %{} = {s} {%}, {%}", .{9824 try w.print(" %{f} = {s} {f%}, {f%}", .{
9973 instruction_index.name(&function).fmt(self),9825 instruction_index.name(&function).fmt(self),
9974 @tagName(tag),9826 @tagName(tag),
9975 extra.val.fmt(function_index, self),9827 extra.val.fmt(function_index, self),
...@@ -9982,16 +9834,16 @@ pub fn printUnbuffered(...@@ -9982,16 +9834,16 @@ pub fn printUnbuffered(
9982 instruction.data,9834 instruction.data,
9983 );9835 );
9984 const indices = extra.trail.next(extra.data.indices_len, u32, &function);9836 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9985 try writer.print(" %{} = {s} {%}", .{9837 try w.print(" %{f} = {s} {f%}", .{
9986 instruction_index.name(&function).fmt(self),9838 instruction_index.name(&function).fmt(self),
9987 @tagName(tag),9839 @tagName(tag),
9988 extra.data.val.fmt(function_index, self),9840 extra.data.val.fmt(function_index, self),
9989 });9841 });
9990 for (indices) |index| try writer.print(", {d}", .{index});9842 for (indices) |index| try w.print(", {d}", .{index});
9991 },9843 },
9992 .fence => |tag| {9844 .fence => |tag| {
9993 const info: MemoryAccessInfo = @bitCast(instruction.data);9845 const info: MemoryAccessInfo = @bitCast(instruction.data);
9994 try writer.print(" {s}{ }{ }", .{9846 try w.print(" {s}{f }{f }", .{
9995 @tagName(tag),9847 @tagName(tag),
9996 info.sync_scope,9848 info.sync_scope,
9997 info.success_ordering,9849 info.success_ordering,
...@@ -10001,7 +9853,7 @@ pub fn printUnbuffered(...@@ -10001,7 +9853,7 @@ pub fn printUnbuffered(
10001 .@"fneg fast",9853 .@"fneg fast",
10002 => |tag| {9854 => |tag| {
10003 const val: Value = @enumFromInt(instruction.data);9855 const val: Value = @enumFromInt(instruction.data);
10004 try writer.print(" %{} = {s} {%}", .{9856 try w.print(" %{f} = {s} {f%}", .{
10005 instruction_index.name(&function).fmt(self),9857 instruction_index.name(&function).fmt(self),
10006 @tagName(tag),9858 @tagName(tag),
10007 val.fmt(function_index, self),9859 val.fmt(function_index, self),
...@@ -10015,13 +9867,13 @@ pub fn printUnbuffered(...@@ -10015,13 +9867,13 @@ pub fn printUnbuffered(
10015 instruction.data,9867 instruction.data,
10016 );9868 );
10017 const indices = extra.trail.next(extra.data.indices_len, Value, &function);9869 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
10018 try writer.print(" %{} = {s} {%}, {%}", .{9870 try w.print(" %{f} = {s} {f%}, {f%}", .{
10019 instruction_index.name(&function).fmt(self),9871 instruction_index.name(&function).fmt(self),
10020 @tagName(tag),9872 @tagName(tag),
10021 extra.data.type.fmt(self),9873 extra.data.type.fmt(self),
10022 extra.data.base.fmt(function_index, self),9874 extra.data.base.fmt(function_index, self),
10023 });9875 });
10024 for (indices) |index| try writer.print(", {%}", .{9876 for (indices) |index| try w.print(", {f%}", .{
10025 index.fmt(function_index, self),9877 index.fmt(function_index, self),
10026 });9878 });
10027 },9879 },
...@@ -10030,22 +9882,22 @@ pub fn printUnbuffered(...@@ -10030,22 +9882,22 @@ pub fn printUnbuffered(
10030 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);9882 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);
10031 const targets =9883 const targets =
10032 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);9884 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);
10033 try writer.print(" {s} {%}, [", .{9885 try w.print(" {s} {f%}, [", .{
10034 @tagName(tag),9886 @tagName(tag),
10035 extra.data.addr.fmt(function_index, self),9887 extra.data.addr.fmt(function_index, self),
10036 });9888 });
10037 for (0.., targets) |target_index, target| {9889 for (0.., targets) |target_index, target| {
10038 if (target_index > 0) try writer.writeAll(", ");9890 if (target_index > 0) try w.writeAll(", ");
10039 try writer.print("{%}", .{9891 try w.print("{f%}", .{
10040 target.toInst(&function).fmt(function_index, self),9892 target.toInst(&function).fmt(function_index, self),
10041 });9893 });
10042 }9894 }
10043 try writer.writeByte(']');9895 try w.writeByte(']');
10044 },9896 },
10045 .insertelement => |tag| {9897 .insertelement => |tag| {
10046 const extra =9898 const extra =
10047 function.extraData(Function.Instruction.InsertElement, instruction.data);9899 function.extraData(Function.Instruction.InsertElement, instruction.data);
10048 try writer.print(" %{} = {s} {%}, {%}, {%}", .{9900 try w.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
10049 instruction_index.name(&function).fmt(self),9901 instruction_index.name(&function).fmt(self),
10050 @tagName(tag),9902 @tagName(tag),
10051 extra.val.fmt(function_index, self),9903 extra.val.fmt(function_index, self),
...@@ -10057,19 +9909,19 @@ pub fn printUnbuffered(...@@ -10057,19 +9909,19 @@ pub fn printUnbuffered(
10057 var extra =9909 var extra =
10058 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);9910 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
10059 const indices = extra.trail.next(extra.data.indices_len, u32, &function);9911 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
10060 try writer.print(" %{} = {s} {%}, {%}", .{9912 try w.print(" %{f} = {s} {f%}, {f%}", .{
10061 instruction_index.name(&function).fmt(self),9913 instruction_index.name(&function).fmt(self),
10062 @tagName(tag),9914 @tagName(tag),
10063 extra.data.val.fmt(function_index, self),9915 extra.data.val.fmt(function_index, self),
10064 extra.data.elem.fmt(function_index, self),9916 extra.data.elem.fmt(function_index, self),
10065 });9917 });
10066 for (indices) |index| try writer.print(", {d}", .{index});9918 for (indices) |index| try w.print(", {d}", .{index});
10067 },9919 },
10068 .load,9920 .load,
10069 .@"load atomic",9921 .@"load atomic",
10070 => |tag| {9922 => |tag| {
10071 const extra = function.extraData(Function.Instruction.Load, instruction.data);9923 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, }", .{
10073 instruction_index.name(&function).fmt(self),9925 instruction_index.name(&function).fmt(self),
10074 @tagName(tag),9926 @tagName(tag),
10075 extra.info.access_kind,9927 extra.info.access_kind,
...@@ -10087,14 +9939,14 @@ pub fn printUnbuffered(...@@ -10087,14 +9939,14 @@ pub fn printUnbuffered(
10087 const vals = extra.trail.next(block_incoming_len, Value, &function);9939 const vals = extra.trail.next(block_incoming_len, Value, &function);
10088 const blocks =9940 const blocks =
10089 extra.trail.next(block_incoming_len, Function.Block.Index, &function);9941 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
10090 try writer.print(" %{} = {s} {%} ", .{9942 try w.print(" %{f} = {s} {f%} ", .{
10091 instruction_index.name(&function).fmt(self),9943 instruction_index.name(&function).fmt(self),
10092 @tagName(tag),9944 @tagName(tag),
10093 vals[0].typeOf(function_index, self).fmt(self),9945 vals[0].typeOf(function_index, self).fmt(self),
10094 });9946 });
10095 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {9947 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
10096 if (incoming_index > 0) try writer.writeAll(", ");9948 if (incoming_index > 0) try w.writeAll(", ");
10097 try writer.print("[ {}, {} ]", .{9949 try w.print("[ {f}, {f} ]", .{
10098 incoming_val.fmt(function_index, self),9950 incoming_val.fmt(function_index, self),
10099 incoming_block.toInst(&function).fmt(function_index, self),9951 incoming_block.toInst(&function).fmt(function_index, self),
10100 });9952 });
...@@ -10102,19 +9954,19 @@ pub fn printUnbuffered(...@@ -10102,19 +9954,19 @@ pub fn printUnbuffered(
10102 },9954 },
10103 .ret => |tag| {9955 .ret => |tag| {
10104 const val: Value = @enumFromInt(instruction.data);9956 const val: Value = @enumFromInt(instruction.data);
10105 try writer.print(" {s} {%}", .{9957 try w.print(" {s} {f%}", .{
10106 @tagName(tag),9958 @tagName(tag),
10107 val.fmt(function_index, self),9959 val.fmt(function_index, self),
10108 });9960 });
10109 },9961 },
10110 .@"ret void",9962 .@"ret void",
10111 .@"unreachable",9963 .@"unreachable",
10112 => |tag| try writer.print(" {s}", .{@tagName(tag)}),9964 => |tag| try w.print(" {s}", .{@tagName(tag)}),
10113 .select,9965 .select,
10114 .@"select fast",9966 .@"select fast",
10115 => |tag| {9967 => |tag| {
10116 const extra = function.extraData(Function.Instruction.Select, instruction.data);9968 const extra = function.extraData(Function.Instruction.Select, instruction.data);
10117 try writer.print(" %{} = {s} {%}, {%}, {%}", .{9969 try w.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
10118 instruction_index.name(&function).fmt(self),9970 instruction_index.name(&function).fmt(self),
10119 @tagName(tag),9971 @tagName(tag),
10120 extra.cond.fmt(function_index, self),9972 extra.cond.fmt(function_index, self),
...@@ -10125,7 +9977,7 @@ pub fn printUnbuffered(...@@ -10125,7 +9977,7 @@ pub fn printUnbuffered(
10125 .shufflevector => |tag| {9977 .shufflevector => |tag| {
10126 const extra =9978 const extra =
10127 function.extraData(Function.Instruction.ShuffleVector, instruction.data);9979 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
10128 try writer.print(" %{} = {s} {%}, {%}, {%}", .{9980 try w.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
10129 instruction_index.name(&function).fmt(self),9981 instruction_index.name(&function).fmt(self),
10130 @tagName(tag),9982 @tagName(tag),
10131 extra.lhs.fmt(function_index, self),9983 extra.lhs.fmt(function_index, self),
...@@ -10137,7 +9989,7 @@ pub fn printUnbuffered(...@@ -10137,7 +9989,7 @@ pub fn printUnbuffered(
10137 .@"store atomic",9989 .@"store atomic",
10138 => |tag| {9990 => |tag| {
10139 const extra = function.extraData(Function.Instruction.Store, instruction.data);9991 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, }", .{
10141 @tagName(tag),9993 @tagName(tag),
10142 extra.info.access_kind,9994 extra.info.access_kind,
10143 extra.val.fmt(function_index, self),9995 extra.val.fmt(function_index, self),
...@@ -10153,32 +10005,32 @@ pub fn printUnbuffered(...@@ -10153,32 +10005,32 @@ pub fn printUnbuffered(
10153 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);10005 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
10154 const blocks =10006 const blocks =
10155 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);10007 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", .{
10157 @tagName(tag),10009 @tagName(tag),
10158 extra.data.val.fmt(function_index, self),10010 extra.data.val.fmt(function_index, self),
10159 extra.data.default.toInst(&function).fmt(function_index, self),10011 extra.data.default.toInst(&function).fmt(function_index, self),
10160 });10012 });
10161 for (vals, blocks) |case_val, case_block| try writer.print(10013 for (vals, blocks) |case_val, case_block| try w.print(
10162 " {%}, {%}\n",10014 " {f%}, {f%}\n",
10163 .{10015 .{
10164 case_val.fmt(self),10016 case_val.fmt(self),
10165 case_block.toInst(&function).fmt(function_index, self),10017 case_block.toInst(&function).fmt(function_index, self),
10166 },10018 },
10167 );10019 );
10168 try writer.writeAll(" ]");10020 try w.writeAll(" ]");
10169 metadata_formatter.need_comma = true;10021 metadata_formatter.need_comma = true;
10170 defer metadata_formatter.need_comma = undefined;10022 defer metadata_formatter.need_comma = undefined;
10171 switch (extra.data.weights) {10023 switch (extra.data.weights) {
10172 .none => {},10024 .none => {},
10173 .unpredictable => try writer.writeAll("!unpredictable !{}"),10025 .unpredictable => try w.writeAll("!unpredictable !{}"),
10174 _ => try writer.print("{}", .{10026 _ => try w.print("{f}", .{
10175 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),10027 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),
10176 }),10028 }),
10177 }10029 }
10178 },10030 },
10179 .va_arg => |tag| {10031 .va_arg => |tag| {
10180 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);10032 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
10181 try writer.print(" %{} = {s} {%}, {%}", .{10033 try w.print(" %{f} = {s} {f%}, {f%}", .{
10182 instruction_index.name(&function).fmt(self),10034 instruction_index.name(&function).fmt(self),
10183 @tagName(tag),10035 @tagName(tag),
10184 extra.list.fmt(function_index, self),10036 extra.list.fmt(function_index, self),
...@@ -10188,45 +10040,45 @@ pub fn printUnbuffered(...@@ -10188,45 +10040,45 @@ pub fn printUnbuffered(
10188 }10040 }
1018910041
10190 if (maybe_dbg_index) |dbg_index| {10042 if (maybe_dbg_index) |dbg_index| {
10191 try writer.print(", !dbg !{}", .{dbg_index});10043 try w.print(", !dbg !{d}", .{dbg_index});
10192 }10044 }
10193 try writer.writeByte('\n');10045 try w.writeByte('\n');
10194 }10046 }
10195 try writer.writeByte('}');10047 try w.writeByte('}');
10196 }10048 }
10197 try writer.writeByte('\n');10049 try w.writeByte('\n');
10198 }10050 }
1019910051
10200 if (attribute_groups.count() > 0) {10052 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;
10202 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|10054 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
10203 try writer.print(10055 try w.print(
10204 \\attributes #{d} = {{{#"} }}10056 \\attributes #{d} = {{{f#"} }}
10205 \\10057 \\
10206 , .{ attribute_group_index, attribute_group.fmt(self) });10058 , .{ attribute_group_index, attribute_group.fmt(self) });
10207 }10059 }
1020810060
10209 if (self.metadata_named.count() > 0) {10061 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;
10211 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {10063 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {
10212 const elements: []const Metadata =10064 const elements: []const Metadata =
10213 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);10065 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);
10214 try writer.writeByte('!');10066 try w.writeByte('!');
10215 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer);10067 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, w);
10216 try writer.writeAll(" = !{");10068 try w.writeAll(" = !{");
10217 metadata_formatter.need_comma = false;10069 metadata_formatter.need_comma = false;
10218 defer metadata_formatter.need_comma = undefined;10070 defer metadata_formatter.need_comma = undefined;
10219 for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)});10071 for (elements) |element| try w.print("{f}", .{try metadata_formatter.fmt("", element)});
10220 try writer.writeAll("}\n");10072 try w.writeAll("}\n");
10221 }10073 }
10222 }10074 }
1022310075
10224 if (metadata_formatter.map.count() > 0) {10076 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;
10226 var metadata_index: usize = 0;10078 var metadata_index: usize = 0;
10227 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {10079 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
10228 @setEvalBranchQuota(10_000);10080 @setEvalBranchQuota(10_000);
10229 try writer.print("!{} = ", .{metadata_index});10081 try w.print("!{d} = ", .{metadata_index});
10230 metadata_formatter.need_comma = false;10082 metadata_formatter.need_comma = false;
10231 defer metadata_formatter.need_comma = undefined;10083 defer metadata_formatter.need_comma = undefined;
1023210084
...@@ -10239,7 +10091,7 @@ pub fn printUnbuffered(...@@ -10239,7 +10091,7 @@ pub fn printUnbuffered(
10239 .scope = location.scope,10091 .scope = location.scope,
10240 .inlinedAt = location.inlined_at,10092 .inlinedAt = location.inlined_at,
10241 .isImplicitCode = false,10093 .isImplicitCode = false,
10242 }, writer);10094 }, w);
10243 continue;10095 continue;
10244 },10096 },
10245 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),10097 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),
...@@ -10255,7 +10107,7 @@ pub fn printUnbuffered(...@@ -10255,7 +10107,7 @@ pub fn printUnbuffered(
10255 .checksumkind = null,10107 .checksumkind = null,
10256 .checksum = null,10108 .checksum = null,
10257 .source = null,10109 .source = null,
10258 }, writer);10110 }, w);
10259 },10111 },
10260 .compile_unit,10112 .compile_unit,
10261 .@"compile_unit optimized",10113 .@"compile_unit optimized",
...@@ -10286,7 +10138,7 @@ pub fn printUnbuffered(...@@ -10286,7 +10138,7 @@ pub fn printUnbuffered(
10286 .rangesBaseAddress = null,10138 .rangesBaseAddress = null,
10287 .sysroot = null,10139 .sysroot = null,
10288 .sdk = null,10140 .sdk = null,
10289 }, writer);10141 }, w);
10290 },10142 },
10291 .subprogram,10143 .subprogram,
10292 .@"subprogram local",10144 .@"subprogram local",
...@@ -10320,7 +10172,7 @@ pub fn printUnbuffered(...@@ -10320,7 +10172,7 @@ pub fn printUnbuffered(
10320 .thrownTypes = null,10172 .thrownTypes = null,
10321 .annotations = null,10173 .annotations = null,
10322 .targetFuncName = null,10174 .targetFuncName = null,
10323 }, writer);10175 }, w);
10324 },10176 },
10325 .lexical_block => {10177 .lexical_block => {
10326 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);10178 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);
...@@ -10329,7 +10181,7 @@ pub fn printUnbuffered(...@@ -10329,7 +10181,7 @@ pub fn printUnbuffered(
10329 .file = extra.file,10181 .file = extra.file,
10330 .line = extra.line,10182 .line = extra.line,
10331 .column = extra.column,10183 .column = extra.column,
10332 }, writer);10184 }, w);
10333 },10185 },
10334 .location => {10186 .location => {
10335 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);10187 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);
...@@ -10339,7 +10191,7 @@ pub fn printUnbuffered(...@@ -10339,7 +10191,7 @@ pub fn printUnbuffered(
10339 .scope = extra.scope,10191 .scope = extra.scope,
10340 .inlinedAt = extra.inlined_at,10192 .inlinedAt = extra.inlined_at,
10341 .isImplicitCode = false,10193 .isImplicitCode = false,
10342 }, writer);10194 }, w);
10343 },10195 },
10344 .basic_bool_type,10196 .basic_bool_type,
10345 .basic_unsigned_type,10197 .basic_unsigned_type,
...@@ -10368,7 +10220,7 @@ pub fn printUnbuffered(...@@ -10368,7 +10220,7 @@ pub fn printUnbuffered(
10368 else => unreachable,10220 else => unreachable,
10369 }),10221 }),
10370 .flags = null,10222 .flags = null,
10371 }, writer);10223 }, w);
10372 },10224 },
10373 .composite_struct_type,10225 .composite_struct_type,
10374 .composite_union_type,10226 .composite_union_type,
...@@ -10413,7 +10265,7 @@ pub fn printUnbuffered(...@@ -10413,7 +10265,7 @@ pub fn printUnbuffered(
10413 .allocated = null,10265 .allocated = null,
10414 .rank = null,10266 .rank = null,
10415 .annotations = null,10267 .annotations = null,
10416 }, writer);10268 }, w);
10417 },10269 },
10418 .derived_pointer_type,10270 .derived_pointer_type,
10419 .derived_member_type,10271 .derived_member_type,
...@@ -10446,7 +10298,7 @@ pub fn printUnbuffered(...@@ -10446,7 +10298,7 @@ pub fn printUnbuffered(
10446 .extraData = null,10298 .extraData = null,
10447 .dwarfAddressSpace = null,10299 .dwarfAddressSpace = null,
10448 .annotations = null,10300 .annotations = null,
10449 }, writer);10301 }, w);
10450 },10302 },
10451 .subroutine_type => {10303 .subroutine_type => {
10452 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);10304 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
...@@ -10454,7 +10306,7 @@ pub fn printUnbuffered(...@@ -10454,7 +10306,7 @@ pub fn printUnbuffered(
10454 .flags = null,10306 .flags = null,
10455 .cc = null,10307 .cc = null,
10456 .types = extra.types_tuple,10308 .types = extra.types_tuple,
10457 }, writer);10309 }, w);
10458 },10310 },
10459 .enumerator_unsigned,10311 .enumerator_unsigned,
10460 .enumerator_signed_positive,10312 .enumerator_signed_positive,
...@@ -10504,7 +10356,7 @@ pub fn printUnbuffered(...@@ -10504,7 +10356,7 @@ pub fn printUnbuffered(
10504 => false,10356 => false,
10505 else => unreachable,10357 else => unreachable,
10506 },10358 },
10507 }, writer);10359 }, w);
10508 },10360 },
10509 .subrange => {10361 .subrange => {
10510 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);10362 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);
...@@ -10513,31 +10365,31 @@ pub fn printUnbuffered(...@@ -10513,31 +10365,31 @@ pub fn printUnbuffered(
10513 .lowerBound = extra.lower_bound,10365 .lowerBound = extra.lower_bound,
10514 .upperBound = null,10366 .upperBound = null,
10515 .stride = null,10367 .stride = null,
10516 }, writer);10368 }, w);
10517 },10369 },
10518 .tuple => {10370 .tuple => {
10519 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);10371 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);
10520 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);10372 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10521 try writer.writeAll("!{");10373 try w.writeAll("!{");
10522 for (elements) |element| try writer.print("{[element]%}", .{10374 for (elements) |element| try w.print("{[element]f%}", .{
10523 .element = try metadata_formatter.fmt("", element),10375 .element = try metadata_formatter.fmt("", element),
10524 });10376 });
10525 try writer.writeAll("}\n");10377 try w.writeAll("}\n");
10526 },10378 },
10527 .str_tuple => {10379 .str_tuple => {
10528 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);10380 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);
10529 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);10381 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10530 try writer.print("!{{{[str]%}", .{10382 try w.print("!{{{[str]f%}", .{
10531 .str = try metadata_formatter.fmt("", extra.data.str),10383 .str = try metadata_formatter.fmt("", extra.data.str),
10532 });10384 });
10533 for (elements) |element| try writer.print("{[element]%}", .{10385 for (elements) |element| try w.print("{[element]f%}", .{
10534 .element = try metadata_formatter.fmt("", element),10386 .element = try metadata_formatter.fmt("", element),
10535 });10387 });
10536 try writer.writeAll("}\n");10388 try w.writeAll("}\n");
10537 },10389 },
10538 .module_flag => {10390 .module_flag => {
10539 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);10391 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", .{
10541 .behavior = try metadata_formatter.fmt("", extra.behavior),10393 .behavior = try metadata_formatter.fmt("", extra.behavior),
10542 .name = try metadata_formatter.fmt("", extra.name),10394 .name = try metadata_formatter.fmt("", extra.name),
10543 .constant = try metadata_formatter.fmt("", extra.constant),10395 .constant = try metadata_formatter.fmt("", extra.constant),
...@@ -10555,7 +10407,7 @@ pub fn printUnbuffered(...@@ -10555,7 +10407,7 @@ pub fn printUnbuffered(
10555 .flags = null,10407 .flags = null,
10556 .@"align" = null,10408 .@"align" = null,
10557 .annotations = null,10409 .annotations = null,
10558 }, writer);10410 }, w);
10559 },10411 },
10560 .parameter => {10412 .parameter => {
10561 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);10413 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);
...@@ -10569,7 +10421,7 @@ pub fn printUnbuffered(...@@ -10569,7 +10421,7 @@ pub fn printUnbuffered(
10569 .flags = null,10421 .flags = null,
10570 .@"align" = null,10422 .@"align" = null,
10571 .annotations = null,10423 .annotations = null,
10572 }, writer);10424 }, w);
10573 },10425 },
10574 .global_var,10426 .global_var,
10575 .@"global_var local",10427 .@"global_var local",
...@@ -10592,7 +10444,7 @@ pub fn printUnbuffered(...@@ -10592,7 +10444,7 @@ pub fn printUnbuffered(
10592 .templateParams = null,10444 .templateParams = null,
10593 .@"align" = null,10445 .@"align" = null,
10594 .annotations = null,10446 .annotations = null,
10595 }, writer);10447 }, w);
10596 },10448 },
10597 .global_var_expression => {10449 .global_var_expression => {
10598 const extra =10450 const extra =
...@@ -10600,7 +10452,7 @@ pub fn printUnbuffered(...@@ -10600,7 +10452,7 @@ pub fn printUnbuffered(
10600 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{10452 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{
10601 .@"var" = extra.variable,10453 .@"var" = extra.variable,
10602 .expr = extra.expression,10454 .expr = extra.expression,
10603 }, writer);10455 }, w);
10604 },10456 },
10605 }10457 }
10606 }10458 }
...@@ -10619,22 +10471,18 @@ fn isValidIdentifier(id: []const u8) bool {...@@ -10619,22 +10471,18 @@ fn isValidIdentifier(id: []const u8) bool {
10619}10471}
1062010472
10621const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };10473const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };
10622fn printEscapedString(10474fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, w: *Writer) Writer.Error!void {
10623 slice: []const u8,
10624 quotes: QuoteBehavior,
10625 writer: anytype,
10626) @TypeOf(writer).Error!void {
10627 const need_quotes = switch (quotes) {10475 const need_quotes = switch (quotes) {
10628 .always_quote => true,10476 .always_quote => true,
10629 .quote_unless_valid_identifier => !isValidIdentifier(slice),10477 .quote_unless_valid_identifier => !isValidIdentifier(slice),
10630 };10478 };
10631 if (need_quotes) try writer.writeByte('"');10479 if (need_quotes) try w.writeByte('"');
10632 for (slice) |byte| switch (byte) {10480 for (slice) |byte| switch (byte) {
10633 '\\' => try writer.writeAll("\\\\"),10481 '\\' => try w.writeAll("\\\\"),
10634 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(byte),10482 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try w.writeByte(byte),
10635 else => try writer.print("\\{X:0>2}", .{byte}),10483 else => try w.print("\\{X:0>2}", .{byte}),
10636 };10484 };
10637 if (need_quotes) try writer.writeByte('"');10485 if (need_quotes) try w.writeByte('"');
10638}10486}
1063910487
10640fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {10488fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {
...@@ -12019,7 +11867,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:...@@ -12019,7 +11867,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:
12019}11867}
1202011868
12021pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {11869pub 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);
12023 return self.trailingMetadataStringAssumeCapacity();11871 return self.trailingMetadataStringAssumeCapacity();
12024}11872}
1202511873
...@@ -15261,13 +15109,3 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -15261,13 +15109,3 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1526115109
15262 return bitcode.toOwnedSlice();15110 return bitcode.toOwnedSlice();
15263}15111}
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" {...@@ -6324,7 +6324,7 @@ test "ampersand" {
6324var fixed_buffer_mem: [100 * 1024]u8 = undefined;6324var fixed_buffer_mem: [100 * 1024]u8 = undefined;
63256325
6326fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {6326fn 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
6329 var tree = try std.zig.Ast.parse(allocator, source, .zig);6329 var tree = try std.zig.Ast.parse(allocator, source, .zig);
6330 defer tree.deinit(allocator);6330 defer tree.deinit(allocator);
lib/std/zig/perf_test.zig+1-1
...@@ -23,7 +23,7 @@ pub fn main() !void {...@@ -23,7 +23,7 @@ pub fn main() !void {
23 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));23 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));
2424
25 var stdout_file: std.fs.File = .stdout();25 var stdout_file: std.fs.File = .stdout();
26 const stdout = stdout_file.writer();26 const stdout = stdout_file.deprecatedWriter();
27 try stdout.print("parsing speed: {:.2}/s, {:.2} used \n", .{27 try stdout.print("parsing speed: {:.2}/s, {:.2} used \n", .{
28 fmtIntSizeBin(bytes_per_sec),28 fmtIntSizeBin(bytes_per_sec),
29 fmtIntSizeBin(memory_used),29 fmtIntSizeBin(memory_used),
lib/std/zig/render.zig+3-3
...@@ -1564,7 +1564,7 @@ fn renderBuiltinCall(...@@ -1564,7 +1564,7 @@ fn renderBuiltinCall(
1564 defer r.gpa.free(new_string);1564 defer r.gpa.free(new_string);
15651565
1566 try renderToken(r, builtin_token + 1, .none); // (1566 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)});
1568 return renderToken(r, str_lit_token + 1, space); // )1568 return renderToken(r, str_lit_token + 1, space); // )
1569 }1569 }
1570 }1570 }
...@@ -2872,7 +2872,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {...@@ -2872,7 +2872,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
2872 .success => |codepoint| {2872 .success => |codepoint| {
2873 if (codepoint <= 0x7f) {2873 if (codepoint <= 0x7f) {
2874 const buf = [1]u8{@as(u8, @intCast(codepoint))};2874 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)});
2876 } else {2876 } else {
2877 try writer.writeAll(escape_sequence);2877 try writer.writeAll(escape_sequence);
2878 }2878 }
...@@ -2884,7 +2884,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {...@@ -2884,7 +2884,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
2884 },2884 },
2885 0x00...('\\' - 1), ('\\' + 1)...0x7f => {2885 0x00...('\\' - 1), ('\\' + 1)...0x7f => {
2886 const buf = [1]u8{byte};2886 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)});
2888 pos += 1;2888 pos += 1;
2889 },2889 },
2890 0x80...0xff => {2890 0x80...0xff => {
lib/std/zig/string_literal.zig+2-9
...@@ -44,14 +44,7 @@ pub const Error = union(enum) {...@@ -44,14 +44,7 @@ pub const Error = union(enum) {
44 raw_string: []const u8,44 raw_string: []const u8,
45 };45 };
4646
47 fn formatMessage(47 fn formatMessage(self: FormatMessage, writer: *std.io.Writer) std.io.Writer.Error!void {
48 self: FormatMessage,
49 comptime f: []const u8,
50 options: std.fmt.FormatOptions,
51 writer: anytype,
52 ) !void {
53 _ = f;
54 _ = options;
55 switch (self.err) {48 switch (self.err) {
56 .invalid_escape_character => |bad_index| try writer.print(49 .invalid_escape_character => |bad_index| try writer.print(
57 "invalid escape character: '{c}'",50 "invalid escape character: '{c}'",
...@@ -93,7 +86,7 @@ pub const Error = union(enum) {...@@ -93,7 +86,7 @@ pub const Error = union(enum) {
93 }86 }
94 }87 }
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) {
97 return .{ .data = .{90 return .{ .data = .{
98 .err = self,91 .err = self,
99 .raw_string = raw_string,92 .raw_string = raw_string,
lib/std/zip.zig+1-1
...@@ -557,7 +557,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -557,7 +557,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
557 self.compression_method,557 self.compression_method,
558 self.uncompressed_size,558 self.uncompressed_size,
559 limited_reader.reader(),559 limited_reader.reader(),
560 out_file.writer(),560 out_file.deprecatedWriter(),
561 );561 );
562 if (limited_reader.bytes_left != 0)562 if (limited_reader.bytes_left != 0)
563 return error.ZipDecompressTruncated;563 return error.ZipDecompressTruncated;
lib/std/zip/test.zig+1-1
...@@ -33,7 +33,7 @@ pub fn expectFiles(...@@ -33,7 +33,7 @@ pub fn expectFiles(
33 var file = try dir.openFile(normalized_sub_path, .{});33 var file = try dir.openFile(normalized_sub_path, .{});
34 defer file.close();34 defer file.close();
35 var content_buf: [4096]u8 = undefined;35 var content_buf: [4096]u8 = undefined;
36 const n = try file.reader().readAll(&content_buf);36 const n = try file.deprecatedReader().readAll(&content_buf);
37 try testing.expectEqualStrings(test_file.content, content_buf[0..n]);37 try testing.expectEqualStrings(test_file.content, content_buf[0..n]);
38 }38 }
39}39}
lib/std/zon/parse.zig+112-130
...@@ -64,22 +64,14 @@ pub const Error = union(enum) {...@@ -64,22 +64,14 @@ pub const Error = union(enum) {
64 }64 }
65 };65 };
6666
67 fn formatMessage(67 fn formatMessage(self: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
68 self: []const u8,
69 comptime f: []const u8,
70 options: std.fmt.FormatOptions,
71 writer: anytype,
72 ) !void {
73 _ = f;
74 _ = options;
75
76 // Just writes the string for now, but we're keeping this behind a formatter so we have68 // Just writes the string for now, but we're keeping this behind a formatter so we have
77 // the option to extend it in the future to print more advanced messages (like `Error`69 // the option to extend it in the future to print more advanced messages (like `Error`
78 // does) without breaking the API.70 // does) without breaking the API.
79 try writer.writeAll(self);71 try w.writeAll(self);
80 }72 }
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) {
83 return .{ .data = switch (self) {75 return .{ .data = switch (self) {
84 .zoir => |note| note.msg.get(diag.zoir),76 .zoir => |note| note.msg.get(diag.zoir),
85 .type_check => |note| note.msg,77 .type_check => |note| note.msg,
...@@ -155,21 +147,14 @@ pub const Error = union(enum) {...@@ -155,21 +147,14 @@ pub const Error = union(enum) {
155 diag: *const Diagnostics,147 diag: *const Diagnostics,
156 };148 };
157149
158 fn formatMessage(150 fn formatMessage(self: FormatMessage, w: *std.io.Writer) std.io.Writer.Error!void {
159 self: FormatMessage,
160 comptime f: []const u8,
161 options: std.fmt.FormatOptions,
162 writer: anytype,
163 ) !void {
164 _ = f;
165 _ = options;
166 switch (self.err) {151 switch (self.err) {
167 .zoir => |err| try writer.writeAll(err.msg.get(self.diag.zoir)),152 .zoir => |err| try w.writeAll(err.msg.get(self.diag.zoir)),
168 .type_check => |tc| try writer.writeAll(tc.message),153 .type_check => |tc| try w.writeAll(tc.message),
169 }154 }
170 }155 }
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) {
173 return .{ .data = .{158 return .{ .data = .{
174 .err = self,159 .err = self,
175 .diag = diag,160 .diag = diag,
...@@ -241,25 +226,19 @@ pub const Diagnostics = struct {...@@ -241,25 +226,19 @@ pub const Diagnostics = struct {
241 return .{ .diag = self };226 return .{ .diag = self };
242 }227 }
243228
244 pub fn format(229 pub fn format(self: *const @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
245 self: *const @This(),230 comptime assert(fmt.len == 0);
246 comptime fmt: []const u8,
247 options: std.fmt.FormatOptions,
248 writer: anytype,
249 ) !void {
250 _ = fmt;
251 _ = options;
252 var errors = self.iterateErrors();231 var errors = self.iterateErrors();
253 while (errors.next()) |err| {232 while (errors.next()) |err| {
254 const loc = err.getLocation(self);233 const loc = err.getLocation(self);
255 const msg = err.fmtMessage(self);234 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
258 var notes = err.iterateNotes(self);237 var notes = err.iterateNotes(self);
259 while (notes.next()) |note| {238 while (notes.next()) |note| {
260 const note_loc = note.getLocation(self);239 const note_loc = note.getLocation(self);
261 const note_msg = note.fmtMessage(self);240 const note_msg = note.fmtMessage(self);
262 try writer.print("{}:{}: note: {s}\n", .{241 try w.print("{d}:{d}: note: {f}\n", .{
263 note_loc.line + 1,242 note_loc.line + 1,
264 note_loc.column + 1,243 note_loc.column + 1,
265 note_msg,244 note_msg,
...@@ -646,7 +625,7 @@ const Parser = struct {...@@ -646,7 +625,7 @@ const Parser = struct {
646 .failure => |err| {625 .failure => |err| {
647 const token = self.ast.nodeMainToken(ast_node);626 const token = self.ast.nodeMainToken(ast_node);
648 const raw_string = self.ast.tokenSlice(token);627 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)});
650 },629 },
651 }630 }
652631
...@@ -1087,7 +1066,10 @@ const Parser = struct {...@@ -1087,7 +1066,10 @@ const Parser = struct {
1087 try writer.writeAll(msg);1066 try writer.writeAll(msg);
1088 inline for (info.fields, 0..) |field_info, i| {1067 inline for (info.fields, 0..) |field_info, i| {
1089 if (i != 0) try writer.writeAll(", ");1068 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 })});
1091 }1073 }
1092 break :b .{1074 break :b .{
1093 .token = token,1075 .token = token,
...@@ -1298,7 +1280,7 @@ test "std.zon ast errors" {...@@ -1298,7 +1280,7 @@ test "std.zon ast errors" {
1298 error.ParseZon,1280 error.ParseZon,
1299 fromSlice(struct {}, gpa, ".{.x = 1 .y = 2}", &diag, .{}),1281 fromSlice(struct {}, gpa, ".{.x = 1 .y = 2}", &diag, .{}),
1300 );1282 );
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});
1302}1284}
13031285
1304test "std.zon comments" {1286test "std.zon comments" {
...@@ -1320,7 +1302,7 @@ test "std.zon comments" {...@@ -1320,7 +1302,7 @@ test "std.zon comments" {
1320 , &diag, .{}));1302 , &diag, .{}));
1321 try std.testing.expectFmt(1303 try std.testing.expectFmt(
1322 "1:1: error: expected expression, found 'a document comment'\n",1304 "1:1: error: expected expression, found 'a document comment'\n",
1323 "{}",1305 "{f}",
1324 .{diag},1306 .{diag},
1325 );1307 );
1326 }1308 }
...@@ -1341,7 +1323,7 @@ test "std.zon failure/oom formatting" {...@@ -1341,7 +1323,7 @@ test "std.zon failure/oom formatting" {
1341 &diag,1323 &diag,
1342 .{},1324 .{},
1343 ));1325 ));
1344 try std.testing.expectFmt("", "{}", .{diag});1326 try std.testing.expectFmt("", "{f}", .{diag});
1345}1327}
13461328
1347test "std.zon fromSlice syntax error" {1329test "std.zon fromSlice syntax error" {
...@@ -1421,7 +1403,7 @@ test "std.zon unions" {...@@ -1421,7 +1403,7 @@ test "std.zon unions" {
1421 \\1:4: note: supported: 'x', 'y'1403 \\1:4: note: supported: 'x', 'y'
1422 \\1404 \\
1423 ,1405 ,
1424 "{}",1406 "{f}",
1425 .{diag},1407 .{diag},
1426 );1408 );
1427 }1409 }
...@@ -1435,7 +1417,7 @@ test "std.zon unions" {...@@ -1435,7 +1417,7 @@ test "std.zon unions" {
1435 error.ParseZon,1417 error.ParseZon,
1436 fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),1418 fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),
1437 );1419 );
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});
1439 }1421 }
14401422
1441 // Extra field1423 // Extra field
...@@ -1447,7 +1429,7 @@ test "std.zon unions" {...@@ -1447,7 +1429,7 @@ test "std.zon unions" {
1447 error.ParseZon,1429 error.ParseZon,
1448 fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),1430 fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
1449 );1431 );
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});
1451 }1433 }
14521434
1453 // No fields1435 // No fields
...@@ -1459,7 +1441,7 @@ test "std.zon unions" {...@@ -1459,7 +1441,7 @@ test "std.zon unions" {
1459 error.ParseZon,1441 error.ParseZon,
1460 fromSlice(Union, gpa, ".{}", &diag, .{}),1442 fromSlice(Union, gpa, ".{}", &diag, .{}),
1461 );1443 );
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});
1463 }1445 }
14641446
1465 // Enum literals cannot coerce into untagged unions1447 // Enum literals cannot coerce into untagged unions
...@@ -1468,7 +1450,7 @@ test "std.zon unions" {...@@ -1468,7 +1450,7 @@ test "std.zon unions" {
1468 var diag: Diagnostics = .{};1450 var diag: Diagnostics = .{};
1469 defer diag.deinit(gpa);1451 defer diag.deinit(gpa);
1470 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));1452 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});
1472 }1454 }
14731455
1474 // Unknown field for enum literal coercion1456 // Unknown field for enum literal coercion
...@@ -1482,7 +1464,7 @@ test "std.zon unions" {...@@ -1482,7 +1464,7 @@ test "std.zon unions" {
1482 \\1:2: note: supported: 'x'1464 \\1:2: note: supported: 'x'
1483 \\1465 \\
1484 ,1466 ,
1485 "{}",1467 "{f}",
1486 .{diag},1468 .{diag},
1487 );1469 );
1488 }1470 }
...@@ -1493,7 +1475,7 @@ test "std.zon unions" {...@@ -1493,7 +1475,7 @@ test "std.zon unions" {
1493 var diag: Diagnostics = .{};1475 var diag: Diagnostics = .{};
1494 defer diag.deinit(gpa);1476 defer diag.deinit(gpa);
1495 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));1477 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});
1497 }1479 }
1498}1480}
14991481
...@@ -1549,7 +1531,7 @@ test "std.zon structs" {...@@ -1549,7 +1531,7 @@ test "std.zon structs" {
1549 \\1:12: note: supported: 'x', 'y'1531 \\1:12: note: supported: 'x', 'y'
1550 \\1532 \\
1551 ,1533 ,
1552 "{}",1534 "{f}",
1553 .{diag},1535 .{diag},
1554 );1536 );
1555 }1537 }
...@@ -1567,7 +1549,7 @@ test "std.zon structs" {...@@ -1567,7 +1549,7 @@ test "std.zon structs" {
1567 \\1:4: error: duplicate struct field name1549 \\1:4: error: duplicate struct field name
1568 \\1:12: note: duplicate name here1550 \\1:12: note: duplicate name here
1569 \\1551 \\
1570 , "{}", .{diag});1552 , "{f}", .{diag});
1571 }1553 }
15721554
1573 // Ignore unknown fields1555 // Ignore unknown fields
...@@ -1592,7 +1574,7 @@ test "std.zon structs" {...@@ -1592,7 +1574,7 @@ test "std.zon structs" {
1592 \\1:4: error: unexpected field 'x'1574 \\1:4: error: unexpected field 'x'
1593 \\1:4: note: none expected1575 \\1:4: note: none expected
1594 \\1576 \\
1595 , "{}", .{diag});1577 , "{f}", .{diag});
1596 }1578 }
15971579
1598 // Missing field1580 // Missing field
...@@ -1604,7 +1586,7 @@ test "std.zon structs" {...@@ -1604,7 +1586,7 @@ test "std.zon structs" {
1604 error.ParseZon,1586 error.ParseZon,
1605 fromSlice(Vec2, gpa, ".{.x=1.5}", &diag, .{}),1587 fromSlice(Vec2, gpa, ".{.x=1.5}", &diag, .{}),
1606 );1588 );
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});
1608 }1590 }
16091591
1610 // Default field1592 // Default field
...@@ -1631,7 +1613,7 @@ test "std.zon structs" {...@@ -1631,7 +1613,7 @@ test "std.zon structs" {
1631 try std.testing.expectFmt(1613 try std.testing.expectFmt(
1632 \\1:18: error: cannot initialize comptime field1614 \\1:18: error: cannot initialize comptime field
1633 \\1615 \\
1634 , "{}", .{diag});1616 , "{f}", .{diag});
1635 }1617 }
16361618
1637 // Enum field (regression test, we were previously getting the field name in an1619 // Enum field (regression test, we were previously getting the field name in an
...@@ -1661,7 +1643,7 @@ test "std.zon structs" {...@@ -1661,7 +1643,7 @@ test "std.zon structs" {
1661 \\1:1: error: types are not available in ZON1643 \\1:1: error: types are not available in ZON
1662 \\1:1: note: replace the type with '.'1644 \\1:1: note: replace the type with '.'
1663 \\1645 \\
1664 , "{}", .{diag});1646 , "{f}", .{diag});
1665 }1647 }
16661648
1667 // Arrays1649 // Arrays
...@@ -1674,7 +1656,7 @@ test "std.zon structs" {...@@ -1674,7 +1656,7 @@ test "std.zon structs" {
1674 \\1:1: error: types are not available in ZON1656 \\1:1: error: types are not available in ZON
1675 \\1:1: note: replace the type with '.'1657 \\1:1: note: replace the type with '.'
1676 \\1658 \\
1677 , "{}", .{diag});1659 , "{f}", .{diag});
1678 }1660 }
16791661
1680 // Slices1662 // Slices
...@@ -1687,7 +1669,7 @@ test "std.zon structs" {...@@ -1687,7 +1669,7 @@ test "std.zon structs" {
1687 \\1:1: error: types are not available in ZON1669 \\1:1: error: types are not available in ZON
1688 \\1:1: note: replace the type with '.'1670 \\1:1: note: replace the type with '.'
1689 \\1671 \\
1690 , "{}", .{diag});1672 , "{f}", .{diag});
1691 }1673 }
16921674
1693 // Tuples1675 // Tuples
...@@ -1706,7 +1688,7 @@ test "std.zon structs" {...@@ -1706,7 +1688,7 @@ test "std.zon structs" {
1706 \\1:1: error: types are not available in ZON1688 \\1:1: error: types are not available in ZON
1707 \\1:1: note: replace the type with '.'1689 \\1:1: note: replace the type with '.'
1708 \\1690 \\
1709 , "{}", .{diag});1691 , "{f}", .{diag});
1710 }1692 }
17111693
1712 // Nested1694 // Nested
...@@ -1719,7 +1701,7 @@ test "std.zon structs" {...@@ -1719,7 +1701,7 @@ test "std.zon structs" {
1719 \\1:9: error: types are not available in ZON1701 \\1:9: error: types are not available in ZON
1720 \\1:9: note: replace the type with '.'1702 \\1:9: note: replace the type with '.'
1721 \\1703 \\
1722 , "{}", .{diag});1704 , "{f}", .{diag});
1723 }1705 }
1724 }1706 }
1725}1707}
...@@ -1764,7 +1746,7 @@ test "std.zon tuples" {...@@ -1764,7 +1746,7 @@ test "std.zon tuples" {
1764 error.ParseZon,1746 error.ParseZon,
1765 fromSlice(Tuple, gpa, ".{0.5, true, 123}", &diag, .{}),1747 fromSlice(Tuple, gpa, ".{0.5, true, 123}", &diag, .{}),
1766 );1748 );
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});
1768 }1750 }
17691751
1770 // Extra field1752 // Extra field
...@@ -1778,7 +1760,7 @@ test "std.zon tuples" {...@@ -1778,7 +1760,7 @@ test "std.zon tuples" {
1778 );1760 );
1779 try std.testing.expectFmt(1761 try std.testing.expectFmt(
1780 "1:2: error: missing tuple field with index 1\n",1762 "1:2: error: missing tuple field with index 1\n",
1781 "{}",1763 "{f}",
1782 .{diag},1764 .{diag},
1783 );1765 );
1784 }1766 }
...@@ -1792,7 +1774,7 @@ test "std.zon tuples" {...@@ -1792,7 +1774,7 @@ test "std.zon tuples" {
1792 error.ParseZon,1774 error.ParseZon,
1793 fromSlice(Tuple, gpa, ".{.foo = 10.0}", &diag, .{}),1775 fromSlice(Tuple, gpa, ".{.foo = 10.0}", &diag, .{}),
1794 );1776 );
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});
1796 }1778 }
17971779
1798 // Struct with missing field names1780 // Struct with missing field names
...@@ -1804,7 +1786,7 @@ test "std.zon tuples" {...@@ -1804,7 +1786,7 @@ test "std.zon tuples" {
1804 error.ParseZon,1786 error.ParseZon,
1805 fromSlice(Struct, gpa, ".{10.0}", &diag, .{}),1787 fromSlice(Struct, gpa, ".{10.0}", &diag, .{}),
1806 );1788 );
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});
1808 }1790 }
18091791
1810 // Comptime field1792 // Comptime field
...@@ -1824,7 +1806,7 @@ test "std.zon tuples" {...@@ -1824,7 +1806,7 @@ test "std.zon tuples" {
1824 try std.testing.expectFmt(1806 try std.testing.expectFmt(
1825 \\1:9: error: cannot initialize comptime field1807 \\1:9: error: cannot initialize comptime field
1826 \\1808 \\
1827 , "{}", .{diag});1809 , "{f}", .{diag});
1828 }1810 }
1829}1811}
18301812
...@@ -1936,7 +1918,7 @@ test "std.zon arrays and slices" {...@@ -1936,7 +1918,7 @@ test "std.zon arrays and slices" {
1936 );1918 );
1937 try std.testing.expectFmt(1919 try std.testing.expectFmt(
1938 "1:3: error: index 0 outside of array of length 0\n",1920 "1:3: error: index 0 outside of array of length 0\n",
1939 "{}",1921 "{f}",
1940 .{diag},1922 .{diag},
1941 );1923 );
1942 }1924 }
...@@ -1951,7 +1933,7 @@ test "std.zon arrays and slices" {...@@ -1951,7 +1933,7 @@ test "std.zon arrays and slices" {
1951 );1933 );
1952 try std.testing.expectFmt(1934 try std.testing.expectFmt(
1953 "1:8: error: index 1 outside of array of length 1\n",1935 "1:8: error: index 1 outside of array of length 1\n",
1954 "{}",1936 "{f}",
1955 .{diag},1937 .{diag},
1956 );1938 );
1957 }1939 }
...@@ -1966,7 +1948,7 @@ test "std.zon arrays and slices" {...@@ -1966,7 +1948,7 @@ test "std.zon arrays and slices" {
1966 );1948 );
1967 try std.testing.expectFmt(1949 try std.testing.expectFmt(
1968 "1:2: error: expected 2 array elements; found 1\n",1950 "1:2: error: expected 2 array elements; found 1\n",
1969 "{}",1951 "{f}",
1970 .{diag},1952 .{diag},
1971 );1953 );
1972 }1954 }
...@@ -1981,7 +1963,7 @@ test "std.zon arrays and slices" {...@@ -1981,7 +1963,7 @@ test "std.zon arrays and slices" {
1981 );1963 );
1982 try std.testing.expectFmt(1964 try std.testing.expectFmt(
1983 "1:2: error: expected 3 array elements; found 0\n",1965 "1:2: error: expected 3 array elements; found 0\n",
1984 "{}",1966 "{f}",
1985 .{diag},1967 .{diag},
1986 );1968 );
1987 }1969 }
...@@ -1996,7 +1978,7 @@ test "std.zon arrays and slices" {...@@ -1996,7 +1978,7 @@ test "std.zon arrays and slices" {
1996 error.ParseZon,1978 error.ParseZon,
1997 fromSlice([3]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),1979 fromSlice([3]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
1998 );1980 );
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});
2000 }1982 }
20011983
2002 // Slice1984 // Slice
...@@ -2007,7 +1989,7 @@ test "std.zon arrays and slices" {...@@ -2007,7 +1989,7 @@ test "std.zon arrays and slices" {
2007 error.ParseZon,1989 error.ParseZon,
2008 fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),1990 fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
2009 );1991 );
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});
2011 }1993 }
2012 }1994 }
20131995
...@@ -2021,7 +2003,7 @@ test "std.zon arrays and slices" {...@@ -2021,7 +2003,7 @@ test "std.zon arrays and slices" {
2021 error.ParseZon,2003 error.ParseZon,
2022 fromSlice([3]u8, gpa, "'a'", &diag, .{}),2004 fromSlice([3]u8, gpa, "'a'", &diag, .{}),
2023 );2005 );
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});
2025 }2007 }
20262008
2027 // Slice2009 // Slice
...@@ -2032,7 +2014,7 @@ test "std.zon arrays and slices" {...@@ -2032,7 +2014,7 @@ test "std.zon arrays and slices" {
2032 error.ParseZon,2014 error.ParseZon,
2033 fromSlice([]u8, gpa, "'a'", &diag, .{}),2015 fromSlice([]u8, gpa, "'a'", &diag, .{}),
2034 );2016 );
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});
2036 }2018 }
2037 }2019 }
20382020
...@@ -2046,7 +2028,7 @@ test "std.zon arrays and slices" {...@@ -2046,7 +2028,7 @@ test "std.zon arrays and slices" {
2046 );2028 );
2047 try std.testing.expectFmt(2029 try std.testing.expectFmt(
2048 "1:3: error: pointers are not available in ZON\n",2030 "1:3: error: pointers are not available in ZON\n",
2049 "{}",2031 "{f}",
2050 .{diag},2032 .{diag},
2051 );2033 );
2052 }2034 }
...@@ -2085,7 +2067,7 @@ test "std.zon string literal" {...@@ -2085,7 +2067,7 @@ test "std.zon string literal" {
2085 error.ParseZon,2067 error.ParseZon,
2086 fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),2068 fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),
2087 );2069 );
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});
2089 }2071 }
20902072
2091 {2073 {
...@@ -2095,7 +2077,7 @@ test "std.zon string literal" {...@@ -2095,7 +2077,7 @@ test "std.zon string literal" {
2095 error.ParseZon,2077 error.ParseZon,
2096 fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),2078 fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),
2097 );2079 );
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});
2099 }2081 }
2100 }2082 }
21012083
...@@ -2112,7 +2094,7 @@ test "std.zon string literal" {...@@ -2112,7 +2094,7 @@ test "std.zon string literal" {
2112 error.ParseZon,2094 error.ParseZon,
2113 fromSlice([4:0]u8, gpa, "\"abcd\"", &diag, .{}),2095 fromSlice([4:0]u8, gpa, "\"abcd\"", &diag, .{}),
2114 );2096 );
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});
2116 }2098 }
21172099
2118 {2100 {
...@@ -2122,7 +2104,7 @@ test "std.zon string literal" {...@@ -2122,7 +2104,7 @@ test "std.zon string literal" {
2122 error.ParseZon,2104 error.ParseZon,
2123 fromSlice([4:0]u8, gpa, "\\\\abcd", &diag, .{}),2105 fromSlice([4:0]u8, gpa, "\\\\abcd", &diag, .{}),
2124 );2106 );
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});
2126 }2108 }
2127 }2109 }
21282110
...@@ -2164,7 +2146,7 @@ test "std.zon string literal" {...@@ -2164,7 +2146,7 @@ test "std.zon string literal" {
2164 error.ParseZon,2146 error.ParseZon,
2165 fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),2147 fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),
2166 );2148 );
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});
2168 }2150 }
21692151
2170 {2152 {
...@@ -2174,7 +2156,7 @@ test "std.zon string literal" {...@@ -2174,7 +2156,7 @@ test "std.zon string literal" {
2174 error.ParseZon,2156 error.ParseZon,
2175 fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),2157 fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),
2176 );2158 );
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});
2178 }2160 }
2179 }2161 }
21802162
...@@ -2186,7 +2168,7 @@ test "std.zon string literal" {...@@ -2186,7 +2168,7 @@ test "std.zon string literal" {
2186 error.ParseZon,2168 error.ParseZon,
2187 fromSlice([]const u8, gpa, "true", &diag, .{}),2169 fromSlice([]const u8, gpa, "true", &diag, .{}),
2188 );2170 );
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});
2190 }2172 }
21912173
2192 // Expecting string literal, getting an incompatible tuple2174 // Expecting string literal, getting an incompatible tuple
...@@ -2197,7 +2179,7 @@ test "std.zon string literal" {...@@ -2197,7 +2179,7 @@ test "std.zon string literal" {
2197 error.ParseZon,2179 error.ParseZon,
2198 fromSlice([]const u8, gpa, ".{false}", &diag, .{}),2180 fromSlice([]const u8, gpa, ".{false}", &diag, .{}),
2199 );2181 );
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});
2201 }2183 }
22022184
2203 // Invalid string literal2185 // Invalid string literal
...@@ -2208,7 +2190,7 @@ test "std.zon string literal" {...@@ -2208,7 +2190,7 @@ test "std.zon string literal" {
2208 error.ParseZon,2190 error.ParseZon,
2209 fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),2191 fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),
2210 );2192 );
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});
2212 }2194 }
22132195
2214 // Slice wrong child type2196 // Slice wrong child type
...@@ -2220,7 +2202,7 @@ test "std.zon string literal" {...@@ -2220,7 +2202,7 @@ test "std.zon string literal" {
2220 error.ParseZon,2202 error.ParseZon,
2221 fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),2203 fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),
2222 );2204 );
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});
2224 }2206 }
22252207
2226 {2208 {
...@@ -2230,7 +2212,7 @@ test "std.zon string literal" {...@@ -2230,7 +2212,7 @@ test "std.zon string literal" {
2230 error.ParseZon,2212 error.ParseZon,
2231 fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),2213 fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),
2232 );2214 );
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});
2234 }2216 }
2235 }2217 }
22362218
...@@ -2243,7 +2225,7 @@ test "std.zon string literal" {...@@ -2243,7 +2225,7 @@ test "std.zon string literal" {
2243 error.ParseZon,2225 error.ParseZon,
2244 fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),2226 fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
2245 );2227 );
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});
2247 }2229 }
22482230
2249 {2231 {
...@@ -2253,7 +2235,7 @@ test "std.zon string literal" {...@@ -2253,7 +2235,7 @@ test "std.zon string literal" {
2253 error.ParseZon,2235 error.ParseZon,
2254 fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),2236 fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
2255 );2237 );
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});
2257 }2239 }
2258 }2240 }
22592241
...@@ -2327,7 +2309,7 @@ test "std.zon enum literals" {...@@ -2327,7 +2309,7 @@ test "std.zon enum literals" {
2327 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2309 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2328 \\2310 \\
2329 ,2311 ,
2330 "{}",2312 "{f}",
2331 .{diag},2313 .{diag},
2332 );2314 );
2333 }2315 }
...@@ -2345,7 +2327,7 @@ test "std.zon enum literals" {...@@ -2345,7 +2327,7 @@ test "std.zon enum literals" {
2345 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2327 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2346 \\2328 \\
2347 ,2329 ,
2348 "{}",2330 "{f}",
2349 .{diag},2331 .{diag},
2350 );2332 );
2351 }2333 }
...@@ -2358,7 +2340,7 @@ test "std.zon enum literals" {...@@ -2358,7 +2340,7 @@ test "std.zon enum literals" {
2358 error.ParseZon,2340 error.ParseZon,
2359 fromSlice(Enum, gpa, "true", &diag, .{}),2341 fromSlice(Enum, gpa, "true", &diag, .{}),
2360 );2342 );
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});
2362 }2344 }
23632345
2364 // Test embedded nulls in an identifier2346 // Test embedded nulls in an identifier
...@@ -2371,7 +2353,7 @@ test "std.zon enum literals" {...@@ -2371,7 +2353,7 @@ test "std.zon enum literals" {
2371 );2353 );
2372 try std.testing.expectFmt(2354 try std.testing.expectFmt(
2373 "1:2: error: identifier cannot contain null bytes\n",2355 "1:2: error: identifier cannot contain null bytes\n",
2374 "{}",2356 "{f}",
2375 .{diag},2357 .{diag},
2376 );2358 );
2377 }2359 }
...@@ -2397,13 +2379,13 @@ test "std.zon parse bool" {...@@ -2397,13 +2379,13 @@ test "std.zon parse bool" {
2397 \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'2379 \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
2398 \\1:2: note: precede identifier with '.' for an enum literal2380 \\1:2: note: precede identifier with '.' for an enum literal
2399 \\2381 \\
2400 , "{}", .{diag});2382 , "{f}", .{diag});
2401 }2383 }
2402 {2384 {
2403 var diag: Diagnostics = .{};2385 var diag: Diagnostics = .{};
2404 defer diag.deinit(gpa);2386 defer diag.deinit(gpa);
2405 try std.testing.expectError(error.ParseZon, fromSlice(bool, gpa, "123", &diag, .{}));2387 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});
2407 }2389 }
2408}2390}
24092391
...@@ -2476,7 +2458,7 @@ test "std.zon parse int" {...@@ -2476,7 +2458,7 @@ test "std.zon parse int" {
2476 ));2458 ));
2477 try std.testing.expectFmt(2459 try std.testing.expectFmt(
2478 "1:1: error: type 'i66' cannot represent value\n",2460 "1:1: error: type 'i66' cannot represent value\n",
2479 "{}",2461 "{f}",
2480 .{diag},2462 .{diag},
2481 );2463 );
2482 }2464 }
...@@ -2492,7 +2474,7 @@ test "std.zon parse int" {...@@ -2492,7 +2474,7 @@ test "std.zon parse int" {
2492 ));2474 ));
2493 try std.testing.expectFmt(2475 try std.testing.expectFmt(
2494 "1:1: error: type 'i66' cannot represent value\n",2476 "1:1: error: type 'i66' cannot represent value\n",
2495 "{}",2477 "{f}",
2496 .{diag},2478 .{diag},
2497 );2479 );
2498 }2480 }
...@@ -2581,7 +2563,7 @@ test "std.zon parse int" {...@@ -2581,7 +2563,7 @@ test "std.zon parse int" {
2581 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{}));2563 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{}));
2582 try std.testing.expectFmt(2564 try std.testing.expectFmt(
2583 "1:3: error: invalid digit 'a' for decimal base\n",2565 "1:3: error: invalid digit 'a' for decimal base\n",
2584 "{}",2566 "{f}",
2585 .{diag},2567 .{diag},
2586 );2568 );
2587 }2569 }
...@@ -2591,7 +2573,7 @@ test "std.zon parse int" {...@@ -2591,7 +2573,7 @@ test "std.zon parse int" {
2591 var diag: Diagnostics = .{};2573 var diag: Diagnostics = .{};
2592 defer diag.deinit(gpa);2574 defer diag.deinit(gpa);
2593 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "true", &diag, .{}));2575 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});
2595 }2577 }
25962578
2597 // Failing because an int is out of range2579 // Failing because an int is out of range
...@@ -2601,7 +2583,7 @@ test "std.zon parse int" {...@@ -2601,7 +2583,7 @@ test "std.zon parse int" {
2601 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{}));2583 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{}));
2602 try std.testing.expectFmt(2584 try std.testing.expectFmt(
2603 "1:1: error: type 'u8' cannot represent value\n",2585 "1:1: error: type 'u8' cannot represent value\n",
2604 "{}",2586 "{f}",
2605 .{diag},2587 .{diag},
2606 );2588 );
2607 }2589 }
...@@ -2613,7 +2595,7 @@ test "std.zon parse int" {...@@ -2613,7 +2595,7 @@ test "std.zon parse int" {
2613 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{}));2595 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{}));
2614 try std.testing.expectFmt(2596 try std.testing.expectFmt(
2615 "1:1: error: type 'i8' cannot represent value\n",2597 "1:1: error: type 'i8' cannot represent value\n",
2616 "{}",2598 "{f}",
2617 .{diag},2599 .{diag},
2618 );2600 );
2619 }2601 }
...@@ -2625,7 +2607,7 @@ test "std.zon parse int" {...@@ -2625,7 +2607,7 @@ test "std.zon parse int" {
2625 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{}));2607 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{}));
2626 try std.testing.expectFmt(2608 try std.testing.expectFmt(
2627 "1:1: error: type 'u8' cannot represent value\n",2609 "1:1: error: type 'u8' cannot represent value\n",
2628 "{}",2610 "{f}",
2629 .{diag},2611 .{diag},
2630 );2612 );
2631 }2613 }
...@@ -2637,7 +2619,7 @@ test "std.zon parse int" {...@@ -2637,7 +2619,7 @@ test "std.zon parse int" {
2637 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{}));2619 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{}));
2638 try std.testing.expectFmt(2620 try std.testing.expectFmt(
2639 "1:1: error: type 'u8' cannot represent value\n",2621 "1:1: error: type 'u8' cannot represent value\n",
2640 "{}",2622 "{f}",
2641 .{diag},2623 .{diag},
2642 );2624 );
2643 }2625 }
...@@ -2649,7 +2631,7 @@ test "std.zon parse int" {...@@ -2649,7 +2631,7 @@ test "std.zon parse int" {
2649 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{}));2631 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{}));
2650 try std.testing.expectFmt(2632 try std.testing.expectFmt(
2651 "1:1: error: type 'u8' cannot represent value\n",2633 "1:1: error: type 'u8' cannot represent value\n",
2652 "{}",2634 "{f}",
2653 .{diag},2635 .{diag},
2654 );2636 );
2655 }2637 }
...@@ -2664,7 +2646,7 @@ test "std.zon parse int" {...@@ -2664,7 +2646,7 @@ test "std.zon parse int" {
2664 \\1:2: note: use '0' for an integer zero2646 \\1:2: note: use '0' for an integer zero
2665 \\1:2: note: use '-0.0' for a floating-point signed zero2647 \\1:2: note: use '-0.0' for a floating-point signed zero
2666 \\2648 \\
2667 , "{}", .{diag});2649 , "{f}", .{diag});
2668 }2650 }
26692651
2670 // Negative integer zero casted to float2652 // Negative integer zero casted to float
...@@ -2677,7 +2659,7 @@ test "std.zon parse int" {...@@ -2677,7 +2659,7 @@ test "std.zon parse int" {
2677 \\1:2: note: use '0' for an integer zero2659 \\1:2: note: use '0' for an integer zero
2678 \\1:2: note: use '-0.0' for a floating-point signed zero2660 \\1:2: note: use '-0.0' for a floating-point signed zero
2679 \\2661 \\
2680 , "{}", .{diag});2662 , "{f}", .{diag});
2681 }2663 }
26822664
2683 // Negative float 0 is allowed2665 // Negative float 0 is allowed
...@@ -2693,7 +2675,7 @@ test "std.zon parse int" {...@@ -2693,7 +2675,7 @@ test "std.zon parse int" {
2693 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{}));2675 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{}));
2694 try std.testing.expectFmt(2676 try std.testing.expectFmt(
2695 "1:1: error: expected number or 'inf' after '-'\n",2677 "1:1: error: expected number or 'inf' after '-'\n",
2696 "{}",2678 "{f}",
2697 .{diag},2679 .{diag},
2698 );2680 );
2699 }2681 }
...@@ -2707,7 +2689,7 @@ test "std.zon parse int" {...@@ -2707,7 +2689,7 @@ test "std.zon parse int" {
2707 );2689 );
2708 try std.testing.expectFmt(2690 try std.testing.expectFmt(
2709 "1:1: error: expected number or 'inf' after '-'\n",2691 "1:1: error: expected number or 'inf' after '-'\n",
2710 "{}",2692 "{f}",
2711 .{diag},2693 .{diag},
2712 );2694 );
2713 }2695 }
...@@ -2717,7 +2699,7 @@ test "std.zon parse int" {...@@ -2717,7 +2699,7 @@ test "std.zon parse int" {
2717 var diag: Diagnostics = .{};2699 var diag: Diagnostics = .{};
2718 defer diag.deinit(gpa);2700 defer diag.deinit(gpa);
2719 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "0xg", &diag, .{}));2701 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});
2721 }2703 }
27222704
2723 // Notes on invalid int literal2705 // Notes on invalid int literal
...@@ -2729,7 +2711,7 @@ test "std.zon parse int" {...@@ -2729,7 +2711,7 @@ test "std.zon parse int" {
2729 \\1:1: error: number '0123' has leading zero2711 \\1:1: error: number '0123' has leading zero
2730 \\1:1: note: use '0o' prefix for octal literals2712 \\1:1: note: use '0o' prefix for octal literals
2731 \\2713 \\
2732 , "{}", .{diag});2714 , "{f}", .{diag});
2733 }2715 }
2734}2716}
27352717
...@@ -2742,7 +2724,7 @@ test "std.zon negative char" {...@@ -2742,7 +2724,7 @@ test "std.zon negative char" {
2742 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{}));2724 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{}));
2743 try std.testing.expectFmt(2725 try std.testing.expectFmt(
2744 "1:1: error: expected number or 'inf' after '-'\n",2726 "1:1: error: expected number or 'inf' after '-'\n",
2745 "{}",2727 "{f}",
2746 .{diag},2728 .{diag},
2747 );2729 );
2748 }2730 }
...@@ -2752,7 +2734,7 @@ test "std.zon negative char" {...@@ -2752,7 +2734,7 @@ test "std.zon negative char" {
2752 try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{}));2734 try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{}));
2753 try std.testing.expectFmt(2735 try std.testing.expectFmt(
2754 "1:1: error: expected number or 'inf' after '-'\n",2736 "1:1: error: expected number or 'inf' after '-'\n",
2755 "{}",2737 "{f}",
2756 .{diag},2738 .{diag},
2757 );2739 );
2758 }2740 }
...@@ -2839,7 +2821,7 @@ test "std.zon parse float" {...@@ -2839,7 +2821,7 @@ test "std.zon parse float" {
2839 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{}));2821 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{}));
2840 try std.testing.expectFmt(2822 try std.testing.expectFmt(
2841 "1:1: error: expected number or 'inf' after '-'\n",2823 "1:1: error: expected number or 'inf' after '-'\n",
2842 "{}",2824 "{f}",
2843 .{diag},2825 .{diag},
2844 );2826 );
2845 }2827 }
...@@ -2849,7 +2831,7 @@ test "std.zon parse float" {...@@ -2849,7 +2831,7 @@ test "std.zon parse float" {
2849 var diag: Diagnostics = .{};2831 var diag: Diagnostics = .{};
2850 defer diag.deinit(gpa);2832 defer diag.deinit(gpa);
2851 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));2833 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});
2853 }2835 }
28542836
2855 // nan as int not allowed2837 // nan as int not allowed
...@@ -2857,7 +2839,7 @@ test "std.zon parse float" {...@@ -2857,7 +2839,7 @@ test "std.zon parse float" {
2857 var diag: Diagnostics = .{};2839 var diag: Diagnostics = .{};
2858 defer diag.deinit(gpa);2840 defer diag.deinit(gpa);
2859 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));2841 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});
2861 }2843 }
28622844
2863 // inf as int not allowed2845 // inf as int not allowed
...@@ -2865,7 +2847,7 @@ test "std.zon parse float" {...@@ -2865,7 +2847,7 @@ test "std.zon parse float" {
2865 var diag: Diagnostics = .{};2847 var diag: Diagnostics = .{};
2866 defer diag.deinit(gpa);2848 defer diag.deinit(gpa);
2867 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "inf", &diag, .{}));2849 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});
2869 }2851 }
28702852
2871 // -inf as int not allowed2853 // -inf as int not allowed
...@@ -2873,7 +2855,7 @@ test "std.zon parse float" {...@@ -2873,7 +2855,7 @@ test "std.zon parse float" {
2873 var diag: Diagnostics = .{};2855 var diag: Diagnostics = .{};
2874 defer diag.deinit(gpa);2856 defer diag.deinit(gpa);
2875 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-inf", &diag, .{}));2857 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});
2877 }2859 }
28782860
2879 // Bad identifier as float2861 // Bad identifier as float
...@@ -2886,7 +2868,7 @@ test "std.zon parse float" {...@@ -2886,7 +2868,7 @@ test "std.zon parse float" {
2886 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'2868 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
2887 \\1:1: note: precede identifier with '.' for an enum literal2869 \\1:1: note: precede identifier with '.' for an enum literal
2888 \\2870 \\
2889 , "{}", .{diag});2871 , "{f}", .{diag});
2890 }2872 }
28912873
2892 {2874 {
...@@ -2895,7 +2877,7 @@ test "std.zon parse float" {...@@ -2895,7 +2877,7 @@ test "std.zon parse float" {
2895 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{}));2877 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{}));
2896 try std.testing.expectFmt(2878 try std.testing.expectFmt(
2897 "1:1: error: expected number or 'inf' after '-'\n",2879 "1:1: error: expected number or 'inf' after '-'\n",
2898 "{}",2880 "{f}",
2899 .{diag},2881 .{diag},
2900 );2882 );
2901 }2883 }
...@@ -2908,7 +2890,7 @@ test "std.zon parse float" {...@@ -2908,7 +2890,7 @@ test "std.zon parse float" {
2908 error.ParseZon,2890 error.ParseZon,
2909 fromSlice(f32, gpa, "\"foo\"", &diag, .{}),2891 fromSlice(f32, gpa, "\"foo\"", &diag, .{}),
2910 );2892 );
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});
2912 }2894 }
2913}2895}
29142896
...@@ -3152,7 +3134,7 @@ test "std.zon vector" {...@@ -3152,7 +3134,7 @@ test "std.zon vector" {
3152 );3134 );
3153 try std.testing.expectFmt(3135 try std.testing.expectFmt(
3154 "1:2: error: expected 2 vector elements; found 1\n",3136 "1:2: error: expected 2 vector elements; found 1\n",
3155 "{}",3137 "{f}",
3156 .{diag},3138 .{diag},
3157 );3139 );
3158 }3140 }
...@@ -3167,7 +3149,7 @@ test "std.zon vector" {...@@ -3167,7 +3149,7 @@ test "std.zon vector" {
3167 );3149 );
3168 try std.testing.expectFmt(3150 try std.testing.expectFmt(
3169 "1:2: error: expected 2 vector elements; found 3\n",3151 "1:2: error: expected 2 vector elements; found 3\n",
3170 "{}",3152 "{f}",
3171 .{diag},3153 .{diag},
3172 );3154 );
3173 }3155 }
...@@ -3182,7 +3164,7 @@ test "std.zon vector" {...@@ -3182,7 +3164,7 @@ test "std.zon vector" {
3182 );3164 );
3183 try std.testing.expectFmt(3165 try std.testing.expectFmt(
3184 "1:8: error: expected type 'f32'\n",3166 "1:8: error: expected type 'f32'\n",
3185 "{}",3167 "{f}",
3186 .{diag},3168 .{diag},
3187 );3169 );
3188 }3170 }
...@@ -3195,7 +3177,7 @@ test "std.zon vector" {...@@ -3195,7 +3177,7 @@ test "std.zon vector" {
3195 error.ParseZon,3177 error.ParseZon,
3196 fromSlice(@Vector(3, u8), gpa, "true", &diag, .{}),3178 fromSlice(@Vector(3, u8), gpa, "true", &diag, .{}),
3197 );3179 );
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});
3199 }3181 }
32003182
3201 // Elements should get freed on error3183 // Elements should get freed on error
...@@ -3206,7 +3188,7 @@ test "std.zon vector" {...@@ -3206,7 +3188,7 @@ test "std.zon vector" {
3206 error.ParseZon,3188 error.ParseZon,
3207 fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),3189 fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
3208 );3190 );
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});
3210 }3192 }
3211}3193}
32123194
...@@ -3330,7 +3312,7 @@ test "std.zon add pointers" {...@@ -3330,7 +3312,7 @@ test "std.zon add pointers" {
3330 error.ParseZon,3312 error.ParseZon,
3331 fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),3313 fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),
3332 );3314 );
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});
3334 }3316 }
33353317
3336 {3318 {
...@@ -3340,7 +3322,7 @@ test "std.zon add pointers" {...@@ -3340,7 +3322,7 @@ test "std.zon add pointers" {
3340 error.ParseZon,3322 error.ParseZon,
3341 fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),3323 fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),
3342 );3324 );
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});
3344 }3326 }
33453327
3346 {3328 {
...@@ -3350,7 +3332,7 @@ test "std.zon add pointers" {...@@ -3350,7 +3332,7 @@ test "std.zon add pointers" {
3350 error.ParseZon,3332 error.ParseZon,
3351 fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),3333 fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
3352 );3334 );
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});
3354 }3336 }
33553337
3356 {3338 {
...@@ -3360,7 +3342,7 @@ test "std.zon add pointers" {...@@ -3360,7 +3342,7 @@ test "std.zon add pointers" {
3360 error.ParseZon,3342 error.ParseZon,
3361 fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),3343 fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),
3362 );3344 );
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});
3364 }3346 }
33653347
3366 {3348 {
...@@ -3370,7 +3352,7 @@ test "std.zon add pointers" {...@@ -3370,7 +3352,7 @@ test "std.zon add pointers" {
3370 error.ParseZon,3352 error.ParseZon,
3371 fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),3353 fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
3372 );3354 );
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});
3374 }3356 }
33753357
3376 {3358 {
...@@ -3380,7 +3362,7 @@ test "std.zon add pointers" {...@@ -3380,7 +3362,7 @@ test "std.zon add pointers" {
3380 error.ParseZon,3362 error.ParseZon,
3381 fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),3363 fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
3382 );3364 );
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});
3384 }3366 }
33853367
3386 {3368 {
...@@ -3390,7 +3372,7 @@ test "std.zon add pointers" {...@@ -3390,7 +3372,7 @@ test "std.zon add pointers" {
3390 error.ParseZon,3372 error.ParseZon,
3391 fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),3373 fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
3392 );3374 );
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});
3394 }3376 }
33953377
3396 {3378 {
...@@ -3400,7 +3382,7 @@ test "std.zon add pointers" {...@@ -3400,7 +3382,7 @@ test "std.zon add pointers" {
3400 error.ParseZon,3382 error.ParseZon,
3401 fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),3383 fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),
3402 );3384 );
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});
3404 }3386 }
34053387
3406 {3388 {
...@@ -3410,7 +3392,7 @@ test "std.zon add pointers" {...@@ -3410,7 +3392,7 @@ test "std.zon add pointers" {
3410 error.ParseZon,3392 error.ParseZon,
3411 fromSlice(?[3]u8, gpa, "true", &diag, .{}),3393 fromSlice(?[3]u8, gpa, "true", &diag, .{}),
3412 );3394 );
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});
3414 }3396 }
34153397
3416 {3398 {
...@@ -3420,7 +3402,7 @@ test "std.zon add pointers" {...@@ -3420,7 +3402,7 @@ test "std.zon add pointers" {
3420 error.ParseZon,3402 error.ParseZon,
3421 fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),3403 fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),
3422 );3404 );
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});
3424 }3406 }
34253407
3426 {3408 {
...@@ -3430,7 +3412,7 @@ test "std.zon add pointers" {...@@ -3430,7 +3412,7 @@ test "std.zon add pointers" {
3430 error.ParseZon,3412 error.ParseZon,
3431 fromSlice(?[]u8, gpa, "true", &diag, .{}),3413 fromSlice(?[]u8, gpa, "true", &diag, .{}),
3432 );3414 );
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});
3434 }3416 }
34353417
3436 {3418 {
...@@ -3440,7 +3422,7 @@ test "std.zon add pointers" {...@@ -3440,7 +3422,7 @@ test "std.zon add pointers" {
3440 error.ParseZon,3422 error.ParseZon,
3441 fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),3423 fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),
3442 );3424 );
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});
3444 }3426 }
34453427
3446 {3428 {
...@@ -3450,7 +3432,7 @@ test "std.zon add pointers" {...@@ -3450,7 +3432,7 @@ test "std.zon add pointers" {
3450 error.ParseZon,3432 error.ParseZon,
3451 fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),3433 fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
3452 );3434 );
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});
3454 }3436 }
3455}3437}
34563438
lib/std/zon/stringify.zig+8-7
...@@ -501,7 +501,7 @@ pub fn Serializer(Writer: type) type {...@@ -501,7 +501,7 @@ pub fn Serializer(Writer: type) type {
501 try self.int(val);501 try self.int(val);
502 },502 },
503 .float, .comptime_float => try self.float(val),503 .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}),
505 .enum_literal => try self.ident(@tagName(val)),505 .enum_literal => try self.ident(@tagName(val)),
506 .@"enum" => try self.ident(@tagName(val)),506 .@"enum" => try self.ident(@tagName(val)),
507 .pointer => |pointer| {507 .pointer => |pointer| {
...@@ -615,7 +615,8 @@ pub fn Serializer(Writer: type) type {...@@ -615,7 +615,8 @@ pub fn Serializer(Writer: type) type {
615615
616 /// Serialize an integer.616 /// Serialize an integer.
617 pub fn int(self: *Self, val: anytype) Writer.Error!void {617 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});
619 }620 }
620621
621 /// Serialize a float.622 /// Serialize a float.
...@@ -630,12 +631,12 @@ pub fn Serializer(Writer: type) type {...@@ -630,12 +631,12 @@ pub fn Serializer(Writer: type) type {
630 } else if (std.math.isNegativeZero(val)) {631 } else if (std.math.isNegativeZero(val)) {
631 return self.writer.writeAll("-0.0");632 return self.writer.writeAll("-0.0");
632 } else {633 } else {
633 try std.fmt.format(self.writer, "{d}", .{val});634 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});
634 },635 },
635 .comptime_float => if (val == 0) {636 .comptime_float => if (val == 0) {
636 return self.writer.writeAll("0");637 return self.writer.writeAll("0");
637 } else {638 } else {
638 try std.fmt.format(self.writer, "{d}", .{val});639 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});
639 },640 },
640 else => comptime unreachable,641 else => comptime unreachable,
641 }642 }
...@@ -645,7 +646,7 @@ pub fn Serializer(Writer: type) type {...@@ -645,7 +646,7 @@ pub fn Serializer(Writer: type) type {
645 ///646 ///
646 /// Escapes the identifier if necessary.647 /// Escapes the identifier if necessary.
647 pub fn ident(self: *Self, name: []const u8) Writer.Error!void {648 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)});
649 }650 }
650651
651 /// Serialize `val` as a Unicode codepoint.652 /// Serialize `val` as a Unicode codepoint.
...@@ -658,7 +659,7 @@ pub fn Serializer(Writer: type) type {...@@ -658,7 +659,7 @@ pub fn Serializer(Writer: type) type {
658 var buf: [8]u8 = undefined;659 var buf: [8]u8 = undefined;
659 const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint;660 const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint;
660 const str = buf[0..len];661 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)});
662 }663 }
663664
664 /// Like `value`, but always serializes `val` as a tuple.665 /// Like `value`, but always serializes `val` as a tuple.
...@@ -716,7 +717,7 @@ pub fn Serializer(Writer: type) type {...@@ -716,7 +717,7 @@ pub fn Serializer(Writer: type) type {
716717
717 /// Like `value`, but always serializes `val` as a string.718 /// Like `value`, but always serializes `val` as a string.
718 pub fn string(self: *Self, val: []const u8) Writer.Error!void {719 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)});
720 }721 }
721722
722 /// Options for formatting multiline strings.723 /// Options for formatting multiline strings.
lib/ubsan_rt.zig+37-58
...@@ -119,12 +119,7 @@ const Value = extern struct {...@@ -119,12 +119,7 @@ const Value = extern struct {
119 }119 }
120 }120 }
121121
122 pub fn format(122 pub fn format(value: Value, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
123 value: Value,
124 comptime fmt: []const u8,
125 _: std.fmt.FormatOptions,
126 writer: anytype,
127 ) !void {
128 comptime assert(fmt.len == 0);123 comptime assert(fmt.len == 0);
129124
130 // Work around x86_64 backend limitation.125 // Work around x86_64 backend limitation.
...@@ -136,12 +131,12 @@ const Value = extern struct {...@@ -136,12 +131,12 @@ const Value = extern struct {
136 switch (value.td.kind) {131 switch (value.td.kind) {
137 .integer => {132 .integer => {
138 if (value.td.isSigned()) {133 if (value.td.isSigned()) {
139 try writer.print("{}", .{value.getSignedInteger()});134 try writer.print("{d}", .{value.getSignedInteger()});
140 } else {135 } else {
141 try writer.print("{}", .{value.getUnsignedInteger()});136 try writer.print("{d}", .{value.getUnsignedInteger()});
142 }137 }
143 },138 },
144 .float => try writer.print("{}", .{value.getFloat()}),139 .float => try writer.print("{d}", .{value.getFloat()}),
145 .unknown => try writer.writeAll("(unknown)"),140 .unknown => try writer.writeAll("(unknown)"),
146 }141 }
147 }142 }
...@@ -172,17 +167,12 @@ fn overflowHandler(...@@ -172,17 +167,12 @@ fn overflowHandler(
172 ) callconv(.c) noreturn {167 ) callconv(.c) noreturn {
173 const lhs: Value = .{ .handle = lhs_handle, .td = data.td };168 const lhs: Value = .{ .handle = lhs_handle, .td = data.td };
174 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };169 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
175170 const signed_str = if (data.td.isSigned()) "signed" else "unsigned";
176 const is_signed = data.td.isSigned();171 panic(
177 const fmt = "{s} integer overflow: " ++ "{} " ++172 @returnAddress(),
178 operator ++ " {} cannot be represented in type {s}";173 "{s} integer overflow: {f} " ++ operator ++ " {f} cannot be represented in type {s}",
179174 .{ signed_str, lhs, rhs, data.td.getName() },
180 panic(@returnAddress(), fmt, .{175 );
181 if (is_signed) "signed" else "unsigned",
182 lhs,
183 rhs,
184 data.td.getName(),
185 });
186 }176 }
187 };177 };
188178
...@@ -201,11 +191,9 @@ fn negationHandler(...@@ -201,11 +191,9 @@ fn negationHandler(
201 value_handle: ValueHandle,191 value_handle: ValueHandle,
202) callconv(.c) noreturn {192) callconv(.c) noreturn {
203 const value: Value = .{ .handle = value_handle, .td = data.td };193 const value: Value = .{ .handle = value_handle, .td = data.td };
204 panic(194 panic(@returnAddress(), "negation of {f} cannot be represented in type {s}", .{
205 @returnAddress(),195 value, data.td.getName(),
206 "negation of {} cannot be represented in type {s}",196 });
207 .{ value, data.td.getName() },
208 );
209}197}
210198
211fn divRemHandlerAbort(199fn divRemHandlerAbort(
...@@ -225,11 +213,9 @@ fn divRemHandler(...@@ -225,11 +213,9 @@ fn divRemHandler(
225 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };213 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
226214
227 if (rhs.isMinusOne()) {215 if (rhs.isMinusOne()) {
228 panic(216 panic(@returnAddress(), "division of {f} by -1 cannot be represented in type {s}", .{
229 @returnAddress(),217 lhs, data.td.getName(),
230 "division of {} by -1 cannot be represented in type {s}",218 });
231 .{ lhs, data.td.getName() },
232 );
233 } else panic(@returnAddress(), "division by zero", .{});219 } else panic(@returnAddress(), "division by zero", .{});
234}220}
235221
...@@ -269,8 +255,8 @@ fn alignmentAssumptionHandler(...@@ -269,8 +255,8 @@ fn alignmentAssumptionHandler(
269 if (maybe_offset) |offset| {255 if (maybe_offset) |offset| {
270 panic(256 panic(
271 @returnAddress(),257 @returnAddress(),
272 "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++258 "assumption of {f} byte alignment (with offset of {d} byte) for pointer of type {s} failed\n" ++
273 "offset address is {} aligned, misalignment offset is {} bytes",259 "offset address is {d} aligned, misalignment offset is {d} bytes",
274 .{260 .{
275 alignment,261 alignment,
276 @intFromPtr(offset),262 @intFromPtr(offset),
...@@ -282,8 +268,8 @@ fn alignmentAssumptionHandler(...@@ -282,8 +268,8 @@ fn alignmentAssumptionHandler(
282 } else {268 } else {
283 panic(269 panic(
284 @returnAddress(),270 @returnAddress(),
285 "assumption of {} byte alignment for pointer of type {s} failed\n" ++271 "assumption of {f} byte alignment for pointer of type {s} failed\n" ++
286 "address is {} aligned, misalignment offset is {} bytes",272 "address is {d} aligned, misalignment offset is {d} bytes",
287 .{273 .{
288 alignment,274 alignment,
289 data.td.getName(),275 data.td.getName(),
...@@ -320,21 +306,21 @@ fn shiftOob(...@@ -320,21 +306,21 @@ fn shiftOob(
320 rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())306 rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())
321 {307 {
322 if (rhs.isNegative()) {308 if (rhs.isNegative()) {
323 panic(@returnAddress(), "shift exponent {} is negative", .{rhs});309 panic(@returnAddress(), "shift exponent {f} is negative", .{rhs});
324 } else {310 } else {
325 panic(311 panic(
326 @returnAddress(),312 @returnAddress(),
327 "shift exponent {} is too large for {}-bit type {s}",313 "shift exponent {f} is too large for {d}-bit type {s}",
328 .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },314 .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },
329 );315 );
330 }316 }
331 } else {317 } else {
332 if (lhs.isNegative()) {318 if (lhs.isNegative()) {
333 panic(@returnAddress(), "left shift of negative value {}", .{lhs});319 panic(@returnAddress(), "left shift of negative value {f}", .{lhs});
334 } else {320 } else {
335 panic(321 panic(
336 @returnAddress(),322 @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}",
338 .{ lhs, rhs, data.lhs_type.getName() },324 .{ lhs, rhs, data.lhs_type.getName() },
339 );325 );
340 }326 }
...@@ -359,11 +345,10 @@ fn outOfBounds(...@@ -359,11 +345,10 @@ fn outOfBounds(
359 index_handle: ValueHandle,345 index_handle: ValueHandle,
360) callconv(.c) noreturn {346) callconv(.c) noreturn {
361 const index: Value = .{ .handle = index_handle, .td = data.index_type };347 const index: Value = .{ .handle = index_handle, .td = data.index_type };
362 panic(348 panic(@returnAddress(), "index {f} out of bounds for type {s}", .{
363 @returnAddress(),349 index,
364 "index {} out of bounds for type {s}",350 data.array_type.getName(),
365 .{ index, data.array_type.getName() },351 });
366 );
367}352}
368353
369const PointerOverflowData = extern struct {354const PointerOverflowData = extern struct {
...@@ -387,7 +372,7 @@ fn pointerOverflow(...@@ -387,7 +372,7 @@ fn pointerOverflow(
387 if (result == 0) {372 if (result == 0) {
388 panic(@returnAddress(), "applying zero offset to null pointer", .{});373 panic(@returnAddress(), "applying zero offset to null pointer", .{});
389 } else {374 } else {
390 panic(@returnAddress(), "applying non-zero offset {} to null pointer", .{result});375 panic(@returnAddress(), "applying non-zero offset {d} to null pointer", .{result});
391 }376 }
392 } else {377 } else {
393 if (result == 0) {378 if (result == 0) {
...@@ -483,7 +468,7 @@ fn typeMismatch(...@@ -483,7 +468,7 @@ fn typeMismatch(
483 } else if (!std.mem.isAligned(handle, alignment)) {468 } else if (!std.mem.isAligned(handle, alignment)) {
484 panic(469 panic(
485 @returnAddress(),470 @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",
487 .{ data.kind.getName(), handle, data.td.getName(), alignment },472 .{ data.kind.getName(), handle, data.td.getName(), alignment },
488 );473 );
489 } else {474 } else {
...@@ -531,7 +516,7 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn {...@@ -531,7 +516,7 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn {
531fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {516fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
532 panic(517 panic(
533 @returnAddress(),518 @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",
535 .{data.arg_index},520 .{data.arg_index},
536 );521 );
537}522}
...@@ -553,11 +538,9 @@ fn loadInvalidValue(...@@ -553,11 +538,9 @@ fn loadInvalidValue(
553 value_handle: ValueHandle,538 value_handle: ValueHandle,
554) callconv(.c) noreturn {539) callconv(.c) noreturn {
555 const value: Value = .{ .handle = value_handle, .td = data.td };540 const value: Value = .{ .handle = value_handle, .td = data.td };
556 panic(541 panic(@returnAddress(), "load of value {f}, which is not valid for type {s}", .{
557 @returnAddress(),542 value, data.td.getName(),
558 "load of value {}, which is not valid for type {s}",543 });
559 .{ value, data.td.getName() },
560 );
561}544}
562545
563const InvalidBuiltinData = extern struct {546const InvalidBuiltinData = extern struct {
...@@ -596,11 +579,7 @@ fn vlaBoundNotPositive(...@@ -596,11 +579,7 @@ fn vlaBoundNotPositive(
596 bound_handle: ValueHandle,579 bound_handle: ValueHandle,
597) callconv(.c) noreturn {580) callconv(.c) noreturn {
598 const bound: Value = .{ .handle = bound_handle, .td = data.td };581 const bound: Value = .{ .handle = bound_handle, .td = data.td };
599 panic(582 panic(@returnAddress(), "variable length array bound evaluates to non-positive value {f}", .{bound});
600 @returnAddress(),
601 "variable length array bound evaluates to non-positive value {}",
602 .{bound},
603 );
604}583}
605584
606const FloatCastOverflowData = extern struct {585const FloatCastOverflowData = extern struct {
...@@ -631,13 +610,13 @@ fn floatCastOverflow(...@@ -631,13 +610,13 @@ fn floatCastOverflow(
631 if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {610 if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {
632 const data: *const FloatCastOverflowData = @ptrCast(data_handle);611 const data: *const FloatCastOverflowData = @ptrCast(data_handle);
633 const from_value: Value = .{ .handle = from_handle, .td = data.from };612 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}", .{
635 from_value, data.to.getName(),614 from_value, data.to.getName(),
636 });615 });
637 } else {616 } else {
638 const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);617 const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);
639 const from_value: Value = .{ .handle = from_handle, .td = data.from };618 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}", .{
641 from_value, data.to.getName(),620 from_value, data.to.getName(),
642 });621 });
643 }622 }
src/Air/print.zig+4-4
...@@ -73,11 +73,11 @@ pub fn writeInst(...@@ -73,11 +73,11 @@ pub fn writeInst(
73}73}
7474
75pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {75pub 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);
77}77}
7878
79pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {79pub 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);
81}81}
8282
83const Writer = struct {83const Writer = struct {
...@@ -704,7 +704,7 @@ const Writer = struct {...@@ -704,7 +704,7 @@ const Writer = struct {
704 }704 }
705 }705 }
706 const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len];706 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)});
708 }708 }
709709
710 fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {710 fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
...@@ -716,7 +716,7 @@ const Writer = struct {...@@ -716,7 +716,7 @@ const Writer = struct {
716 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;716 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
717 try w.writeOperand(s, inst, 0, pl_op.operand);717 try w.writeOperand(s, inst, 0, pl_op.operand);
718 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);718 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))});
720 }720 }
721721
722 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {722 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 {...@@ -51,60 +51,60 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
51 const zig_backend = opts.zig_backend;51 const zig_backend = opts.zig_backend;
5252
53 @setEvalBranchQuota(4000);53 @setEvalBranchQuota(4000);
54 try buffer.writer().print(54 try buffer.print(
55 \\const std = @import("std");55 \\const std = @import("std");
56 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer56 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
57 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.57 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
58 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;58 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
59 \\pub const zig_version_string = "{s}";59 \\pub const zig_version_string = "{s}";
60 \\pub const zig_backend = std.builtin.CompilerBackend.{p_};60 \\pub const zig_backend = std.builtin.CompilerBackend.{f};
61 \\61 \\
62 \\pub const output_mode: std.builtin.OutputMode = .{p_};62 \\pub const output_mode: std.builtin.OutputMode = .{f};
63 \\pub const link_mode: std.builtin.LinkMode = .{p_};63 \\pub const link_mode: std.builtin.LinkMode = .{f};
64 \\pub const unwind_tables: std.builtin.UnwindTables = .{p_};64 \\pub const unwind_tables: std.builtin.UnwindTables = .{f};
65 \\pub const is_test = {};65 \\pub const is_test = {};
66 \\pub const single_threaded = {};66 \\pub const single_threaded = {};
67 \\pub const abi: std.Target.Abi = .{p_};67 \\pub const abi: std.Target.Abi = .{f};
68 \\pub const cpu: std.Target.Cpu = .{{68 \\pub const cpu: std.Target.Cpu = .{{
69 \\ .arch = .{p_},69 \\ .arch = .{f},
70 \\ .model = &std.Target.{p_}.cpu.{p_},70 \\ .model = &std.Target.{f}.cpu.{f},
71 \\ .features = std.Target.{p_}.featureSet(&.{{71 \\ .features = std.Target.{f}.featureSet(&.{{
72 \\72 \\
73 , .{73 , .{
74 build_options.version,74 build_options.version,
75 std.zig.fmtId(@tagName(zig_backend)),75 std.zig.fmtIdPU(@tagName(zig_backend)),
76 std.zig.fmtId(@tagName(opts.output_mode)),76 std.zig.fmtIdPU(@tagName(opts.output_mode)),
77 std.zig.fmtId(@tagName(opts.link_mode)),77 std.zig.fmtIdPU(@tagName(opts.link_mode)),
78 std.zig.fmtId(@tagName(opts.unwind_tables)),78 std.zig.fmtIdPU(@tagName(opts.unwind_tables)),
79 opts.is_test,79 opts.is_test,
80 opts.single_threaded,80 opts.single_threaded,
81 std.zig.fmtId(@tagName(target.abi)),81 std.zig.fmtIdPU(@tagName(target.abi)),
82 std.zig.fmtId(@tagName(target.cpu.arch)),82 std.zig.fmtIdPU(@tagName(target.cpu.arch)),
83 std.zig.fmtId(arch_family_name),83 std.zig.fmtIdPU(arch_family_name),
84 std.zig.fmtId(target.cpu.model.name),84 std.zig.fmtIdPU(target.cpu.model.name),
85 std.zig.fmtId(arch_family_name),85 std.zig.fmtIdPU(arch_family_name),
86 });86 });
8787
88 for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {88 for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {
89 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));89 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
90 const is_enabled = target.cpu.features.isEnabled(index);90 const is_enabled = target.cpu.features.isEnabled(index);
91 if (is_enabled) {91 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)});
93 }93 }
94 }94 }
95 try buffer.writer().print(95 try buffer.print(
96 \\ }}),96 \\ }}),
97 \\}};97 \\}};
98 \\pub const os: std.Target.Os = .{{98 \\pub const os: std.Target.Os = .{{
99 \\ .tag = .{p_},99 \\ .tag = .{f},
100 \\ .version_range = .{{100 \\ .version_range = .{{
101 ,101 ,
102 .{std.zig.fmtId(@tagName(target.os.tag))},102 .{std.zig.fmtIdPU(@tagName(target.os.tag))},
103 );103 );
104104
105 switch (target.os.versionRange()) {105 switch (target.os.versionRange()) {
106 .none => try buffer.appendSlice(" .none = {} },\n"),106 .none => try buffer.appendSlice(" .none = {} },\n"),
107 .semver => |semver| try buffer.writer().print(107 .semver => |semver| try buffer.print(
108 \\ .semver = .{{108 \\ .semver = .{{
109 \\ .min = .{{109 \\ .min = .{{
110 \\ .major = {},110 \\ .major = {},
...@@ -127,7 +127,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -127,7 +127,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
127 semver.max.minor,127 semver.max.minor,
128 semver.max.patch,128 semver.max.patch,
129 }),129 }),
130 .linux => |linux| try buffer.writer().print(130 .linux => |linux| try buffer.print(
131 \\ .linux = .{{131 \\ .linux = .{{
132 \\ .range = .{{132 \\ .range = .{{
133 \\ .min = .{{133 \\ .min = .{{
...@@ -164,7 +164,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -164,7 +164,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
164164
165 linux.android,165 linux.android,
166 }),166 }),
167 .hurd => |hurd| try buffer.writer().print(167 .hurd => |hurd| try buffer.print(
168 \\ .hurd = .{{168 \\ .hurd = .{{
169 \\ .range = .{{169 \\ .range = .{{
170 \\ .min = .{{170 \\ .min = .{{
...@@ -198,10 +198,10 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -198,10 +198,10 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
198 hurd.glibc.minor,198 hurd.glibc.minor,
199 hurd.glibc.patch,199 hurd.glibc.patch,
200 }),200 }),
201 .windows => |windows| try buffer.writer().print(201 .windows => |windows| try buffer.print(
202 \\ .windows = .{{202 \\ .windows = .{{
203 \\ .min = {c},203 \\ .min = {fc},
204 \\ .max = {c},204 \\ .max = {fc},
205 \\ }}}},205 \\ }}}},
206 \\206 \\
207 , .{ windows.min, windows.max }),207 , .{ windows.min, windows.max }),
...@@ -217,7 +217,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -217,7 +217,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
217 );217 );
218218
219 if (target.dynamic_linker.get()) |dl| {219 if (target.dynamic_linker.get()) |dl| {
220 try buffer.writer().print(220 try buffer.print(
221 \\ .dynamic_linker = .init("{s}"),221 \\ .dynamic_linker = .init("{s}"),
222 \\}};222 \\}};
223 \\223 \\
...@@ -237,9 +237,9 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -237,9 +237,9 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
237 // knows libc will provide it, and likewise c.zig will not export memcpy.237 // knows libc will provide it, and likewise c.zig will not export memcpy.
238 const link_libc = opts.link_libc;238 const link_libc = opts.link_libc;
239239
240 try buffer.writer().print(240 try buffer.print(
241 \\pub const object_format: std.Target.ObjectFormat = .{p_};241 \\pub const object_format: std.Target.ObjectFormat = .{f};
242 \\pub const mode: std.builtin.OptimizeMode = .{p_};242 \\pub const mode: std.builtin.OptimizeMode = .{f};
243 \\pub const link_libc = {};243 \\pub const link_libc = {};
244 \\pub const link_libcpp = {};244 \\pub const link_libcpp = {};
245 \\pub const have_error_return_tracing = {};245 \\pub const have_error_return_tracing = {};
...@@ -249,12 +249,12 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -249,12 +249,12 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
249 \\pub const position_independent_code = {};249 \\pub const position_independent_code = {};
250 \\pub const position_independent_executable = {};250 \\pub const position_independent_executable = {};
251 \\pub const strip_debug_info = {};251 \\pub const strip_debug_info = {};
252 \\pub const code_model: std.builtin.CodeModel = .{p_};252 \\pub const code_model: std.builtin.CodeModel = .{f};
253 \\pub const omit_frame_pointer = {};253 \\pub const omit_frame_pointer = {};
254 \\254 \\
255 , .{255 , .{
256 std.zig.fmtId(@tagName(target.ofmt)),256 std.zig.fmtIdPU(@tagName(target.ofmt)),
257 std.zig.fmtId(@tagName(opts.optimize_mode)),257 std.zig.fmtIdPU(@tagName(opts.optimize_mode)),
258 link_libc,258 link_libc,
259 opts.link_libcpp,259 opts.link_libcpp,
260 opts.error_tracing,260 opts.error_tracing,
...@@ -264,15 +264,15 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -264,15 +264,15 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
264 opts.pic,264 opts.pic,
265 opts.pie,265 opts.pie,
266 opts.strip,266 opts.strip,
267 std.zig.fmtId(@tagName(opts.code_model)),267 std.zig.fmtIdPU(@tagName(opts.code_model)),
268 opts.omit_frame_pointer,268 opts.omit_frame_pointer,
269 });269 });
270270
271 if (target.os.tag == .wasi) {271 if (target.os.tag == .wasi) {
272 try buffer.writer().print(272 try buffer.print(
273 \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{p_};273 \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{f};
274 \\274 \\
275 , .{std.zig.fmtId(@tagName(opts.wasi_exec_model))});275 , .{std.zig.fmtIdPU(@tagName(opts.wasi_exec_model))});
276 }276 }
277277
278 if (opts.is_test) {278 if (opts.is_test) {
...@@ -317,7 +317,7 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {...@@ -317,7 +317,7 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
317 if (root_dir.statFile(sub_path)) |stat| {317 if (root_dir.statFile(sub_path)) |stat| {
318 if (stat.size != file.source.?.len) {318 if (stat.size != file.source.?.len) {
319 std.log.warn(319 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}. " ++
321 "Overwriting with correct file contents now",321 "Overwriting with correct file contents now",
322 .{ file.path.fmt(comp), file.source.?.len, stat.size },322 .{ file.path.fmt(comp), file.source.?.len, stat.size },
323 );323 );
src/Compilation.zig+6-6
...@@ -1001,7 +1001,7 @@ pub const CObject = struct {...@@ -1001,7 +1001,7 @@ pub const CObject = struct {
10011001
1002 var line = std.ArrayList(u8).init(eb.gpa);1002 var line = std.ArrayList(u8).init(eb.gpa);
1003 defer line.deinit();1003 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
1006 break :source_line try eb.addString(line.items);1006 break :source_line try eb.addString(line.items);
1007 };1007 };
...@@ -1069,7 +1069,7 @@ pub const CObject = struct {...@@ -1069,7 +1069,7 @@ pub const CObject = struct {
10691069
1070 const file = try std.fs.cwd().openFile(path, .{});1070 const file = try std.fs.cwd().openFile(path, .{});
1071 defer file.close();1071 defer file.close();
1072 var br = std.io.bufferedReader(file.reader());1072 var br = std.io.bufferedReader(file.deprecatedReader());
1073 const reader = br.reader();1073 const reader = br.reader();
1074 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });1074 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });
1075 defer bc.deinit();1075 defer bc.deinit();
...@@ -1875,7 +1875,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1875,7 +1875,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1875 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {1875 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
1876 std.debug.lockStdErr();1876 std.debug.lockStdErr();
1877 defer std.debug.unlockStdErr();1877 defer std.debug.unlockStdErr();
1878 const stderr = std.fs.File.stderr().writer();1878 const stderr = std.fs.File.stderr().deprecatedWriter();
1879 nosuspend {1879 nosuspend {
1880 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;1880 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1881 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;1881 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
...@@ -3932,7 +3932,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3932,7 +3932,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3932 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.3932 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
3933 // However, we haven't reported any such error.3933 // However, we haven't reported any such error.
3934 // This is a compiler bug.3934 // This is a compiler bug.
3935 const stderr = std.fs.File.stderr().writer();3935 const stderr = std.fs.File.stderr().deprecatedWriter();
3936 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");3936 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3937 try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});3937 try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
3938 while (ref) |r| {3938 while (ref) |r| {
...@@ -4894,7 +4894,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4894,7 +4894,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4894 var walker = try mod_dir.walk(comp.gpa);4894 var walker = try mod_dir.walk(comp.gpa);
4895 defer walker.deinit();4895 defer walker.deinit();
48964896
4897 var archiver = std.tar.writer(tar_file.writer().any());4897 var archiver = std.tar.writer(tar_file.deprecatedWriter().any());
4898 archiver.prefix = name;4898 archiver.prefix = name;
48994899
4900 while (try walker.next()) |entry| {4900 while (try walker.next()) |entry| {
...@@ -7214,7 +7214,7 @@ pub fn lockAndSetMiscFailure(...@@ -7214,7 +7214,7 @@ pub fn lockAndSetMiscFailure(
7214pub fn dump_argv(argv: []const []const u8) void {7214pub fn dump_argv(argv: []const []const u8) void {
7215 std.debug.lockStdErr();7215 std.debug.lockStdErr();
7216 defer std.debug.unlockStdErr();7216 defer std.debug.unlockStdErr();
7217 const stderr = std.fs.File.stderr().writer();7217 const stderr = std.fs.File.stderr().deprecatedWriter();
7218 for (argv[0 .. argv.len - 1]) |arg| {7218 for (argv[0 .. argv.len - 1]) |arg| {
7219 nosuspend stderr.print("{s} ", .{arg}) catch return;7219 nosuspend stderr.print("{s} ", .{arg}) catch return;
7220 }7220 }
src/InternPool.zig+3-3
...@@ -1892,7 +1892,7 @@ pub const NullTerminatedString = enum(u32) {...@@ -1892,7 +1892,7 @@ pub const NullTerminatedString = enum(u32) {
1892 if (comptime std.mem.eql(u8, specifier, "")) {1892 if (comptime std.mem.eql(u8, specifier, "")) {
1893 try writer.writeAll(slice);1893 try writer.writeAll(slice);
1894 } else if (comptime std.mem.eql(u8, specifier, "i")) {1894 } 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)});
1896 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");1896 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");
1897 }1897 }
18981898
...@@ -11259,7 +11259,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -11259,7 +11259,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
11259}11259}
1126011260
11261fn dumpAllFallible(ip: *const InternPool) anyerror!void {11261fn 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());
11263 const w = bw.writer();11263 const w = bw.writer();
11264 for (ip.locals, 0..) |*local, tid| {11264 for (ip.locals, 0..) |*local, tid| {
11265 const items = local.shared.items.view();11265 const items = local.shared.items.view();
...@@ -11369,7 +11369,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11369,7 +11369,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11369 defer arena_allocator.deinit();11369 defer arena_allocator.deinit();
11370 const arena = arena_allocator.allocator();11370 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());
11373 const w = bw.writer();11373 const w = bw.writer();
1137411374
11375 var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .empty;11375 var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .empty;
src/Package.zig+1-1
...@@ -134,7 +134,7 @@ pub const Hash = struct {...@@ -134,7 +134,7 @@ pub const Hash = struct {
134 }134 }
135 var bin_digest: [Algo.digest_length]u8 = undefined;135 var bin_digest: [Algo.digest_length]u8 = undefined;
136 Algo.hash(sub_path, &bin_digest, .{});136 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;
138 return result;138 return result;
139 }139 }
140};140};
src/Package/Fetch.zig+15-15
...@@ -201,7 +201,7 @@ pub const JobQueue = struct {...@@ -201,7 +201,7 @@ pub const JobQueue = struct {
201 const hash_slice = hash.toSlice();201 const hash_slice = hash.toSlice();
202202
203 try buf.writer().print(203 try buf.writer().print(
204 \\ pub const {} = struct {{204 \\ pub const {f} = struct {{
205 \\205 \\
206 , .{std.zig.fmtId(hash_slice)});206 , .{std.zig.fmtId(hash_slice)});
207207
...@@ -233,9 +233,9 @@ pub const JobQueue = struct {...@@ -233,9 +233,9 @@ pub const JobQueue = struct {
233233
234 if (fetch.has_build_zig) {234 if (fetch.has_build_zig) {
235 try buf.writer().print(235 try buf.writer().print(
236 \\ pub const build_zig = @import("{}");236 \\ pub const build_zig = @import("{f}");
237 \\237 \\
238 , .{std.zig.fmtEscapes(hash_slice)});238 , .{std.zig.fmtString(hash_slice)});
239 }239 }
240240
241 if (fetch.manifest) |*manifest| {241 if (fetch.manifest) |*manifest| {
...@@ -246,8 +246,8 @@ pub const JobQueue = struct {...@@ -246,8 +246,8 @@ pub const JobQueue = struct {
246 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {246 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {
247 const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue;247 const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue;
248 try buf.writer().print(248 try buf.writer().print(
249 " .{{ \"{}\", \"{}\" }},\n",249 " .{{ \"{f}\", \"{f}\" }},\n",
250 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },250 .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) },
251 );251 );
252 }252 }
253253
...@@ -278,8 +278,8 @@ pub const JobQueue = struct {...@@ -278,8 +278,8 @@ pub const JobQueue = struct {
278 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {278 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {
279 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;279 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;
280 try buf.writer().print(280 try buf.writer().print(
281 " .{{ \"{}\", \"{}\" }},\n",281 " .{{ \"{f}\", \"{f}\" }},\n",
282 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },282 .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) },
283 );283 );
284 }284 }
285 try buf.appendSlice("};\n");285 try buf.appendSlice("};\n");
...@@ -1321,7 +1321,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {...@@ -1321,7 +1321,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {
1321 .{@errorName(err)},1321 .{@errorName(err)},
1322 ));1322 ));
1323 if (len == 0) break;1323 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(
1325 "write temporary zip file failed: {s}",1325 "write temporary zip file failed: {s}",
1326 .{@errorName(err)},1326 .{@errorName(err)},
1327 ));1327 ));
...@@ -1374,7 +1374,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U...@@ -1374,7 +1374,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
1374 var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true });1374 var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true });
1375 defer pack_file.close();1375 defer pack_file.close();
1376 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();1376 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());
1378 try pack_file.sync();1378 try pack_file.sync();
13791379
1380 var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true });1380 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...@@ -1382,7 +1382,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
1382 {1382 {
1383 const index_prog_node = f.prog_node.start("Index pack", 0);1383 const index_prog_node = f.prog_node.start("Index pack", 0);
1384 defer index_prog_node.end();1384 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());
1386 try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer());1386 try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer());
1387 try index_buffered_writer.flush();1387 try index_buffered_writer.flush();
1388 try index_file.sync();1388 try index_file.sync();
...@@ -1655,13 +1655,13 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute...@@ -1655,13 +1655,13 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
16551655
1656fn dumpHashInfo(all_files: []const *const HashedFile) !void {1656fn dumpHashInfo(all_files: []const *const HashedFile) !void {
1657 const stdout: std.fs.File = .stdout();1657 const stdout: std.fs.File = .stdout();
1658 var bw = std.io.bufferedWriter(stdout.writer());1658 var bw = std.io.bufferedWriter(stdout.deprecatedWriter());
1659 const w = bw.writer();1659 const w = bw.writer();
16601660
1661 for (all_files) |hashed_file| {1661 for (all_files) |hashed_file| {
1662 try w.print("{s}: {s}: {s}\n", .{1662 try w.print("{s}: {x}: {s}\n", .{
1663 @tagName(hashed_file.kind),1663 @tagName(hashed_file.kind),
1664 std.fmt.fmtSliceHexLower(&hashed_file.hash),1664 &hashed_file.hash,
1665 hashed_file.normalized_path,1665 hashed_file.normalized_path,
1666 });1666 });
1667 }1667 }
...@@ -2074,7 +2074,7 @@ test "zip" {...@@ -2074,7 +2074,7 @@ test "zip" {
2074 {2074 {
2075 var zip_file = try tmp.dir.createFile("test.zip", .{});2075 var zip_file = try tmp.dir.createFile("test.zip", .{});
2076 defer zip_file.close();2076 defer zip_file.close();
2077 var bw = std.io.bufferedWriter(zip_file.writer());2077 var bw = std.io.bufferedWriter(zip_file.deprecatedWriter());
2078 var store: [test_files.len]std.zip.testutil.FileStore = undefined;2078 var store: [test_files.len]std.zip.testutil.FileStore = undefined;
2079 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});2079 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});
2080 try bw.flush();2080 try bw.flush();
...@@ -2107,7 +2107,7 @@ test "zip with one root folder" {...@@ -2107,7 +2107,7 @@ test "zip with one root folder" {
2107 {2107 {
2108 var zip_file = try tmp.dir.createFile("test.zip", .{});2108 var zip_file = try tmp.dir.createFile("test.zip", .{});
2109 defer zip_file.close();2109 defer zip_file.close();
2110 var bw = std.io.bufferedWriter(zip_file.writer());2110 var bw = std.io.bufferedWriter(zip_file.deprecatedWriter());
2111 var store: [test_files.len]std.zip.testutil.FileStore = undefined;2111 var store: [test_files.len]std.zip.testutil.FileStore = undefined;
2112 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});2112 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});
2113 try bw.flush();2113 try bw.flush();
src/Package/Fetch/git.zig+9-9
...@@ -127,7 +127,7 @@ pub const Oid = union(Format) {...@@ -127,7 +127,7 @@ pub const Oid = union(Format) {
127 ) @TypeOf(writer).Error!void {127 ) @TypeOf(writer).Error!void {
128 _ = fmt;128 _ = fmt;
129 _ = options;129 _ = options;
130 try writer.print("{}", .{std.fmt.fmtSliceHexLower(oid.slice())});130 try writer.print("{x}", .{oid.slice()});
131 }131 }
132132
133 pub fn slice(oid: *const Oid) []const u8 {133 pub fn slice(oid: *const Oid) []const u8 {
...@@ -353,7 +353,7 @@ const Odb = struct {...@@ -353,7 +353,7 @@ const Odb = struct {
353 fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb {353 fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb {
354 try pack_file.seekTo(0);354 try pack_file.seekTo(0);
355 try index_file.seekTo(0);355 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());
357 return .{357 return .{
358 .format = format,358 .format = format,
359 .pack_file = pack_file,359 .pack_file = pack_file,
...@@ -377,7 +377,7 @@ const Odb = struct {...@@ -377,7 +377,7 @@ const Odb = struct {
377 const base_object = while (true) {377 const base_object = while (true) {
378 if (odb.cache.get(base_offset)) |base_object| break base_object;378 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());
381 switch (base_header) {381 switch (base_header) {
382 .ofs_delta => |ofs_delta| {382 .ofs_delta => |ofs_delta| {
383 try delta_offsets.append(odb.allocator, base_offset);383 try delta_offsets.append(odb.allocator, base_offset);
...@@ -390,7 +390,7 @@ const Odb = struct {...@@ -390,7 +390,7 @@ const Odb = struct {
390 base_offset = try odb.pack_file.getPos();390 base_offset = try odb.pack_file.getPos();
391 },391 },
392 else => {392 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());
394 errdefer odb.allocator.free(base_data);394 errdefer odb.allocator.free(base_data);
395 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };395 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };
396 try odb.cache.put(odb.allocator, base_offset, base_object);396 try odb.cache.put(odb.allocator, base_offset, base_object);
...@@ -420,7 +420,7 @@ const Odb = struct {...@@ -420,7 +420,7 @@ const Odb = struct {
420 const found_index = while (start_index < end_index) {420 const found_index = while (start_index < end_index) {
421 const mid_index = start_index + (end_index - start_index) / 2;421 const mid_index = start_index + (end_index - start_index) / 2;
422 try odb.index_file.seekTo(IndexHeader.size + mid_index * oid_length);422 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());
424 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {424 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {
425 .lt => start_index = mid_index + 1,425 .lt => start_index = mid_index + 1,
426 .gt => end_index = mid_index,426 .gt => end_index = mid_index,
...@@ -431,12 +431,12 @@ const Odb = struct {...@@ -431,12 +431,12 @@ const Odb = struct {
431 const n_objects = odb.index_header.fan_out_table[255];431 const n_objects = odb.index_header.fan_out_table[255];
432 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);432 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);
433 try odb.index_file.seekTo(offset_values_start + found_index * 4);433 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));
435 const pack_offset = pack_offset: {435 const pack_offset = pack_offset: {
436 if (l1_offset.big) {436 if (l1_offset.big) {
437 const l2_offset_values_start = offset_values_start + n_objects * 4;437 const l2_offset_values_start = offset_values_start + n_objects * 4;
438 try odb.index_file.seekTo(l2_offset_values_start + l1_offset.value * 4);438 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);
440 } else {440 } else {
441 break :pack_offset l1_offset.value;441 break :pack_offset l1_offset.value;
442 }442 }
...@@ -1561,7 +1561,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void...@@ -1561,7 +1561,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void
15611561
1562 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });1562 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });
1563 defer index_file.close();1563 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
1566 // Arbitrary size limit on files read while checking the repository contents1566 // Arbitrary size limit on files read while checking the repository contents
1567 // (all files in the test repo are known to be smaller than this)1567 // (all files in the test repo are known to be smaller than this)
...@@ -1678,7 +1678,7 @@ pub fn main() !void {...@@ -1678,7 +1678,7 @@ pub fn main() !void {
1678 std.debug.print("Starting index...\n", .{});1678 std.debug.print("Starting index...\n", .{});
1679 var index_file = try git_dir.createFile("idx", .{ .read = true });1679 var index_file = try git_dir.createFile("idx", .{ .read = true });
1680 defer index_file.close();1680 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());
1682 try indexPack(allocator, format, pack_file, index_buffered_writer.writer());1682 try indexPack(allocator, format, pack_file, index_buffered_writer.writer());
1683 try index_buffered_writer.flush();1683 try index_buffered_writer.flush();
1684 try index_file.sync();1684 try index_file.sync();
src/Package/Manifest.zig+2-2
...@@ -401,7 +401,7 @@ const Parse = struct {...@@ -401,7 +401,7 @@ const Parse = struct {
401 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});401 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});
402402
403 if (name.len > max_name_len)403 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}", .{
405 std.zig.fmtId(name), max_name_len,405 std.zig.fmtId(name), max_name_len,
406 });406 });
407407
...@@ -416,7 +416,7 @@ const Parse = struct {...@@ -416,7 +416,7 @@ const Parse = struct {
416 return fail(p, main_token, "name must be a valid bare zig identifier", .{});416 return fail(p, main_token, "name must be a valid bare zig identifier", .{});
417417
418 if (ident_name.len > max_name_len)418 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}", .{
420 std.zig.fmtId(ident_name), max_name_len,420 std.zig.fmtId(ident_name), max_name_len,
421 });421 });
422422
src/Sema.zig+454-452
...@@ -5,6 +5,39 @@...@@ -5,6 +5,39 @@
5//! Does type checking, comptime control flow, and safety-check generation.5//! Does type checking, comptime control flow, and safety-check generation.
6//! This is the the heart of the Zig compiler.6//! 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
8pt: Zcu.PerThread,41pt: Zcu.PerThread,
9/// Alias to `zcu.gpa`.42/// Alias to `zcu.gpa`.
10gpa: Allocator,43gpa: Allocator,
...@@ -157,39 +190,6 @@ pub fn getComptimeAlloc(sema: *Sema, idx: ComptimeAllocIndex) *ComptimeAlloc {...@@ -157,39 +190,6 @@ pub fn getComptimeAlloc(sema: *Sema, idx: ComptimeAllocIndex) *ComptimeAlloc {
157 return &sema.comptime_allocs.items[@intFromEnum(idx)];190 return &sema.comptime_allocs.items[@intFromEnum(idx)];
158}191}
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
193pub const default_branch_quota = 1000;193pub const default_branch_quota = 1000;
194194
195pub const InferredErrorSet = struct {195pub const InferredErrorSet = struct {
...@@ -888,7 +888,7 @@ const ComptimeReason = union(enum) {...@@ -888,7 +888,7 @@ const ComptimeReason = union(enum) {
888 /// Evaluating at comptime because of a comptime-only type. This field is separate so that888 /// Evaluating at comptime because of a comptime-only type. This field is separate so that
889 /// the type in question can be included in the error message. AstGen could never emit this889 /// the type in question can be included in the error message. AstGen could never emit this
890 /// reason, because it knows nothing of types.890 /// 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.
892 /// We will then explain why this type is comptime-only.892 /// We will then explain why this type is comptime-only.
893 comptime_only: struct {893 comptime_only: struct {
894 ty: Type,894 ty: Type,
...@@ -930,17 +930,17 @@ const ComptimeReason = union(enum) {...@@ -930,17 +930,17 @@ const ComptimeReason = union(enum) {
930 .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" },930 .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" },
931 .tuple_init => .{ "initializer of comptime-only tuple", "must be comptime-known" },931 .tuple_init => .{ "initializer of comptime-only tuple", "must be comptime-known" },
932 };932 };
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 });
934 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);934 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
935 },935 },
936 .comptime_only_param_ty => |co| {936 .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)});
938 try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{});938 try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{});
939 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);939 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
940 },940 },
941 .comptime_only_ret_ty => |co| {941 .comptime_only_ret_ty => |co| {
942 const function_with: []const u8 = if (co.is_generic_inst) "generic function instantiated with" else "function with";942 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) });
944 try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{});944 try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{});
945 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);945 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
946 },946 },
...@@ -1905,7 +1905,7 @@ fn analyzeBodyInner(...@@ -1905,7 +1905,7 @@ fn analyzeBodyInner(
1905 const err_union = try sema.resolveInst(extra.data.operand);1905 const err_union = try sema.resolveInst(extra.data.operand);
1906 const err_union_ty = sema.typeOf(err_union);1906 const err_union_ty = sema.typeOf(err_union);
1907 if (err_union_ty.zigTypeTag(zcu) != .error_union) {1907 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}'", .{
1909 err_union_ty.fmt(pt),1909 err_union_ty.fmt(pt),
1910 });1910 });
1911 }1911 }
...@@ -2339,7 +2339,7 @@ pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) Compile...@@ -2339,7 +2339,7 @@ pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) Compile
23392339
2340fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError {2340fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError {
2341 const pt = sema.pt;2341 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", .{
2343 lhs_ty.fmt(pt), rhs_ty.fmt(pt),2343 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
2344 });2344 });
2345}2345}
...@@ -2347,7 +2347,7 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T...@@ -2347,7 +2347,7 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T
2347fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError {2347fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError {
2348 const pt = sema.pt;2348 const pt = sema.pt;
2349 const msg = msg: {2349 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}'", .{
2351 non_optional_ty.fmt(pt),2351 non_optional_ty.fmt(pt),
2352 });2352 });
2353 errdefer msg.destroy(sema.gpa);2353 errdefer msg.destroy(sema.gpa);
...@@ -2363,12 +2363,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non...@@ -2363,12 +2363,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non
2363fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {2363fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
2364 const pt = sema.pt;2364 const pt = sema.pt;
2365 const msg = msg: {2365 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", .{
2367 ty.fmt(pt),2367 ty.fmt(pt),
2368 });2368 });
2369 errdefer msg.destroy(sema.gpa);2369 errdefer msg.destroy(sema.gpa);
2370 if (ty.isSlice(pt.zcu)) {2370 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)});
2372 }2372 }
2373 break :msg msg;2373 break :msg msg;
2374 };2374 };
...@@ -2377,7 +2377,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty...@@ -2377,7 +2377,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty
23772377
2378fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {2378fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
2379 const pt = sema.pt;2379 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", .{
2381 ty.fmt(pt),2381 ty.fmt(pt),
2382 });2382 });
2383}2383}
...@@ -2390,7 +2390,7 @@ fn failWithErrorSetCodeMissing(...@@ -2390,7 +2390,7 @@ fn failWithErrorSetCodeMissing(
2390 src_err_set_ty: Type,2390 src_err_set_ty: Type,
2391) CompileError {2391) CompileError {
2392 const pt = sema.pt;2392 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}'", .{
2394 dest_err_set_ty.fmt(pt), src_err_set_ty.fmt(pt),2394 dest_err_set_ty.fmt(pt), src_err_set_ty.fmt(pt),
2395 });2395 });
2396}2396}
...@@ -2398,7 +2398,7 @@ fn failWithErrorSetCodeMissing(...@@ -2398,7 +2398,7 @@ fn failWithErrorSetCodeMissing(
2398pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError {2398pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError {
2399 const pt = sema.pt;2399 const pt = sema.pt;
2400 return sema.failWithOwnedErrorMsg(block, msg: {2400 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}'", .{
2402 int_ty.fmt(pt), val.fmtValueSema(pt, sema),2402 int_ty.fmt(pt), val.fmtValueSema(pt, sema),
2403 });2403 });
2404 errdefer msg.destroy(sema.gpa);2404 errdefer msg.destroy(sema.gpa);
...@@ -2448,7 +2448,7 @@ fn failWithInvalidFieldAccess(...@@ -2448,7 +2448,7 @@ fn failWithInvalidFieldAccess(
2448 const child_ty = inner_ty.optionalChild(zcu);2448 const child_ty = inner_ty.optionalChild(zcu);
2449 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt;2449 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt;
2450 const msg = msg: {2450 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)});
2452 errdefer msg.destroy(sema.gpa);2452 errdefer msg.destroy(sema.gpa);
2453 try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{});2453 try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{});
2454 break :msg msg;2454 break :msg msg;
...@@ -2458,14 +2458,14 @@ fn failWithInvalidFieldAccess(...@@ -2458,14 +2458,14 @@ fn failWithInvalidFieldAccess(
2458 const child_ty = inner_ty.errorUnionPayload(zcu);2458 const child_ty = inner_ty.errorUnionPayload(zcu);
2459 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err;2459 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err;
2460 const msg = msg: {2460 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)});
2462 errdefer msg.destroy(sema.gpa);2462 errdefer msg.destroy(sema.gpa);
2463 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});2463 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
2464 break :msg msg;2464 break :msg msg;
2465 };2465 };
2466 return sema.failWithOwnedErrorMsg(block, msg);2466 return sema.failWithOwnedErrorMsg(block, msg);
2467 }2467 }
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)});
2469}2469}
24702470
2471fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool {2471fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool {
...@@ -2494,7 +2494,7 @@ fn failWithComptimeErrorRetTrace(...@@ -2494,7 +2494,7 @@ fn failWithComptimeErrorRetTrace(
2494 const pt = sema.pt;2494 const pt = sema.pt;
2495 const zcu = pt.zcu;2495 const zcu = pt.zcu;
2496 const msg = msg: {2496 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)});
2498 errdefer msg.destroy(sema.gpa);2498 errdefer msg.destroy(sema.gpa);
24992499
2500 for (sema.comptime_err_ret_trace.items) |src_loc| {2500 for (sema.comptime_err_ret_trace.items) |src_loc| {
...@@ -3005,7 +3005,7 @@ pub fn createTypeName(...@@ -3005,7 +3005,7 @@ pub fn createTypeName(
3005 inst: ?Zir.Inst.Index,3005 inst: ?Zir.Inst.Index,
3006 /// This is used purely to give the type a unique name in the `anon` case.3006 /// This is used purely to give the type a unique name in the `anon` case.
3007 type_index: InternPool.Index,3007 type_index: InternPool.Index,
3008) !struct {3008) CompileError!struct {
3009 name: InternPool.NullTerminatedString,3009 name: InternPool.NullTerminatedString,
3010 nav: InternPool.Nav.Index.Optional,3010 nav: InternPool.Nav.Index.Optional,
3011} {3011} {
...@@ -3024,11 +3024,10 @@ pub fn createTypeName(...@@ -3024,11 +3024,10 @@ pub fn createTypeName(
3024 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);3024 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
3025 const zir_tags = sema.code.instructions.items(.tag);3025 const zir_tags = sema.code.instructions.items(.tag);
30263026
3027 var buf: std.ArrayListUnmanaged(u8) = .empty;3027 var aw: std.io.Writer.Allocating = .init(gpa);
3028 defer buf.deinit(gpa);3028 defer aw.deinit();
30293029 const bw = &aw.interface;
3030 const writer = buf.writer(gpa);3030 bw.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory;
3031 try writer.print("{}(", .{block.type_name_ctx.fmt(ip)});
30323031
3033 var arg_i: usize = 0;3032 var arg_i: usize = 0;
3034 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {3033 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {
...@@ -3041,18 +3040,18 @@ pub fn createTypeName(...@@ -3041,18 +3040,18 @@ pub fn createTypeName(
3041 // result in a compile error.3040 // result in a compile error.
3042 const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat3041 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
3046 // Limiting the depth here helps avoid type names getting too long, which3045 // Limiting the depth here helps avoid type names getting too long, which
3047 // in turn helps to avoid unreasonably long symbol names for namespaced3046 // in turn helps to avoid unreasonably long symbol names for namespaced
3048 // symbols. Such names should ideally be human-readable, and additionally,3047 // symbols. Such names should ideally be human-readable, and additionally,
3049 // some tooling may not support very long symbol names.3048 // some tooling may not support very long symbol names.
3050 try writer.print("{}", .{Value.fmtValueSemaFull(.{3049 bw.print("{f}", .{Value.fmtValueSemaFull(.{
3051 .val = arg_val,3050 .val = arg_val,
3052 .pt = pt,3051 .pt = pt,
3053 .opt_sema = sema,3052 .opt_sema = sema,
3054 .depth = 1,3053 .depth = 1,
3055 })});3054 })}) catch return error.OutOfMemory;
30563055
3057 arg_i += 1;3056 arg_i += 1;
3058 continue;3057 continue;
...@@ -3060,9 +3059,9 @@ pub fn createTypeName(...@@ -3060,9 +3059,9 @@ pub fn createTypeName(
3060 else => continue,3059 else => continue,
3061 };3060 };
30623061
3063 try writer.writeByte(')');3062 try bw.writeByte(')');
3064 return .{3063 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),
3066 .nav = .none,3065 .nav = .none,
3067 };3066 };
3068 },3067 },
...@@ -3074,7 +3073,7 @@ pub fn createTypeName(...@@ -3074,7 +3073,7 @@ pub fn createTypeName(
3074 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {3073 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
3075 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {3074 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
3076 return .{3075 return .{
3077 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{3076 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{
3078 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),3077 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
3079 }, .no_embedded_nulls),3078 }, .no_embedded_nulls),
3080 .nav = .none,3079 .nav = .none,
...@@ -3097,7 +3096,7 @@ pub fn createTypeName(...@@ -3097,7 +3096,7 @@ pub fn createTypeName(
3097 // that builtin from the language, we can consider this.3096 // that builtin from the language, we can consider this.
30983097
3099 return .{3098 return .{
3100 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{3099 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}__{s}_{d}", .{
3101 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),3100 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
3102 }, .no_embedded_nulls),3101 }, .no_embedded_nulls),
3103 .nav = .none,3102 .nav = .none,
...@@ -3581,7 +3580,7 @@ fn ensureResultUsed(...@@ -3581,7 +3580,7 @@ fn ensureResultUsed(
3581 },3580 },
3582 else => {3581 else => {
3583 const msg = msg: {3582 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)});
3585 errdefer msg.destroy(sema.gpa);3584 errdefer msg.destroy(sema.gpa);
3586 try sema.errNote(src, msg, "all non-void values must be used", .{});3585 try sema.errNote(src, msg, "all non-void values must be used", .{});
3587 try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{});3586 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...@@ -3851,7 +3850,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3851 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.3850 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.
3852 // TODO: source location of runtime control flow3851 // TODO: source location of runtime control flow
3853 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });3852 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)});
3855 }3854 }
38563855
3857 // This is a runtime value.3856 // This is a runtime value.
...@@ -4348,7 +4347,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4348,7 +4347,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4348 // The alloc wasn't comptime-known per the above logic, so the4347 // The alloc wasn't comptime-known per the above logic, so the
4349 // type cannot be comptime-only.4348 // type cannot be comptime-only.
4350 // TODO: source location of runtime control flow4349 // 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)});
4352 }4351 }
4353 if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) {4352 if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) {
4354 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });4353 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....@@ -4445,7 +4444,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4445 if (!object_ty.isIndexable(zcu)) {4444 if (!object_ty.isIndexable(zcu)) {
4446 // Instead of using checkIndexable we customize this error.4445 // Instead of using checkIndexable we customize this error.
4447 const msg = msg: {4446 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)});
4449 errdefer msg.destroy(sema.gpa);4448 errdefer msg.destroy(sema.gpa);
4450 try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{});4449 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....@@ -4480,10 +4479,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4480 .for_node_offset = inst_data.src_node,4479 .for_node_offset = inst_data.src_node,
4481 .input_index = len_idx,4480 .input_index = len_idx,
4482 } });4481 } });
4483 try sema.errNote(a_src, msg, "length {} here", .{4482 try sema.errNote(a_src, msg, "length {f} here", .{
4484 v.fmtValueSema(pt, sema),4483 v.fmtValueSema(pt, sema),
4485 });4484 });
4486 try sema.errNote(arg_src, msg, "length {} here", .{4485 try sema.errNote(arg_src, msg, "length {f} here", .{
4487 arg_val.fmtValueSema(pt, sema),4486 arg_val.fmtValueSema(pt, sema),
4488 });4487 });
4489 break :msg msg;4488 break :msg msg;
...@@ -4515,7 +4514,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4515,7 +4514,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4515 .for_node_offset = inst_data.src_node,4514 .for_node_offset = inst_data.src_node,
4516 .input_index = i,4515 .input_index = i,
4517 } });4516 } });
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", .{
4519 object_ty.fmt(pt),4518 object_ty.fmt(pt),
4520 });4519 });
4521 }4520 }
...@@ -4591,7 +4590,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -4591,7 +4590,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4591 switch (val_ty.zigTypeTag(zcu)) {4590 switch (val_ty.zigTypeTag(zcu)) {
4592 .array, .vector => {},4591 .array, .vector => {},
4593 else => if (!val_ty.isTuple(zcu)) {4592 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) });
4595 },4594 },
4596 }4595 }
4597 const want_ty = try pt.arrayType(.{4596 const want_ty = try pt.arrayType(.{
...@@ -4665,7 +4664,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4665,7 +4664,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4665 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;4664 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;
4666 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {4665 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {
4667 return sema.failWithOwnedErrorMsg(block, msg: {4666 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)});
4669 errdefer msg.destroy(sema.gpa);4668 errdefer msg.destroy(sema.gpa);
4670 try sema.errNote(src, msg, "address-of operator always returns a pointer", .{});4669 try sema.errNote(src, msg, "address-of operator always returns a pointer", .{});
4671 break :msg msg;4670 break :msg msg;
...@@ -5074,7 +5073,7 @@ fn validateStructInit(...@@ -5074,7 +5073,7 @@ fn validateStructInit(
5074 }5073 }
5075 continue;5074 continue;
5076 };5075 };
5077 const template = "missing struct field: {}";5076 const template = "missing struct field: {f}";
5078 const args = .{field_name.fmt(ip)};5077 const args = .{field_name.fmt(ip)};
5079 if (root_msg) |msg| {5078 if (root_msg) |msg| {
5080 try sema.errNote(init_src, msg, template, args);5079 try sema.errNote(init_src, msg, template, args);
...@@ -5204,7 +5203,7 @@ fn validateStructInit(...@@ -5204,7 +5203,7 @@ fn validateStructInit(
5204 }5203 }
5205 continue;5204 continue;
5206 };5205 };
5207 const template = "missing struct field: {}";5206 const template = "missing struct field: {f}";
5208 const args = .{field_name.fmt(ip)};5207 const args = .{field_name.fmt(ip)};
5209 if (root_msg) |msg| {5208 if (root_msg) |msg| {
5210 try sema.errNote(init_src, msg, template, args);5209 try sema.errNote(init_src, msg, template, args);
...@@ -5508,11 +5507,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -5508,11 +5507,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
5508 const operand_ty = sema.typeOf(operand);5507 const operand_ty = sema.typeOf(operand);
55095508
5510 if (operand_ty.zigTypeTag(zcu) != .pointer) {5509 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)});
5512 } else switch (operand_ty.ptrSize(zcu)) {5511 } else switch (operand_ty.ptrSize(zcu)) {
5513 .one, .c => {},5512 .one, .c => {},
5514 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer 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)}),
5515 .slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(pt)}),5514 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),
5516 }5515 }
55175516
5518 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) {5517 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) {
...@@ -5529,7 +5528,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -5529,7 +5528,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
5529 const msg = msg: {5528 const msg = msg: {
5530 const msg = try sema.errMsg(5529 const msg = try sema.errMsg(
5531 src,5530 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",
5533 .{elem_ty.fmt(pt)},5532 .{elem_ty.fmt(pt)},
5534 );5533 );
5535 errdefer msg.destroy(sema.gpa);5534 errdefer msg.destroy(sema.gpa);
...@@ -5561,7 +5560,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -5561,7 +5560,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
55615560
5562 if (!typeIsDestructurable(operand_ty, zcu)) {5561 if (!typeIsDestructurable(operand_ty, zcu)) {
5563 return sema.failWithOwnedErrorMsg(block, msg: {5562 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)});
5565 errdefer msg.destroy(sema.gpa);5564 errdefer msg.destroy(sema.gpa);
5566 try sema.errNote(destructure_src, msg, "result destructured here", .{});5565 try sema.errNote(destructure_src, msg, "result destructured here", .{});
5567 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {5566 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {
...@@ -5604,12 +5603,12 @@ fn failWithBadMemberAccess(...@@ -5604,12 +5603,12 @@ fn failWithBadMemberAccess(
5604 else => unreachable,5603 else => unreachable,
5605 };5604 };
5606 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {5605 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}'", .{
5608 agg_ty.fmt(pt), field_name.fmt(ip),5607 agg_ty.fmt(pt), field_name.fmt(ip),
5609 });5608 });
5610 };5609 };
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}'", .{
5613 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),5612 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
5614 });5613 });
5615}5614}
...@@ -5629,7 +5628,7 @@ fn failWithBadStructFieldAccess(...@@ -5629,7 +5628,7 @@ fn failWithBadStructFieldAccess(
5629 const msg = msg: {5628 const msg = msg: {
5630 const msg = try sema.errMsg(5629 const msg = try sema.errMsg(
5631 field_src,5630 field_src,
5632 "no field named '{}' in struct '{}'",5631 "no field named '{f}' in struct '{f}'",
5633 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },5632 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },
5634 );5633 );
5635 errdefer msg.destroy(sema.gpa);5634 errdefer msg.destroy(sema.gpa);
...@@ -5655,7 +5654,7 @@ fn failWithBadUnionFieldAccess(...@@ -5655,7 +5654,7 @@ fn failWithBadUnionFieldAccess(
5655 const msg = msg: {5654 const msg = msg: {
5656 const msg = try sema.errMsg(5655 const msg = try sema.errMsg(
5657 field_src,5656 field_src,
5658 "no field named '{}' in union '{}'",5657 "no field named '{f}' in union '{f}'",
5659 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },5658 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },
5660 );5659 );
5661 errdefer msg.destroy(gpa);5660 errdefer msg.destroy(gpa);
...@@ -5907,30 +5906,30 @@ fn zirCompileLog(...@@ -5907,30 +5906,30 @@ fn zirCompileLog(
5907 const zcu = pt.zcu;5906 const zcu = pt.zcu;
5908 const gpa = zcu.gpa;5907 const gpa = zcu.gpa;
59095908
5910 var buf: std.ArrayListUnmanaged(u8) = .empty;5909 var aw: std.io.Writer.Allocating = .init(gpa);
5911 defer buf.deinit(gpa);5910 defer aw.deinit();
59125911 const bw = &aw.interface;
5913 const writer = buf.writer(gpa);
59145912
5915 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);5913 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
5916 const src_node = extra.data.src_node;5914 const src_node = extra.data.src_node;
5917 const args = sema.code.refSlice(extra.end, extended.small);5915 const args = sema.code.refSlice(extra.end, extended.small);
59185916
5919 for (args, 0..) |arg_ref, i| {5917 for (args, 0..) |arg_ref, i| {
5920 if (i != 0) try writer.print(", ", .{});5918 if (i != 0) bw.writeAll(", ") catch return error.OutOfMemory;
59215919
5922 const arg = try sema.resolveInst(arg_ref);5920 const arg = try sema.resolveInst(arg_ref);
5923 const arg_ty = sema.typeOf(arg);5921 const arg_ty = sema.typeOf(arg);
5924 if (try sema.resolveValueResolveLazy(arg)) |val| {5922 if (try sema.resolveValueResolveLazy(arg)) |val| {
5925 try writer.print("@as({}, {})", .{5923 bw.print("@as({f}, {f})", .{
5926 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),5924 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),
5927 });5925 }) catch return error.OutOfMemory;
5928 } else {5926 } 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;
5930 }5928 }
5931 }5929 }
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
5935 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {5934 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {
5936 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{5935 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{
...@@ -6472,7 +6471,7 @@ fn resolveAnalyzedBlock(...@@ -6472,7 +6471,7 @@ fn resolveAnalyzedBlock(
6472 const type_src = src; // TODO: better source location6471 const type_src = src; // TODO: better source location
6473 if (try resolved_ty.comptimeOnlySema(pt)) {6472 if (try resolved_ty.comptimeOnlySema(pt)) {
6474 const msg = msg: {6473 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)});
6476 errdefer msg.destroy(sema.gpa);6475 errdefer msg.destroy(sema.gpa);
64776476
6478 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;6477 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...@@ -6588,7 +6587,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
65886587
6589 {6588 {
6590 if (ptr_ty.zigTypeTag(zcu) != .pointer) {6589 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)});
6592 }6591 }
6593 const ptr_ty_info = ptr_ty.ptrInfo(zcu);6592 const ptr_ty_info = ptr_ty.ptrInfo(zcu);
6594 if (ptr_ty_info.flags.size == .slice) {6593 if (ptr_ty_info.flags.size == .slice) {
...@@ -6611,7 +6610,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -6611,7 +6610,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
6611 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);6610 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);
6612 if (!try sema.validateExternType(export_ty, .other)) {6611 if (!try sema.validateExternType(export_ty, .other)) {
6613 return sema.failWithOwnedErrorMsg(block, msg: {6612 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)});
6615 errdefer msg.destroy(sema.gpa);6614 errdefer msg.destroy(sema.gpa);
6616 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);6615 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
6617 try sema.addDeclaredHereNote(msg, export_ty);6616 try sema.addDeclaredHereNote(msg, export_ty);
...@@ -6663,7 +6662,7 @@ pub fn analyzeExport(...@@ -6663,7 +6662,7 @@ pub fn analyzeExport(
66636662
6664 if (!try sema.validateExternType(export_ty, .other)) {6663 if (!try sema.validateExternType(export_ty, .other)) {
6665 return sema.failWithOwnedErrorMsg(block, msg: {6664 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)});
6667 errdefer msg.destroy(gpa);6666 errdefer msg.destroy(gpa);
66686667
6669 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);6668 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
...@@ -7287,7 +7286,7 @@ fn checkCallArgumentCount(...@@ -7287,7 +7286,7 @@ fn checkCallArgumentCount(
7287 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))7286 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))
7288 {7287 {
7289 const msg = msg: {7288 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}'", .{
7291 callee_ty.fmt(pt),7290 callee_ty.fmt(pt),
7292 });7291 });
7293 errdefer msg.destroy(sema.gpa);7292 errdefer msg.destroy(sema.gpa);
...@@ -7299,7 +7298,7 @@ fn checkCallArgumentCount(...@@ -7299,7 +7298,7 @@ fn checkCallArgumentCount(
7299 },7298 },
7300 else => {},7299 else => {},
7301 }7300 }
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)});
7303 };7302 };
73047303
7305 const func_ty_info = zcu.typeToFunc(func_ty).?;7304 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7362,7 +7361,7 @@ fn callBuiltin(...@@ -7362,7 +7361,7 @@ fn callBuiltin(
7362 },7361 },
7363 else => {},7362 else => {},
7364 }7363 }
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)});
7366 };7365 };
73677366
7368 const func_ty_info = zcu.typeToFunc(func_ty).?;7367 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7746,7 +7745,7 @@ fn analyzeCall(...@@ -7746,7 +7745,7 @@ fn analyzeCall(
77467745
7747 if (!param_ty.isValidParamType(zcu)) {7746 if (!param_ty.isValidParamType(zcu)) {
7748 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";7747 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", .{
7750 opaque_str, param_ty.fmt(pt),7749 opaque_str, param_ty.fmt(pt),
7751 });7750 });
7752 }7751 }
...@@ -7843,7 +7842,7 @@ fn analyzeCall(...@@ -7843,7 +7842,7 @@ fn analyzeCall(
78437842
7844 if (!full_ty.isValidReturnType(zcu)) {7843 if (!full_ty.isValidReturnType(zcu)) {
7845 const opaque_str = if (full_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";7844 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", .{
7847 opaque_str, full_ty.fmt(pt),7846 opaque_str, full_ty.fmt(pt),
7848 });7847 });
7849 }7848 }
...@@ -8301,7 +8300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -8301,7 +8300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
8301 }8300 }
8302 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);8301 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);
8303 if (owner_func_ty.toIntern() != func_ty.toIntern()) {8302 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}'", .{
8305 func_ty.fmt(pt), owner_func_ty.fmt(pt),8304 func_ty.fmt(pt), owner_func_ty.fmt(pt),
8306 });8305 });
8307 }8306 }
...@@ -8325,9 +8324,9 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -8325,9 +8324,9 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
8325 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });8324 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });
8326 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);8325 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);
8327 if (child_type.zigTypeTag(zcu) == .@"opaque") {8326 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)});
8329 } else if (child_type.zigTypeTag(zcu) == .null) {8328 } 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)});
8331 }8330 }
8332 const opt_type = try pt.optionalType(child_type.toIntern());8331 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...@@ -8388,7 +8387,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8388 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;8387 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
8389 switch (vec_ty.zigTypeTag(zcu)) {8388 switch (vec_ty.zigTypeTag(zcu)) {
8390 .array, .vector => {},8389 .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)}),
8392 }8391 }
8393 return Air.internedToRef(vec_ty.childType(zcu).toIntern());8392 return Air.internedToRef(vec_ty.childType(zcu).toIntern());
8394}8393}
...@@ -8456,7 +8455,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:...@@ -8456,7 +8455,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:
8456 const pt = sema.pt;8455 const pt = sema.pt;
8457 const zcu = pt.zcu;8456 const zcu = pt.zcu;
8458 if (elem_type.zigTypeTag(zcu) == .@"opaque") {8457 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)});
8460 } else if (elem_type.zigTypeTag(zcu) == .noreturn) {8459 } else if (elem_type.zigTypeTag(zcu) == .noreturn) {
8461 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});8460 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});
8462 }8461 }
...@@ -8492,7 +8491,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8492,7 +8491,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8492 const payload = try sema.resolveType(block, rhs_src, extra.rhs);8491 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
84938492
8494 if (error_set.zigTypeTag(zcu) != .error_set) {8493 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}'", .{
8496 error_set.fmt(pt),8495 error_set.fmt(pt),
8497 });8496 });
8498 }8497 }
...@@ -8505,11 +8504,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p...@@ -8505,11 +8504,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p
8505 const pt = sema.pt;8504 const pt = sema.pt;
8506 const zcu = pt.zcu;8505 const zcu = pt.zcu;
8507 if (payload_ty.zigTypeTag(zcu) == .@"opaque") {8506 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", .{
8509 payload_ty.fmt(pt),8508 payload_ty.fmt(pt),
8510 });8509 });
8511 } else if (payload_ty.zigTypeTag(zcu) == .error_set) {8510 } 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", .{
8513 payload_ty.fmt(pt),8512 payload_ty.fmt(pt),
8514 });8513 });
8515 }8514 }
...@@ -8647,9 +8646,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8647,9 +8646,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8647 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);8646 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);
8648 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);8647 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);
8649 if (lhs_ty.zigTypeTag(zcu) != .error_set)8648 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)});
8651 if (rhs_ty.zigTypeTag(zcu) != .error_set)8650 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
8654 // Anything merged with anyerror is anyerror.8653 // Anything merged with anyerror is anyerror.
8655 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {8654 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...@@ -8759,7 +8758,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8759 return sema.fail(8758 return sema.fail(
8760 block,8759 block,
8761 operand_src,8760 operand_src,
8762 "untagged union '{}' cannot be converted to integer",8761 "untagged union '{f}' cannot be converted to integer",
8763 .{operand_ty.fmt(pt)},8762 .{operand_ty.fmt(pt)},
8764 );8763 );
8765 };8764 };
...@@ -8767,7 +8766,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8767,7 +8766,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8767 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);8766 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);
8768 },8767 },
8769 else => {8768 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}'", .{
8771 operand_ty.fmt(pt),8770 operand_ty.fmt(pt),
8772 });8771 });
8773 },8772 },
...@@ -8778,7 +8777,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8778,7 +8777,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8778 // TODO: use correct solution8777 // TODO: use correct solution
8779 // https://github.com/ziglang/zig/issues/159098778 // https://github.com/ziglang/zig/issues/15909
8780 if (enum_tag_ty.enumFieldCount(zcu) == 0 and !enum_tag_ty.isNonexhaustiveEnum(zcu)) {8779 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}'", .{
8782 enum_tag_ty.fmt(pt),8781 enum_tag_ty.fmt(pt),
8783 });8782 });
8784 }8783 }
...@@ -8812,7 +8811,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8812,7 +8811,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8812 const operand_ty = sema.typeOf(operand);8811 const operand_ty = sema.typeOf(operand);
88138812
8814 if (dest_ty.zigTypeTag(zcu) != .@"enum") {8813 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)});
8816 }8815 }
8817 _ = try sema.checkIntType(block, operand_src, operand_ty);8816 _ = try sema.checkIntType(block, operand_src, operand_ty);
88188817
...@@ -8822,7 +8821,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8822,7 +8821,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8822 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {8821 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
8823 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());8822 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());
8824 }8823 }
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}'", .{
8826 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt),8825 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt),
8827 });8826 });
8828 }8827 }
...@@ -8830,7 +8829,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8830,7 +8829,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8830 return sema.failWithUseOfUndef(block, operand_src);8829 return sema.failWithUseOfUndef(block, operand_src);
8831 }8830 }
8832 if (!(try sema.enumHasInt(dest_ty, int_val))) {8831 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}'", .{
8834 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),8833 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),
8835 });8834 });
8836 }8835 }
...@@ -9024,7 +9023,7 @@ fn zirErrUnionPayload(...@@ -9024,7 +9023,7 @@ fn zirErrUnionPayload(
9024 const operand_src = src;9023 const operand_src = src;
9025 const err_union_ty = sema.typeOf(operand);9024 const err_union_ty = sema.typeOf(operand);
9026 if (err_union_ty.zigTypeTag(zcu) != .error_union) {9025 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}'", .{
9028 err_union_ty.fmt(pt),9027 err_union_ty.fmt(pt),
9029 });9028 });
9030 }9029 }
...@@ -9092,7 +9091,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -9092,7 +9091,7 @@ fn analyzeErrUnionPayloadPtr(
9092 assert(operand_ty.zigTypeTag(zcu) == .pointer);9091 assert(operand_ty.zigTypeTag(zcu) == .pointer);
90939092
9094 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {9093 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}'", .{
9096 operand_ty.childType(zcu).fmt(pt),9095 operand_ty.childType(zcu).fmt(pt),
9097 });9096 });
9098 }9097 }
...@@ -9169,7 +9168,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air...@@ -9169,7 +9168,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
9169 const zcu = pt.zcu;9168 const zcu = pt.zcu;
9170 const operand_ty = sema.typeOf(operand);9169 const operand_ty = sema.typeOf(operand);
9171 if (operand_ty.zigTypeTag(zcu) != .error_union) {9170 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}'", .{
9173 operand_ty.fmt(pt),9172 operand_ty.fmt(pt),
9174 });9173 });
9175 }9174 }
...@@ -9205,7 +9204,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:...@@ -9205,7 +9204,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:
9205 assert(operand_ty.zigTypeTag(zcu) == .pointer);9204 assert(operand_ty.zigTypeTag(zcu) == .pointer);
92069205
9207 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {9206 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}'", .{
9209 operand_ty.childType(zcu).fmt(pt),9208 operand_ty.childType(zcu).fmt(pt),
9210 });9209 });
9211 }9210 }
...@@ -9450,19 +9449,18 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {...@@ -9450,19 +9449,18 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
9450fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {9449fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {
9451 const CallingConventionsSupportingVarArgsList = struct {9450 const CallingConventionsSupportingVarArgsList = struct {
9452 arch: std.Target.Cpu.Arch,9451 arch: std.Target.Cpu.Arch,
9453 pub fn format(ctx: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {9452 pub fn format(ctx: @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
9454 _ = fmt;9453 comptime assert(fmt.len == 0);
9455 _ = options;
9456 var first = true;9454 var first = true;
9457 for (calling_conventions_supporting_var_args) |cc_inner| {9455 for (calling_conventions_supporting_var_args) |cc_inner| {
9458 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {9456 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {
9459 if (supported_arch == ctx.arch) break;9457 if (supported_arch == ctx.arch) break;
9460 } else continue; // callconv not supported by this arch9458 } else continue; // callconv not supported by this arch
9461 if (!first) {9459 if (!first) {
9462 try writer.writeAll(", ");9460 try w.writeAll(", ");
9463 }9461 }
9464 first = false;9462 first = false;
9465 try writer.print("'{s}'", .{@tagName(cc_inner)});9463 try w.print("'{s}'", .{@tagName(cc_inner)});
9466 }9464 }
9467 }9465 }
9468 };9466 };
...@@ -9472,7 +9470,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:...@@ -9472,7 +9470,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
9472 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});9470 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});
9473 errdefer msg.destroy(sema.gpa);9471 errdefer msg.destroy(sema.gpa);
9474 const target = sema.pt.zcu.getTarget();9472 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 }});
9476 break :msg msg;9474 break :msg msg;
9477 });9475 });
9478 }9476 }
...@@ -9520,7 +9518,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)...@@ -9520,7 +9518,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)
9520 }9518 }
95219519
9522 return sema.failWithOwnedErrorMsg(block, msg: {9520 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)});
9524 errdefer msg.destroy(sema.gpa);9522 errdefer msg.destroy(sema.gpa);
95259523
9526 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;9524 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;
...@@ -9598,13 +9596,13 @@ fn funcCommon(...@@ -9598,13 +9596,13 @@ fn funcCommon(
9598 }9596 }
9599 if (!param_ty.isValidParamType(zcu)) {9597 if (!param_ty.isValidParamType(zcu)) {
9600 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9598 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", .{
9602 opaque_str, param_ty.fmt(pt),9600 opaque_str, param_ty.fmt(pt),
9603 });9601 });
9604 }9602 }
9605 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {9603 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {
9606 const msg = msg: {9604 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}'", .{
9608 param_ty.fmt(pt), @tagName(cc),9606 param_ty.fmt(pt), @tagName(cc),
9609 });9607 });
9610 errdefer msg.destroy(sema.gpa);9608 errdefer msg.destroy(sema.gpa);
...@@ -9618,7 +9616,7 @@ fn funcCommon(...@@ -9618,7 +9616,7 @@ fn funcCommon(
9618 }9616 }
9619 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {9617 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
9620 const msg = msg: {9618 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", .{
9622 param_ty.fmt(pt),9620 param_ty.fmt(pt),
9623 });9621 });
9624 errdefer msg.destroy(sema.gpa);9622 errdefer msg.destroy(sema.gpa);
...@@ -9798,7 +9796,7 @@ fn finishFunc(...@@ -9798,7 +9796,7 @@ fn finishFunc(
97989796
9799 if (!return_type.isValidReturnType(zcu)) {9797 if (!return_type.isValidReturnType(zcu)) {
9800 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9798 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", .{
9802 opaque_str, return_type.fmt(pt),9800 opaque_str, return_type.fmt(pt),
9803 });9801 });
9804 }9802 }
...@@ -9806,7 +9804,7 @@ fn finishFunc(...@@ -9806,7 +9804,7 @@ fn finishFunc(
9806 !try sema.validateExternType(return_type, .ret_ty))9804 !try sema.validateExternType(return_type, .ret_ty))
9807 {9805 {
9808 const msg = msg: {9806 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}'", .{
9810 return_type.fmt(pt), @tagName(cc_resolved),9808 return_type.fmt(pt), @tagName(cc_resolved),
9811 });9809 });
9812 errdefer msg.destroy(gpa);9810 errdefer msg.destroy(gpa);
...@@ -9828,7 +9826,7 @@ fn finishFunc(...@@ -9828,7 +9826,7 @@ fn finishFunc(
98289826
9829 const msg = try sema.errMsg(9827 const msg = try sema.errMsg(
9830 ret_ty_src,9828 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",
9832 .{return_type.fmt(pt)},9830 .{return_type.fmt(pt)},
9833 );9831 );
9834 errdefer msg.destroy(sema.gpa);9832 errdefer msg.destroy(sema.gpa);
...@@ -9897,17 +9895,16 @@ fn finishFunc(...@@ -9897,17 +9895,16 @@ fn finishFunc(
9897 .bad_arch => |allowed_archs| {9895 .bad_arch => |allowed_archs| {
9898 const ArchListFormatter = struct {9896 const ArchListFormatter = struct {
9899 archs: []const std.Target.Cpu.Arch,9897 archs: []const std.Target.Cpu.Arch,
9900 pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {9898 pub fn format(formatter: @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
9901 _ = fmt;9899 comptime assert(fmt.len == 0);
9902 _ = options;
9903 for (formatter.archs, 0..) |arch, i| {9900 for (formatter.archs, 0..) |arch, i| {
9904 if (i != 0)9901 if (i != 0)
9905 try writer.writeAll(", ");9902 try w.writeAll(", ");
9906 try writer.print("'{s}'", .{@tagName(arch)});9903 try w.print("'{s}'", .{@tagName(arch)});
9907 }9904 }
9908 }9905 }
9909 };9906 };
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}", .{
9911 @tagName(cc_resolved),9908 @tagName(cc_resolved),
9912 ArchListFormatter{ .archs = allowed_archs },9909 ArchListFormatter{ .archs = allowed_archs },
9913 });9910 });
...@@ -10008,7 +10005,7 @@ fn analyzeAs(...@@ -10008,7 +10005,7 @@ fn analyzeAs(
10008 const operand = try sema.resolveInst(zir_operand);10005 const operand = try sema.resolveInst(zir_operand);
10009 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;10006 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
10010 switch (dest_ty.zigTypeTag(zcu)) {10007 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)}),
10012 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),10009 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
10013 else => {},10010 else => {},
10014 }10011 }
...@@ -10036,12 +10033,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10036,12 +10033,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10036 const ptr_ty = operand_ty.scalarType(zcu);10033 const ptr_ty = operand_ty.scalarType(zcu);
10037 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;10034 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
10038 if (!ptr_ty.isPtrAtRuntime(zcu)) {10035 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)});
10040 }10037 }
10041 const pointee_ty = ptr_ty.childType(zcu);10038 const pointee_ty = ptr_ty.childType(zcu);
10042 if (try ptr_ty.comptimeOnlySema(pt)) {10039 if (try ptr_ty.comptimeOnlySema(pt)) {
10043 const msg = msg: {10040 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)});
10045 errdefer msg.destroy(sema.gpa);10042 errdefer msg.destroy(sema.gpa);
10046 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);10043 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);
10047 break :msg msg;10044 break :msg msg;
...@@ -10289,14 +10286,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10289,14 +10286,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10289 .type,10286 .type,
10290 .undefined,10287 .undefined,
10291 .void,10288 .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
10294 .@"enum" => {10291 .@"enum" => {
10295 const msg = msg: {10292 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)});
10297 errdefer msg.destroy(sema.gpa);10294 errdefer msg.destroy(sema.gpa);
10298 switch (operand_ty.zigTypeTag(zcu)) {10295 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)}),
10300 else => {},10297 else => {},
10301 }10298 }
1030210299
...@@ -10307,11 +10304,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10307,11 +10304,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1030710304
10308 .pointer => {10305 .pointer => {
10309 const msg = msg: {10306 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)});
10311 errdefer msg.destroy(sema.gpa);10308 errdefer msg.destroy(sema.gpa);
10312 switch (operand_ty.zigTypeTag(zcu)) {10309 switch (operand_ty.zigTypeTag(zcu)) {
10313 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt 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)}),
10314 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(pt)}),10311 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}),
10315 else => {},10312 else => {},
10316 }10313 }
1031710314
...@@ -10325,7 +10322,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10325,7 +10322,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10325 .@"union" => "union",10322 .@"union" => "union",
10326 else => unreachable,10323 else => unreachable,
10327 };10324 };
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", .{
10329 dest_ty.fmt(pt), container,10326 dest_ty.fmt(pt), container,
10330 });10327 });
10331 },10328 },
...@@ -10353,14 +10350,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10353,14 +10350,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10353 .type,10350 .type,
10354 .undefined,10351 .undefined,
10355 .void,10352 .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
10358 .@"enum" => {10355 .@"enum" => {
10359 const msg = msg: {10356 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)});
10361 errdefer msg.destroy(sema.gpa);10358 errdefer msg.destroy(sema.gpa);
10362 switch (dest_ty.zigTypeTag(zcu)) {10359 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)}),
10364 else => {},10361 else => {},
10365 }10362 }
1036610363
...@@ -10370,11 +10367,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10370,11 +10367,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10370 },10367 },
10371 .pointer => {10368 .pointer => {
10372 const msg = msg: {10369 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)});
10374 errdefer msg.destroy(sema.gpa);10371 errdefer msg.destroy(sema.gpa);
10375 switch (dest_ty.zigTypeTag(zcu)) {10372 switch (dest_ty.zigTypeTag(zcu)) {
10376 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr 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)}),
10377 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(pt)}),10374 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}),
10378 else => {},10375 else => {},
10379 }10376 }
1038010377
...@@ -10388,7 +10385,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10388,7 +10385,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10388 .@"union" => "union",10385 .@"union" => "union",
10389 else => unreachable,10386 else => unreachable,
10390 };10387 };
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", .{
10392 operand_ty.fmt(pt), container,10389 operand_ty.fmt(pt), container,
10393 });10390 });
10394 },10391 },
...@@ -10431,7 +10428,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10431,7 +10428,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10431 else => return sema.fail(10428 else => return sema.fail(
10432 block,10429 block,
10433 src,10430 src,
10434 "expected float or vector type, found '{}'",10431 "expected float or vector type, found '{f}'",
10435 .{dest_ty.fmt(pt)},10432 .{dest_ty.fmt(pt)},
10436 ),10433 ),
10437 };10434 };
...@@ -10441,7 +10438,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10441,7 +10438,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10441 else => return sema.fail(10438 else => return sema.fail(
10442 block,10439 block,
10443 operand_src,10440 operand_src,
10444 "expected float or vector type, found '{}'",10441 "expected float or vector type, found '{f}'",
10445 .{operand_ty.fmt(pt)},10442 .{operand_ty.fmt(pt)},
10446 ),10443 ),
10447 }10444 }
...@@ -10525,7 +10522,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10525,7 +10522,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10525 if (indexable_ty.zigTypeTag(zcu) != .pointer) {10522 if (indexable_ty.zigTypeTag(zcu) != .pointer) {
10526 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });10523 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });
10527 const msg = msg: {10524 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}'", .{
10529 indexable_ty.fmt(pt),10526 indexable_ty.fmt(pt),
10530 });10527 });
10531 errdefer msg.destroy(sema.gpa);10528 errdefer msg.destroy(sema.gpa);
...@@ -10667,7 +10664,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -10667,7 +10664,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
10667 const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand));10664 const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand));
10668 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {10665 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {
10669 .pointer => lhs_ptr_ty.childType(zcu),10666 .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)}),
10671 };10668 };
1067210669
10673 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {10670 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {
...@@ -10682,7 +10679,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -10682,7 +10679,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
10682 };10679 };
10683 },10680 },
10684 },10681 },
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)}),
10686 };10683 };
1068710684
10688 return Air.internedToRef(sentinel_ty.toIntern());10685 return Air.internedToRef(sentinel_ty.toIntern());
...@@ -10877,7 +10874,7 @@ const SwitchProngAnalysis = struct {...@@ -10877,7 +10874,7 @@ const SwitchProngAnalysis = struct {
10877 .base_node_inst = capture_src.base_node_inst,10874 .base_node_inst = capture_src.base_node_inst,
10878 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },10875 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },
10879 };10876 };
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}'", .{
10881 operand_ty.fmt(pt),10878 operand_ty.fmt(pt),
10882 });10879 });
10883 }10880 }
...@@ -11309,7 +11306,7 @@ fn switchCond(...@@ -11309,7 +11306,7 @@ fn switchCond(
11309 .@"enum",11306 .@"enum",
11310 => {11307 => {
11311 if (operand_ty.isSlice(zcu)) {11308 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)});
11313 }11310 }
11314 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {11311 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
11315 return Air.internedToRef(opv.toIntern());11312 return Air.internedToRef(opv.toIntern());
...@@ -11344,7 +11341,7 @@ fn switchCond(...@@ -11344,7 +11341,7 @@ fn switchCond(
11344 .vector,11341 .vector,
11345 .frame,11342 .frame,
11346 .@"anyframe",11343 .@"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)}),
11348 }11345 }
11349}11346}
1135011347
...@@ -11445,7 +11442,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11445,7 +11442,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11445 operand_ty;11442 operand_ty;
1144611443
11447 if (operand_err_set.zigTypeTag(zcu) != .error_union) {11444 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}'", .{
11449 operand_ty.fmt(pt),11446 operand_ty.fmt(pt),
11450 });11447 });
11451 }11448 }
...@@ -11699,7 +11696,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11699,7 +11696,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11699 // Even if the operand is comptime-known, this `switch` is runtime.11696 // Even if the operand is comptime-known, this `switch` is runtime.
11700 if (try operand_ty.comptimeOnlySema(pt)) {11697 if (try operand_ty.comptimeOnlySema(pt)) {
11701 return sema.failWithOwnedErrorMsg(block, msg: {11698 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)});
11703 errdefer msg.destroy(gpa);11700 errdefer msg.destroy(gpa);
11704 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});11701 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});
11705 break :msg msg;11702 break :msg msg;
...@@ -11923,14 +11920,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11923,14 +11920,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11923 cond_ty,11920 cond_ty,
11924 i,11921 i,
11925 msg,11922 msg,
11926 "unhandled enumeration value: '{}'",11923 "unhandled enumeration value: '{f}'",
11927 .{field_name.fmt(&zcu.intern_pool)},11924 .{field_name.fmt(&zcu.intern_pool)},
11928 );11925 );
11929 }11926 }
11930 try sema.errNote(11927 try sema.errNote(
11931 cond_ty.srcLoc(zcu),11928 cond_ty.srcLoc(zcu),
11932 msg,11929 msg,
11933 "enum '{}' declared here",11930 "enum '{f}' declared here",
11934 .{cond_ty.fmt(pt)},11931 .{cond_ty.fmt(pt)},
11935 );11932 );
11936 break :msg msg;11933 break :msg msg;
...@@ -12142,7 +12139,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12142,7 +12139,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12142 return sema.fail(12139 return sema.fail(
12143 block,12140 block,
12144 src,12141 src,
12145 "else prong required when switching on type '{}'",12142 "else prong required when switching on type '{f}'",
12146 .{cond_ty.fmt(pt)},12143 .{cond_ty.fmt(pt)},
12147 );12144 );
12148 }12145 }
...@@ -12218,7 +12215,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12218,7 +12215,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12218 .@"anyframe",12215 .@"anyframe",
12219 .comptime_float,12216 .comptime_float,
12220 .float,12217 .float,
12221 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{12218 => return sema.fail(block, operand_src, "invalid switch operand type '{f}'", .{
12222 raw_operand_ty.fmt(pt),12219 raw_operand_ty.fmt(pt),
12223 }),12220 }),
12224 }12221 }
...@@ -12747,7 +12744,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12747,7 +12744,7 @@ fn analyzeSwitchRuntimeBlock(
12747 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {12744 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {
12748 .@"enum" => {12745 .@"enum" => {
12749 if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) {12746 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'", .{
12751 operand_ty.fmt(pt),12748 operand_ty.fmt(pt),
12752 });12749 });
12753 }12750 }
...@@ -12803,7 +12800,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12803,7 +12800,7 @@ fn analyzeSwitchRuntimeBlock(
12803 },12800 },
12804 .error_set => {12801 .error_set => {
12805 if (operand_ty.isAnyError(zcu)) {12802 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'", .{
12807 operand_ty.fmt(pt),12804 operand_ty.fmt(pt),
12808 });12805 });
12809 }12806 }
...@@ -12964,7 +12961,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12964,7 +12961,7 @@ fn analyzeSwitchRuntimeBlock(
12964 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));12961 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));
12965 }12962 }
12966 },12963 },
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'", .{
12968 operand_ty.fmt(pt),12965 operand_ty.fmt(pt),
12969 }),12966 }),
12970 };12967 };
...@@ -13478,7 +13475,7 @@ fn validateErrSetSwitch(...@@ -13478,7 +13475,7 @@ fn validateErrSetSwitch(
13478 try sema.errNote(13475 try sema.errNote(
13479 src,13476 src,
13480 msg,13477 msg,
13481 "unhandled error value: 'error.{}'",13478 "unhandled error value: 'error.{f}'",
13482 .{error_name.fmt(ip)},13479 .{error_name.fmt(ip)},
13483 );13480 );
13484 }13481 }
...@@ -13704,7 +13701,7 @@ fn validateSwitchNoRange(...@@ -13704,7 +13701,7 @@ fn validateSwitchNoRange(
13704 const msg = msg: {13701 const msg = msg: {
13705 const msg = try sema.errMsg(13702 const msg = try sema.errMsg(
13706 operand_src,13703 operand_src,
13707 "ranges not allowed when switching on type '{}'",13704 "ranges not allowed when switching on type '{f}'",
13708 .{operand_ty.fmt(sema.pt)},13705 .{operand_ty.fmt(sema.pt)},
13709 );13706 );
13710 errdefer msg.destroy(sema.gpa);13707 errdefer msg.destroy(sema.gpa);
...@@ -13862,7 +13859,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13862,7 +13859,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13862 .array_type => break :hf field_name.eqlSlice("len", ip),13859 .array_type => break :hf field_name.eqlSlice("len", ip),
13863 else => {},13860 else => {},
13864 }13861 }
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'", .{
13866 ty.fmt(pt),13863 ty.fmt(pt),
13867 });13864 });
13868 };13865 };
...@@ -14050,7 +14047,7 @@ fn zirShl(...@@ -14050,7 +14047,7 @@ fn zirShl(
14050 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14047 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14051 const rhs_elem = try rhs_val.elemValue(pt, i);14048 const rhs_elem = try rhs_val.elemValue(pt, i);
14052 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {14049 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}'", .{
14054 rhs_elem.fmtValueSema(pt, sema),14051 rhs_elem.fmtValueSema(pt, sema),
14055 i,14052 i,
14056 scalar_ty.fmt(pt),14053 scalar_ty.fmt(pt),
...@@ -14058,7 +14055,7 @@ fn zirShl(...@@ -14058,7 +14055,7 @@ fn zirShl(
14058 }14055 }
14059 }14056 }
14060 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {14057 } 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}'", .{
14062 rhs_val.fmtValueSema(pt, sema),14059 rhs_val.fmtValueSema(pt, sema),
14063 scalar_ty.fmt(pt),14060 scalar_ty.fmt(pt),
14064 });14061 });
...@@ -14069,14 +14066,14 @@ fn zirShl(...@@ -14069,14 +14066,14 @@ fn zirShl(
14069 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14066 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14070 const rhs_elem = try rhs_val.elemValue(pt, i);14067 const rhs_elem = try rhs_val.elemValue(pt, i);
14071 if (rhs_elem.compareHetero(.lt, try pt.intValue(scalar_rhs_ty, 0), zcu)) {14068 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}'", .{
14073 rhs_elem.fmtValueSema(pt, sema),14070 rhs_elem.fmtValueSema(pt, sema),
14074 i,14071 i,
14075 });14072 });
14076 }14073 }
14077 }14074 }
14078 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {14075 } 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}'", .{
14080 rhs_val.fmtValueSema(pt, sema),14077 rhs_val.fmtValueSema(pt, sema),
14081 });14078 });
14082 }14079 }
...@@ -14231,7 +14228,7 @@ fn zirShr(...@@ -14231,7 +14228,7 @@ fn zirShr(
14231 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14228 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14232 const rhs_elem = try rhs_val.elemValue(pt, i);14229 const rhs_elem = try rhs_val.elemValue(pt, i);
14233 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {14230 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}'", .{
14235 rhs_elem.fmtValueSema(pt, sema),14232 rhs_elem.fmtValueSema(pt, sema),
14236 i,14233 i,
14237 scalar_ty.fmt(pt),14234 scalar_ty.fmt(pt),
...@@ -14239,7 +14236,7 @@ fn zirShr(...@@ -14239,7 +14236,7 @@ fn zirShr(
14239 }14236 }
14240 }14237 }
14241 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {14238 } 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}'", .{
14243 rhs_val.fmtValueSema(pt, sema),14240 rhs_val.fmtValueSema(pt, sema),
14244 scalar_ty.fmt(pt),14241 scalar_ty.fmt(pt),
14245 });14242 });
...@@ -14250,14 +14247,14 @@ fn zirShr(...@@ -14250,14 +14247,14 @@ fn zirShr(
14250 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14247 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14251 const rhs_elem = try rhs_val.elemValue(pt, i);14248 const rhs_elem = try rhs_val.elemValue(pt, i);
14252 if (rhs_elem.compareHetero(.lt, try pt.intValue(rhs_ty.childType(zcu), 0), zcu)) {14249 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}'", .{
14254 rhs_elem.fmtValueSema(pt, sema),14251 rhs_elem.fmtValueSema(pt, sema),
14255 i,14252 i,
14256 });14253 });
14257 }14254 }
14258 }14255 }
14259 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {14256 } 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}'", .{
14261 rhs_val.fmtValueSema(pt, sema),14258 rhs_val.fmtValueSema(pt, sema),
14262 });14259 });
14263 }14260 }
...@@ -14543,11 +14540,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14543,11 +14540,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1454314540
14544 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {14541 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {
14545 if (lhs_is_tuple) break :lhs_info undefined;14542 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)});
14547 };14544 };
14548 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {14545 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {
14549 assert(!rhs_is_tuple);14546 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)});
14551 };14548 };
1455214549
14553 const resolved_elem_ty = t: {14550 const resolved_elem_ty = t: {
...@@ -15000,7 +14997,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15000,7 +14997,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15000 // Analyze the lhs first, to catch the case that someone tried to do exponentiation14997 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
15001 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {14998 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
15002 const msg = msg: {14999 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)});
15004 errdefer msg.destroy(sema.gpa);15001 errdefer msg.destroy(sema.gpa);
15005 switch (lhs_ty.zigTypeTag(zcu)) {15002 switch (lhs_ty.zigTypeTag(zcu)) {
15006 .int, .float, .comptime_float, .comptime_int, .vector => {15003 .int, .float, .comptime_float, .comptime_int, .vector => {
...@@ -15132,7 +15129,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15132,7 +15129,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15132 .int, .comptime_int, .float, .comptime_float => false,15129 .int, .comptime_int, .float, .comptime_float => false,
15133 else => true,15130 else => true,
15134 }) {15131 }) {
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)});
15136 }15133 }
1513715134
15138 if (rhs_scalar_ty.isAnyFloat()) {15135 if (rhs_scalar_ty.isAnyFloat()) {
...@@ -15163,7 +15160,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -15163,7 +15160,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1516315160
15164 switch (rhs_scalar_ty.zigTypeTag(zcu)) {15161 switch (rhs_scalar_ty.zigTypeTag(zcu)) {
15165 .int, .comptime_int, .float, .comptime_float => {},15162 .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)}),
15167 }15164 }
1516815165
15169 const lhs = Air.internedToRef((try sema.splat(rhs_ty, try pt.intValue(rhs_scalar_ty, 0))).toIntern());15166 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...@@ -15237,7 +15234,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15237 return sema.fail(15234 return sema.fail(
15238 block,15235 block,
15239 src,15236 src,
15240 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",15237 "ambiguous coercion of division operands '{f}' and '{f}'; non-zero remainder '{f}'",
15241 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), rem.fmtValueSema(pt, sema) },15238 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), rem.fmtValueSema(pt, sema) },
15242 );15239 );
15243 }15240 }
...@@ -15289,7 +15286,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15289,7 +15286,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15289 return sema.fail(15286 return sema.fail(
15290 block,15287 block,
15291 src,15288 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",
15293 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },15290 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },
15294 );15291 );
15295 }15292 }
...@@ -15951,7 +15948,7 @@ fn zirOverflowArithmetic(...@@ -15951,7 +15948,7 @@ fn zirOverflowArithmetic(
15951 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);15948 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);
1595215949
15953 if (dest_ty.scalarType(zcu).zigTypeTag(zcu) != .int) {15950 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)});
15955 }15952 }
1595615953
15957 const maybe_lhs_val = try sema.resolveValue(lhs);15954 const maybe_lhs_val = try sema.resolveValue(lhs);
...@@ -16157,14 +16154,14 @@ fn analyzeArithmetic(...@@ -16157,14 +16154,14 @@ fn analyzeArithmetic(
16157 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");16154 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");
16158 }16155 }
16159 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {16156 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}'", .{
16161 lhs_ty.fmt(pt), rhs_ty.fmt(pt),16158 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
16162 });16159 });
16163 }16160 }
1616416161
16165 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);16162 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
16166 if (elem_size == 0) {16163 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", .{
16168 lhs_ty.elemType2(zcu).fmt(pt),16165 lhs_ty.elemType2(zcu).fmt(pt),
16169 });16166 });
16170 }16167 }
...@@ -16215,7 +16212,7 @@ fn analyzeArithmetic(...@@ -16215,7 +16212,7 @@ fn analyzeArithmetic(
16215 };16212 };
1621616213
16217 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {16214 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", .{
16219 lhs_ty.elemType2(zcu).fmt(pt),16216 lhs_ty.elemType2(zcu).fmt(pt),
16220 });16217 });
16221 }16218 }
...@@ -16619,7 +16616,7 @@ fn zirCmpEq(...@@ -16619,7 +16616,7 @@ fn zirCmpEq(
1661916616
16620 if (lhs_ty_tag == .null or rhs_ty_tag == .null) {16617 if (lhs_ty_tag == .null or rhs_ty_tag == .null) {
16621 const non_null_type = if (lhs_ty_tag == .null) rhs_ty else lhs_ty;16618 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)});
16623 }16620 }
1662416621
16625 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {16622 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {
...@@ -16676,7 +16673,7 @@ fn analyzeCmpUnionTag(...@@ -16676,7 +16673,7 @@ fn analyzeCmpUnionTag(
16676 const msg = msg: {16673 const msg = msg: {
16677 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});16674 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
16678 errdefer msg.destroy(sema.gpa);16675 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)});
16680 break :msg msg;16677 break :msg msg;
16681 };16678 };
16682 return sema.failWithOwnedErrorMsg(block, msg);16679 return sema.failWithOwnedErrorMsg(block, msg);
...@@ -16762,7 +16759,7 @@ fn analyzeCmp(...@@ -16762,7 +16759,7 @@ fn analyzeCmp(
16762 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };16759 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
16763 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });16760 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
16764 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {16761 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}'", .{
16766 compareOperatorName(op), resolved_type.fmt(pt),16763 compareOperatorName(op), resolved_type.fmt(pt),
16767 });16764 });
16768 }16765 }
...@@ -16871,7 +16868,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -16871,7 +16868,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
16871 .undefined,16868 .undefined,
16872 .null,16869 .null,
16873 .@"opaque",16870 .@"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
16876 .type,16873 .type,
16877 .enum_literal,16874 .enum_literal,
...@@ -16912,7 +16909,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -16912,7 +16909,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16912 .undefined,16909 .undefined,
16913 .null,16910 .null,
16914 .@"opaque",16911 .@"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
16917 .type,16914 .type,
16918 .enum_literal,16915 .enum_literal,
...@@ -18212,7 +18209,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi...@@ -18212,7 +18209,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
18212 return sema.fail(18209 return sema.fail(
18213 block,18210 block,
18214 src,18211 src,
18215 "bit shifting operation expected integer type, found '{}'",18212 "bit shifting operation expected integer type, found '{f}'",
18216 .{operand.fmt(pt)},18213 .{operand.fmt(pt)},
18217 );18214 );
18218}18215}
...@@ -18451,7 +18448,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi...@@ -18451,7 +18448,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi
18451 const pt = sema.pt;18448 const pt = sema.pt;
18452 const zcu = pt.zcu;18449 const zcu = pt.zcu;
18453 if (!ty.isSelfComparable(zcu, true)) {18450 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)});
18455 }18452 }
18456}18453}
1845718454
...@@ -18501,7 +18498,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -18501,7 +18498,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
18501 const zcu = pt.zcu;18498 const zcu = pt.zcu;
18502 switch (ty.zigTypeTag(zcu)) {18499 switch (ty.zigTypeTag(zcu)) {
18503 .error_set, .error_union, .undefined => return,18500 .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}'", .{
18505 ty.fmt(pt),18502 ty.fmt(pt),
18506 }),18503 }),
18507 }18504 }
...@@ -18645,7 +18642,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -18645,7 +18642,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
18645 const pt = sema.pt;18642 const pt = sema.pt;
18646 const zcu = pt.zcu;18643 const zcu = pt.zcu;
18647 if (err_union_ty.zigTypeTag(zcu) != .error_union) {18644 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}'", .{
18649 err_union_ty.fmt(pt),18646 err_union_ty.fmt(pt),
18650 });18647 });
18651 }18648 }
...@@ -18705,7 +18702,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -18705,7 +18702,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
18705 const pt = sema.pt;18702 const pt = sema.pt;
18706 const zcu = pt.zcu;18703 const zcu = pt.zcu;
18707 if (err_union_ty.zigTypeTag(zcu) != .error_union) {18704 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}'", .{
18709 err_union_ty.fmt(pt),18706 err_union_ty.fmt(pt),
18710 });18707 });
18711 }18708 }
...@@ -18903,7 +18900,7 @@ fn zirRetImplicit(...@@ -18903,7 +18900,7 @@ fn zirRetImplicit(
18903 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);18900 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
18904 if (base_tag == .noreturn) {18901 if (base_tag == .noreturn) {
18905 const msg = msg: {18902 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", .{
18907 sema.fn_ret_ty.fmt(pt),18904 sema.fn_ret_ty.fmt(pt),
18908 });18905 });
18909 errdefer msg.destroy(sema.gpa);18906 errdefer msg.destroy(sema.gpa);
...@@ -18913,7 +18910,7 @@ fn zirRetImplicit(...@@ -18913,7 +18910,7 @@ fn zirRetImplicit(
18913 return sema.failWithOwnedErrorMsg(block, msg);18910 return sema.failWithOwnedErrorMsg(block, msg);
18914 } else if (base_tag != .void) {18911 } else if (base_tag != .void) {
18915 const msg = msg: {18912 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", .{
18917 sema.fn_ret_ty.fmt(pt),18914 sema.fn_ret_ty.fmt(pt),
18918 });18915 });
18919 errdefer msg.destroy(sema.gpa);18916 errdefer msg.destroy(sema.gpa);
...@@ -19302,13 +19299,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19302,13 +19299,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1930219299
19303 if (host_size != 0) {19300 if (host_size != 0) {
19304 if (bit_offset >= host_size * 8) {19301 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", .{
19306 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,19303 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,
19307 });19304 });
19308 }19305 }
19309 const elem_bit_size = try elem_ty.bitSizeSema(pt);19306 const elem_bit_size = try elem_ty.bitSizeSema(pt);
19310 if (elem_bit_size > host_size * 8 - bit_offset) {19307 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", .{
19312 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,19309 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
19313 });19310 });
19314 }19311 }
...@@ -19323,7 +19320,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19323,7 +19320,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19323 } else if (inst_data.size == .c) {19320 } else if (inst_data.size == .c) {
19324 if (!try sema.validateExternType(elem_ty, .other)) {19321 if (!try sema.validateExternType(elem_ty, .other)) {
19325 const msg = msg: {19322 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)});
19327 errdefer msg.destroy(sema.gpa);19324 errdefer msg.destroy(sema.gpa);
1932819325
19329 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);19326 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...@@ -19340,7 +19337,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1934019337
19341 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {19338 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {
19342 return sema.failWithOwnedErrorMsg(block, msg: {19339 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)});
19344 errdefer msg.destroy(sema.gpa);19341 errdefer msg.destroy(sema.gpa);
19345 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);19342 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);
19346 break :msg msg;19343 break :msg msg;
...@@ -19509,7 +19506,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19509,7 +19506,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
19509 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;19506 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
19510 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);19507 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);
19511 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {19508 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)});
19513 }19510 }
19514 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });19511 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });
19515 const init = try sema.resolveInst(extra.init);19512 const init = try sema.resolveInst(extra.init);
...@@ -19672,7 +19669,7 @@ fn zirStructInit(...@@ -19672,7 +19669,7 @@ fn zirStructInit(
19672 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});19669 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
19673 errdefer msg.destroy(sema.gpa);19670 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", .{
19676 field_name.fmt(ip),19673 field_name.fmt(ip),
19677 });19674 });
19678 try sema.addDeclaredHereNote(msg, resolved_ty);19675 try sema.addDeclaredHereNote(msg, resolved_ty);
...@@ -19791,7 +19788,7 @@ fn finishStructInit(...@@ -19791,7 +19788,7 @@ fn finishStructInit(
19791 const field_init = struct_type.fieldInit(ip, i);19788 const field_init = struct_type.fieldInit(ip, i);
19792 if (field_init == .none) {19789 if (field_init == .none) {
19793 const field_name = struct_type.field_names.get(ip)[i];19790 const field_name = struct_type.field_names.get(ip)[i];
19794 const template = "missing struct field: {}";19791 const template = "missing struct field: {f}";
19795 const args = .{field_name.fmt(ip)};19792 const args = .{field_name.fmt(ip)};
19796 if (root_msg) |msg| {19793 if (root_msg) |msg| {
19797 try sema.errNote(init_src, msg, template, args);19794 try sema.errNote(init_src, msg, template, args);
...@@ -20406,7 +20403,7 @@ fn fieldType(...@@ -20406,7 +20403,7 @@ fn fieldType(
20406 },20403 },
20407 else => {},20404 else => {},
20408 }20405 }
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}'", .{
20410 cur_ty.fmt(pt),20407 cur_ty.fmt(pt),
20411 });20408 });
20412 }20409 }
...@@ -20453,7 +20450,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20453,7 +20450,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20453 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);20450 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
20454 const ty = try sema.resolveType(block, operand_src, inst_data.operand);20451 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
20455 if (ty.isNoReturn(zcu)) {20452 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)});
20457 }20454 }
20458 const val = try ty.lazyAbiAlignment(sema.pt);20455 const val = try ty.lazyAbiAlignment(sema.pt);
20459 return Air.internedToRef(val.toIntern());20456 return Air.internedToRef(val.toIntern());
...@@ -20531,7 +20528,7 @@ fn zirAbs(...@@ -20531,7 +20528,7 @@ fn zirAbs(
20531 else => return sema.fail(20528 else => return sema.fail(
20532 block,20529 block,
20533 operand_src,20530 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}'",
20535 .{operand_ty.fmt(pt)},20532 .{operand_ty.fmt(pt)},
20536 ),20533 ),
20537 };20534 };
...@@ -20600,7 +20597,7 @@ fn zirUnaryMath(...@@ -20600,7 +20597,7 @@ fn zirUnaryMath(
20600 else => return sema.fail(20597 else => return sema.fail(
20601 block,20598 block,
20602 operand_src,20599 operand_src,
20603 "expected vector of floats or float type, found '{}'",20600 "expected vector of floats or float type, found '{f}'",
20604 .{operand_ty.fmt(pt)},20601 .{operand_ty.fmt(pt)},
20605 ),20602 ),
20606 }20603 }
...@@ -20629,8 +20626,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20629,8 +20626,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20629 },20626 },
20630 .@"enum" => operand_ty,20627 .@"enum" => operand_ty,
20631 .@"union" => operand_ty.unionTagType(zcu) orelse20628 .@"union" => operand_ty.unionTagType(zcu) orelse
20632 return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(pt)}),20629 return sema.fail(block, src, "union '{f}' is untagged", .{operand_ty.fmt(pt)}),
20633 else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{20630 else => return sema.fail(block, operand_src, "expected enum or union; found '{f}'", .{
20634 operand_ty.fmt(pt),20631 operand_ty.fmt(pt),
20635 }),20632 }),
20636 };20633 };
...@@ -20638,7 +20635,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20638,7 +20635,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20638 // TODO I don't think this is the correct way to handle this but20635 // TODO I don't think this is the correct way to handle this but
20639 // it prevents a crash.20636 // it prevents a crash.
20640 // https://github.com/ziglang/zig/issues/1590920637 // 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}'", .{
20642 enum_ty.fmt(pt),20639 enum_ty.fmt(pt),
20643 });20640 });
20644 }20641 }
...@@ -20646,7 +20643,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20646,7 +20643,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20646 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {20643 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
20647 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {20644 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {
20648 const msg = msg: {20645 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}'", .{
20650 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),20647 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),
20651 });20648 });
20652 errdefer msg.destroy(sema.gpa);20649 errdefer msg.destroy(sema.gpa);
...@@ -20833,7 +20830,7 @@ fn zirReify(...@@ -20833,7 +20830,7 @@ fn zirReify(
20833 } else if (ptr_size == .c) {20830 } else if (ptr_size == .c) {
20834 if (!try sema.validateExternType(elem_ty, .other)) {20831 if (!try sema.validateExternType(elem_ty, .other)) {
20835 const msg = msg: {20832 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)});
20837 errdefer msg.destroy(gpa);20834 errdefer msg.destroy(gpa);
2083820835
20839 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);20836 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);
...@@ -20946,7 +20943,7 @@ fn zirReify(...@@ -20946,7 +20943,7 @@ fn zirReify(
20946 _ = try pt.getErrorValue(name);20943 _ = try pt.getErrorValue(name);
20947 const gop = names.getOrPutAssumeCapacity(name);20944 const gop = names.getOrPutAssumeCapacity(name);
20948 if (gop.found_existing) {20945 if (gop.found_existing) {
20949 return sema.fail(block, src, "duplicate error '{}'", .{20946 return sema.fail(block, src, "duplicate error '{f}'", .{
20950 name.fmt(ip),20947 name.fmt(ip),
20951 });20948 });
20952 }20949 }
...@@ -21294,7 +21291,7 @@ fn reifyEnum(...@@ -21294,7 +21291,7 @@ fn reifyEnum(
2129421291
21295 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {21292 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {
21296 // TODO: better source location21293 // 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}'", .{
21298 field_name.fmt(ip),21295 field_name.fmt(ip),
21299 field_value_val.fmtValueSema(pt, sema),21296 field_value_val.fmtValueSema(pt, sema),
21300 tag_ty.fmt(pt),21297 tag_ty.fmt(pt),
...@@ -21305,14 +21302,14 @@ fn reifyEnum(...@@ -21305,14 +21302,14 @@ fn reifyEnum(
21305 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {21302 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {
21306 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {21303 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21307 .name => msg: {21304 .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)});
21309 errdefer msg.destroy(gpa);21306 errdefer msg.destroy(gpa);
21310 _ = conflict.prev_field_idx; // TODO: this note is incorrect21307 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21311 try sema.errNote(src, msg, "other field here", .{});21308 try sema.errNote(src, msg, "other field here", .{});
21312 break :msg msg;21309 break :msg msg;
21313 },21310 },
21314 .value => msg: {21311 .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)});
21316 errdefer msg.destroy(gpa);21313 errdefer msg.destroy(gpa);
21317 _ = conflict.prev_field_idx; // TODO: this note is incorrect21314 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21318 try sema.errNote(src, msg, "other enum tag value here", .{});21315 try sema.errNote(src, msg, "other enum tag value here", .{});
...@@ -21460,13 +21457,13 @@ fn reifyUnion(...@@ -21460,13 +21457,13 @@ fn reifyUnion(
2146021457
21461 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {21458 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {
21462 // TODO: better source location21459 // 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}'", .{
21464 field_name.fmt(ip), enum_tag_ty.fmt(pt),21461 field_name.fmt(ip), enum_tag_ty.fmt(pt),
21465 });21462 });
21466 };21463 };
21467 if (seen_tags.isSet(enum_index)) {21464 if (seen_tags.isSet(enum_index)) {
21468 // TODO: better source location21465 // 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)});
21470 }21467 }
21471 seen_tags.set(enum_index);21468 seen_tags.set(enum_index);
2147221469
...@@ -21487,7 +21484,7 @@ fn reifyUnion(...@@ -21487,7 +21484,7 @@ fn reifyUnion(
21487 var it = seen_tags.iterator(.{ .kind = .unset });21484 var it = seen_tags.iterator(.{ .kind = .unset });
21488 while (it.next()) |enum_index| {21485 while (it.next()) |enum_index| {
21489 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);21486 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", .{
21491 field_name.fmt(ip),21488 field_name.fmt(ip),
21492 });21489 });
21493 }21490 }
...@@ -21512,7 +21509,7 @@ fn reifyUnion(...@@ -21512,7 +21509,7 @@ fn reifyUnion(
21512 const gop = field_names.getOrPutAssumeCapacity(field_name);21509 const gop = field_names.getOrPutAssumeCapacity(field_name);
21513 if (gop.found_existing) {21510 if (gop.found_existing) {
21514 // TODO: better source location21511 // 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)});
21516 }21513 }
2151721514
21518 field_ty.* = field_type_val.toIntern();21515 field_ty.* = field_type_val.toIntern();
...@@ -21544,7 +21541,7 @@ fn reifyUnion(...@@ -21544,7 +21541,7 @@ fn reifyUnion(
21544 }21541 }
21545 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {21542 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
21546 return sema.failWithOwnedErrorMsg(block, msg: {21543 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)});
21548 errdefer msg.destroy(gpa);21545 errdefer msg.destroy(gpa);
2154921546
21550 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);21547 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);
...@@ -21554,7 +21551,7 @@ fn reifyUnion(...@@ -21554,7 +21551,7 @@ fn reifyUnion(
21554 });21551 });
21555 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21552 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21556 return sema.failWithOwnedErrorMsg(block, msg: {21553 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)});
21558 errdefer msg.destroy(gpa);21555 errdefer msg.destroy(gpa);
2155921556
21560 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21557 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
...@@ -21636,7 +21633,7 @@ fn reifyTuple(...@@ -21636,7 +21633,7 @@ fn reifyTuple(
21636 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(21633 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
21637 block,21634 block,
21638 src,21635 src,
21639 "tuple cannot have non-numeric field '{}'",21636 "tuple cannot have non-numeric field '{f}'",
21640 .{field_name.fmt(ip)},21637 .{field_name.fmt(ip)},
21641 );21638 );
21642 if (field_name_index != field_idx) {21639 if (field_name_index != field_idx) {
...@@ -21814,7 +21811,7 @@ fn reifyStruct(...@@ -21814,7 +21811,7 @@ fn reifyStruct(
21814 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);21811 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21815 if (struct_type.addFieldName(ip, field_name)) |prev_index| {21812 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
21816 _ = prev_index; // TODO: better source location21813 _ = 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)});
21818 }21815 }
2181921816
21820 if (any_aligned_fields) {21817 if (any_aligned_fields) {
...@@ -21883,7 +21880,7 @@ fn reifyStruct(...@@ -21883,7 +21880,7 @@ fn reifyStruct(
21883 }21880 }
21884 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {21881 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
21885 return sema.failWithOwnedErrorMsg(block, msg: {21882 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)});
21887 errdefer msg.destroy(gpa);21884 errdefer msg.destroy(gpa);
2188821885
21889 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);21886 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);
...@@ -21893,7 +21890,7 @@ fn reifyStruct(...@@ -21893,7 +21890,7 @@ fn reifyStruct(
21893 });21890 });
21894 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21891 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21895 return sema.failWithOwnedErrorMsg(block, msg: {21892 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)});
21897 errdefer msg.destroy(gpa);21894 errdefer msg.destroy(gpa);
2189821895
21899 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21896 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
...@@ -21970,7 +21967,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -21970,7 +21967,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2197021967
21971 if (!try sema.validateExternType(arg_ty, .param_ty)) {21968 if (!try sema.validateExternType(arg_ty, .param_ty)) {
21972 const msg = msg: {21969 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)});
21974 errdefer msg.destroy(sema.gpa);21971 errdefer msg.destroy(sema.gpa);
2197521972
21976 try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty);21973 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...@@ -22029,7 +22026,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
22029 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);22026 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
22030 const ty = try sema.resolveType(block, ty_src, inst_data.operand);22027 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);
22033 return sema.addNullTerminatedStrLit(type_name);22030 return sema.addNullTerminatedStrLit(type_name);
22034}22031}
2203522032
...@@ -22157,7 +22154,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22157,7 +22154,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2215722154
22158 if (ptr_ty.isSlice(zcu)) {22155 if (ptr_ty.isSlice(zcu)) {
22159 const msg = msg: {22156 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)});
22161 errdefer msg.destroy(sema.gpa);22158 errdefer msg.destroy(sema.gpa);
22162 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});22159 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});
22163 break :msg msg;22160 break :msg msg;
...@@ -22184,7 +22181,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22184,7 +22181,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22184 }22181 }
22185 if (try ptr_ty.comptimeOnlySema(pt)) {22182 if (try ptr_ty.comptimeOnlySema(pt)) {
22186 return sema.failWithOwnedErrorMsg(block, msg: {22183 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)});
22188 errdefer msg.destroy(sema.gpa);22185 errdefer msg.destroy(sema.gpa);
2218922186
22190 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);22187 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);
...@@ -22241,7 +22238,7 @@ fn ptrFromIntVal(...@@ -22241,7 +22238,7 @@ fn ptrFromIntVal(
22241 }22238 }
22242 const addr = try operand_val.toUnsignedIntSema(pt);22239 const addr = try operand_val.toUnsignedIntSema(pt);
22243 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)22240 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)});
22245 if (addr != 0 and ptr_align != .none) {22242 if (addr != 0 and ptr_align != .none) {
22246 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|22243 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|
22247 addr & mask22244 addr & mask
...@@ -22249,7 +22246,7 @@ fn ptrFromIntVal(...@@ -22249,7 +22246,7 @@ fn ptrFromIntVal(
22249 addr;22246 addr;
2225022247
22251 if (!ptr_align.check(masked_addr)) {22248 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)});
22253 }22250 }
22254 }22251 }
2225522252
...@@ -22294,8 +22291,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22294,8 +22291,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22294 errdefer msg.destroy(sema.gpa);22291 errdefer msg.destroy(sema.gpa);
22295 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);22292 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);
22296 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);22293 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);
22297 try sema.errNote(src, msg, "destination payload is '{}'", .{dest_payload_ty.fmt(pt)});22294 try sema.errNote(src, msg, "destination payload is '{f}'", .{dest_payload_ty.fmt(pt)});
22298 try sema.errNote(src, msg, "operand payload is '{}'", .{operand_payload_ty.fmt(pt)});22295 try sema.errNote(src, msg, "operand payload is '{f}'", .{operand_payload_ty.fmt(pt)});
22299 try addDeclaredHereNote(sema, msg, dest_ty);22296 try addDeclaredHereNote(sema, msg, dest_ty);
22300 try addDeclaredHereNote(sema, msg, operand_ty);22297 try addDeclaredHereNote(sema, msg, operand_ty);
22301 break :msg msg;22298 break :msg msg;
...@@ -22340,7 +22337,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22340,7 +22337,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22340 break :disjoint true;22337 break :disjoint true;
22341 };22338 };
22342 if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) {22339 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", .{
22344 operand_err_ty.fmt(pt), dest_err_ty.fmt(pt),22341 operand_err_ty.fmt(pt), dest_err_ty.fmt(pt),
22345 });22342 });
22346 }22343 }
...@@ -22360,7 +22357,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22360,7 +22357,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22360 };22357 };
2236122358
22362 if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) {22359 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}'", .{
22364 err_name.fmt(ip), dest_err_ty.fmt(pt),22361 err_name.fmt(ip), dest_err_ty.fmt(pt),
22365 });22362 });
22366 }22363 }
...@@ -22520,13 +22517,15 @@ fn ptrCastFull(...@@ -22520,13 +22517,15 @@ fn ptrCastFull(
22520 const src_elem_size = src_elem_ty.abiSize(zcu);22517 const src_elem_size = src_elem_ty.abiSize(zcu);
22521 const dest_elem_size = dest_elem_ty.abiSize(zcu);22518 const dest_elem_size = dest_elem_ty.abiSize(zcu);
22522 if (dest_elem_size == 0) {22519 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 });
22524 }22523 }
22525 if (opt_src_len) |src_len| {22524 if (opt_src_len) |src_len| {
22526 const bytes = src_len * src_elem_size;22525 const bytes = src_len * src_elem_size;
22527 const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) {22526 const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) {
22528 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),22527 .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)}),
22530 else => unreachable,22529 else => unreachable,
22531 };22530 };
22532 break :len .{ .constant = dest_len };22531 break :len .{ .constant = dest_len };
...@@ -22544,7 +22543,9 @@ fn ptrCastFull(...@@ -22544,7 +22543,9 @@ fn ptrCastFull(
22544 // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`.22543 // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`.
22545 // The result value will have `dest_len * dest_base_per_elem` values of type `dest_base_ty`.22544 // The result value will have `dest_len * dest_base_per_elem` values of type `dest_base_ty`.
22546 if (dest_base_ty.toIntern() != src_base_ty.toIntern()) {22545 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 });
22548 }22549 }
22549 // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is22550 // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is
22550 // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`.22551 // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`.
...@@ -22552,7 +22553,7 @@ fn ptrCastFull(...@@ -22552,7 +22553,7 @@ fn ptrCastFull(
22552 const base_len = src_len * src_base_per_elem;22553 const base_len = src_len * src_base_per_elem;
22553 const dest_len = std.math.divExact(u64, base_len, dest_base_per_elem) catch switch (src_info.flags.size) {22554 const dest_len = std.math.divExact(u64, base_len, dest_base_per_elem) catch switch (src_info.flags.size) {
22554 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),22555 .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)}),
22556 else => unreachable,22557 else => unreachable,
22557 };22558 };
22558 break :len .{ .constant = dest_len };22559 break :len .{ .constant = dest_len };
...@@ -22613,7 +22614,7 @@ fn ptrCastFull(...@@ -22613,7 +22614,7 @@ fn ptrCastFull(
22613 );22614 );
22614 if (imc_res == .ok) break :check_child;22615 if (imc_res == .ok) break :check_child;
22615 return sema.failWithOwnedErrorMsg(block, msg: {22616 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}'", .{
22617 src_child.fmt(pt), dest_child.fmt(pt),22618 src_child.fmt(pt), dest_child.fmt(pt),
22618 });22619 });
22619 errdefer msg.destroy(sema.gpa);22620 errdefer msg.destroy(sema.gpa);
...@@ -22640,11 +22641,11 @@ fn ptrCastFull(...@@ -22640,11 +22641,11 @@ fn ptrCastFull(
22640 }22641 }
22641 return sema.failWithOwnedErrorMsg(block, msg: {22642 return sema.failWithOwnedErrorMsg(block, msg: {
22642 const msg = if (src_info.sentinel == .none) blk: {22643 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", .{
22644 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),22645 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
22645 });22646 });
22646 } else blk: {22647 } 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}'", .{
22648 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),22649 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),
22649 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),22650 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
22650 });22651 });
...@@ -22686,7 +22687,7 @@ fn ptrCastFull(...@@ -22686,7 +22687,7 @@ fn ptrCastFull(
22686 if (dest_allows_zero) break :check_allowzero;22687 if (dest_allows_zero) break :check_allowzero;
2268722688
22688 return sema.failWithOwnedErrorMsg(block, msg: {22689 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}'", .{
22690 operand_ty.fmt(pt),22691 operand_ty.fmt(pt),
22691 dest_ty.fmt(pt),22692 dest_ty.fmt(pt),
22692 });22693 });
...@@ -22714,10 +22715,10 @@ fn ptrCastFull(...@@ -22714,10 +22715,10 @@ fn ptrCastFull(
22714 return sema.failWithOwnedErrorMsg(block, msg: {22715 return sema.failWithOwnedErrorMsg(block, msg: {
22715 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});22716 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});
22716 errdefer msg.destroy(sema.gpa);22717 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}'", .{
22718 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,22719 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,
22719 });22720 });
22720 try sema.errNote(src, msg, "'{}' has alignment '{d}'", .{22721 try sema.errNote(src, msg, "'{f}' has alignment '{d}'", .{
22721 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,22722 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,
22722 });22723 });
22723 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});22724 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});
...@@ -22731,10 +22732,10 @@ fn ptrCastFull(...@@ -22731,10 +22732,10 @@ fn ptrCastFull(
22731 return sema.failWithOwnedErrorMsg(block, msg: {22732 return sema.failWithOwnedErrorMsg(block, msg: {
22732 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});22733 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});
22733 errdefer msg.destroy(sema.gpa);22734 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}'", .{
22735 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),22736 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),
22736 });22737 });
22737 try sema.errNote(src, msg, "'{}' has address space '{s}'", .{22738 try sema.errNote(src, msg, "'{f}' has address space '{s}'", .{
22738 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),22739 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),
22739 });22740 });
22740 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});22741 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});
...@@ -22801,7 +22802,7 @@ fn ptrCastFull(...@@ -22801,7 +22802,7 @@ fn ptrCastFull(
2280122802
22802 if (operand_val.isNull(zcu)) {22803 if (operand_val.isNull(zcu)) {
22803 if (!dest_ty.ptrAllowsZero(zcu)) {22804 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)});
22805 }22806 }
22806 if (dest_ty.zigTypeTag(zcu) == .optional) {22807 if (dest_ty.zigTypeTag(zcu) == .optional) {
22807 return Air.internedToRef((try pt.nullValue(dest_ty)).toIntern());22808 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...@@ -23092,7 +23093,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23092 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;23093 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;
23093 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;23094 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;
23094 if (operand_is_vector != dest_is_vector) {23095 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) });
23096 }23097 }
2309723098
23098 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {23099 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {
...@@ -23112,7 +23113,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23112,7 +23113,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23112 }23113 }
2311323114
23114 if (operand_info.signedness != dest_info.signedness) {23115 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}'", .{
23116 @tagName(dest_info.signedness), operand_ty.fmt(pt),23117 @tagName(dest_info.signedness), operand_ty.fmt(pt),
23117 });23118 });
23118 }23119 }
...@@ -23121,7 +23122,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23121,7 +23122,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23121 const msg = msg: {23122 const msg = msg: {
23122 const msg = try sema.errMsg(23123 const msg = try sema.errMsg(
23123 src,23124 src,
23124 "destination type '{}' has more bits than source type '{}'",23125 "destination type '{f}' has more bits than source type '{f}'",
23125 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },23126 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },
23126 );23127 );
23127 errdefer msg.destroy(sema.gpa);23128 errdefer msg.destroy(sema.gpa);
...@@ -23239,7 +23240,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23239,7 +23240,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23239 return sema.fail(23240 return sema.fail(
23240 block,23241 block,
23241 operand_src,23242 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",
23243 .{ scalar_ty.fmt(pt), bits },23244 .{ scalar_ty.fmt(pt), bits },
23244 );23245 );
23245 }23246 }
...@@ -23359,7 +23360,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -23359,7 +23360,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
23359 try ty.resolveLayout(pt);23360 try ty.resolveLayout(pt);
23360 switch (ty.zigTypeTag(zcu)) {23361 switch (ty.zigTypeTag(zcu)) {
23361 .@"struct" => {},23362 .@"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)}),
23363 }23364 }
2336423365
23365 const field_index = if (ty.isTuple(zcu)) blk: {23366 const field_index = if (ty.isTuple(zcu)) blk: {
...@@ -23394,7 +23395,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com...@@ -23394,7 +23395,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com
23394 const zcu = pt.zcu;23395 const zcu = pt.zcu;
23395 switch (ty.zigTypeTag(zcu)) {23396 switch (ty.zigTypeTag(zcu)) {
23396 .@"struct", .@"enum", .@"union", .@"opaque" => return,23397 .@"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)}),
23398 }23399 }
23399}23400}
2340023401
...@@ -23405,7 +23406,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr...@@ -23405,7 +23406,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr
23405 switch (ty.zigTypeTag(zcu)) {23406 switch (ty.zigTypeTag(zcu)) {
23406 .comptime_int => return true,23407 .comptime_int => return true,
23407 .int => return false,23408 .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)}),
23409 }23410 }
23410}23411}
2341123412
...@@ -23459,7 +23460,7 @@ fn checkPtrOperand(...@@ -23459,7 +23460,7 @@ fn checkPtrOperand(
23459 const msg = msg: {23460 const msg = msg: {
23460 const msg = try sema.errMsg(23461 const msg = try sema.errMsg(
23461 ty_src,23462 ty_src,
23462 "expected pointer, found '{}'",23463 "expected pointer, found '{f}'",
23463 .{ty.fmt(pt)},23464 .{ty.fmt(pt)},
23464 );23465 );
23465 errdefer msg.destroy(sema.gpa);23466 errdefer msg.destroy(sema.gpa);
...@@ -23473,7 +23474,7 @@ fn checkPtrOperand(...@@ -23473,7 +23474,7 @@ fn checkPtrOperand(
23473 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,23474 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
23474 else => {},23475 else => {},
23475 }23476 }
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)});
23477}23478}
2347823479
23479fn checkPtrType(23480fn checkPtrType(
...@@ -23491,7 +23492,7 @@ fn checkPtrType(...@@ -23491,7 +23492,7 @@ fn checkPtrType(
23491 const msg = msg: {23492 const msg = msg: {
23492 const msg = try sema.errMsg(23493 const msg = try sema.errMsg(
23493 ty_src,23494 ty_src,
23494 "expected pointer type, found '{}'",23495 "expected pointer type, found '{f}'",
23495 .{ty.fmt(pt)},23496 .{ty.fmt(pt)},
23496 );23497 );
23497 errdefer msg.destroy(sema.gpa);23498 errdefer msg.destroy(sema.gpa);
...@@ -23505,7 +23506,7 @@ fn checkPtrType(...@@ -23505,7 +23506,7 @@ fn checkPtrType(
23505 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,23506 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
23506 else => {},23507 else => {},
23507 }23508 }
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)});
23509}23510}
2351023511
23511fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {23512fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
...@@ -23516,7 +23517,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -23516,7 +23517,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
23516 const as = ty.ptrAddressSpace(zcu);23517 const as = ty.ptrAddressSpace(zcu);
23517 if (target_util.arePointersLogical(target, as)) {23518 if (target_util.arePointersLogical(target, as)) {
23518 return sema.failWithOwnedErrorMsg(block, msg: {23519 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)});
23520 errdefer msg.destroy(sema.gpa);23521 errdefer msg.destroy(sema.gpa);
23521 try sema.errNote(23522 try sema.errNote(
23522 src,23523 src,
...@@ -23547,7 +23548,7 @@ fn checkVectorElemType(...@@ -23547,7 +23548,7 @@ fn checkVectorElemType(
23547 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,23548 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,
23548 else => {},23549 else => {},
23549 }23550 }
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)});
23551}23552}
2355223553
23553fn checkFloatType(23554fn checkFloatType(
...@@ -23560,7 +23561,7 @@ fn checkFloatType(...@@ -23560,7 +23561,7 @@ fn checkFloatType(
23560 const zcu = pt.zcu;23561 const zcu = pt.zcu;
23561 switch (ty.zigTypeTag(zcu)) {23562 switch (ty.zigTypeTag(zcu)) {
23562 .comptime_int, .comptime_float, .float => {},23563 .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)}),
23564 }23565 }
23565}23566}
2356623567
...@@ -23578,7 +23579,7 @@ fn checkNumericType(...@@ -23578,7 +23579,7 @@ fn checkNumericType(
23578 .comptime_float, .float, .comptime_int, .int => {},23579 .comptime_float, .float, .comptime_int, .int => {},
23579 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),23580 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),
23580 },23581 },
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)}),
23582 }23583 }
23583}23584}
2358423585
...@@ -23612,7 +23613,7 @@ fn checkAtomicPtrOperand(...@@ -23612,7 +23613,7 @@ fn checkAtomicPtrOperand(
23612 error.BadType => return sema.fail(23613 error.BadType => return sema.fail(
23613 block,23614 block,
23614 elem_ty_src,23615 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}'",
23616 .{elem_ty.fmt(pt)},23617 .{elem_ty.fmt(pt)},
23617 ),23618 ),
23618 };23619 };
...@@ -23673,12 +23674,12 @@ fn checkIntOrVector(...@@ -23673,12 +23674,12 @@ fn checkIntOrVector(
23673 const elem_ty = operand_ty.childType(zcu);23674 const elem_ty = operand_ty.childType(zcu);
23674 switch (elem_ty.zigTypeTag(zcu)) {23675 switch (elem_ty.zigTypeTag(zcu)) {
23675 .int => return elem_ty,23676 .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}'", .{
23677 elem_ty.fmt(pt),23678 elem_ty.fmt(pt),
23678 }),23679 }),
23679 }23680 }
23680 },23681 },
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}'", .{
23682 operand_ty.fmt(pt),23683 operand_ty.fmt(pt),
23683 }),23684 }),
23684 }23685 }
...@@ -23698,12 +23699,12 @@ fn checkIntOrVectorAllowComptime(...@@ -23698,12 +23699,12 @@ fn checkIntOrVectorAllowComptime(
23698 const elem_ty = operand_ty.childType(zcu);23699 const elem_ty = operand_ty.childType(zcu);
23699 switch (elem_ty.zigTypeTag(zcu)) {23700 switch (elem_ty.zigTypeTag(zcu)) {
23700 .int, .comptime_int => return elem_ty,23701 .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}'", .{
23702 elem_ty.fmt(pt),23703 elem_ty.fmt(pt),
23703 }),23704 }),
23704 }23705 }
23705 },23706 },
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}'", .{
23707 operand_ty.fmt(pt),23708 operand_ty.fmt(pt),
23708 }),23709 }),
23709 }23710 }
...@@ -23794,7 +23795,7 @@ fn checkVectorizableBinaryOperands(...@@ -23794,7 +23795,7 @@ fn checkVectorizableBinaryOperands(
23794 }23795 }
23795 } else {23796 } else {
23796 const msg = msg: {23797 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}'", .{
23798 lhs_ty.fmt(pt), rhs_ty.fmt(pt),23799 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
23799 });23800 });
23800 errdefer msg.destroy(sema.gpa);23801 errdefer msg.destroy(sema.gpa);
...@@ -23928,7 +23929,7 @@ fn zirCmpxchg(...@@ -23928,7 +23929,7 @@ fn zirCmpxchg(
23928 return sema.fail(23929 return sema.fail(
23929 block,23930 block,
23930 elem_ty_src,23931 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}'",
23932 .{elem_ty.fmt(pt)},23933 .{elem_ty.fmt(pt)},
23933 );23934 );
23934 }23935 }
...@@ -24012,7 +24013,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -24012,7 +24013,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2401224013
24013 switch (dest_ty.zigTypeTag(zcu)) {24014 switch (dest_ty.zigTypeTag(zcu)) {
24014 .array, .vector => {},24015 .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)}),
24016 }24017 }
2401724018
24018 const operand = try sema.resolveInst(extra.rhs);24019 const operand = try sema.resolveInst(extra.rhs);
...@@ -24088,7 +24089,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24088,7 +24089,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24088 const zcu = pt.zcu;24089 const zcu = pt.zcu;
2408924090
24090 if (operand_ty.zigTypeTag(zcu) != .vector) {24091 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)});
24092 }24093 }
2409324094
24094 const scalar_ty = operand_ty.childType(zcu);24095 const scalar_ty = operand_ty.childType(zcu);
...@@ -24097,13 +24098,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24097,13 +24098,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24097 switch (operation) {24098 switch (operation) {
24098 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {24099 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
24099 .int, .bool => {},24100 .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}'", .{
24101 @tagName(operation), operand_ty.fmt(pt),24102 @tagName(operation), operand_ty.fmt(pt),
24102 }),24103 }),
24103 },24104 },
24104 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {24105 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
24105 .int, .float => {},24106 .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}'", .{
24107 @tagName(operation), operand_ty.fmt(pt),24108 @tagName(operation), operand_ty.fmt(pt),
24108 }),24109 }),
24109 },24110 },
...@@ -24157,7 +24158,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -24157,7 +24158,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2415724158
24158 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {24159 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {
24159 .array, .vector => sema.typeOf(mask).arrayLen(zcu),24160 .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)}),
24161 };24162 };
24162 mask_ty = try pt.vectorType(.{24163 mask_ty = try pt.vectorType(.{
24163 .len = @intCast(mask_len),24164 .len = @intCast(mask_len),
...@@ -24184,11 +24185,14 @@ fn analyzeShuffle(...@@ -24184,11 +24185,14 @@ fn analyzeShuffle(
24184 const b_src = block.builtinCallArgSrc(src_node, 2);24185 const b_src = block.builtinCallArgSrc(src_node, 2);
24185 const mask_src = block.builtinCallArgSrc(src_node, 3);24186 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.
24188 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {24190 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {
24189 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),24191 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),
24190 .undefined => 0,24192 .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 }),
24192 };24196 };
24193 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });24197 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });
24194 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);24198 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);
...@@ -24197,7 +24201,9 @@ fn analyzeShuffle(...@@ -24197,7 +24201,9 @@ fn analyzeShuffle(
24197 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {24201 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {
24198 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),24202 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),
24199 .undefined => 0,24203 .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 }),
24201 };24207 };
24202 const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() });24208 const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() });
24203 const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src);24209 const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src);
...@@ -24235,7 +24241,7 @@ fn analyzeShuffle(...@@ -24235,7 +24241,7 @@ fn analyzeShuffle(
24235 if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: {24241 if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: {
24236 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});24242 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});
24237 errdefer msg.destroy(sema.gpa);24243 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) });
24239 if (idx < b_len) {24245 if (idx < b_len) {
24240 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});24246 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});
24241 }24247 }
...@@ -24351,7 +24357,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -24351,7 +24357,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2435124357
24352 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {24358 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {
24353 .vector, .array => pred_ty.arrayLen(zcu),24359 .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)}),
24355 };24361 };
24356 const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64));24362 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....@@ -24611,7 +24617,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2461124617
24612 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {24618 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
24613 .comptime_float, .float => {},24619 .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)}),
24615 }24621 }
2461624622
24617 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {24623 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
...@@ -24712,7 +24718,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -24712,7 +24718,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2471224718
24713 const args_ty = sema.typeOf(args);24719 const args_ty = sema.typeOf(args);
24714 if (!args_ty.isTuple(zcu)) {24720 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)});
24716 }24722 }
2471724723
24718 const resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(zcu));24724 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...@@ -24757,12 +24763,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24757 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);24763 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);
24758 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);24764 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
24759 if (parent_ptr_info.flags.size != .one) {24765 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)});
24761 }24767 }
24762 const parent_ty: Type = .fromInterned(parent_ptr_info.child);24768 const parent_ty: Type = .fromInterned(parent_ptr_info.child);
24763 switch (parent_ty.zigTypeTag(zcu)) {24769 switch (parent_ty.zigTypeTag(zcu)) {
24764 .@"struct", .@"union" => {},24770 .@"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)}),
24766 }24772 }
24767 try parent_ty.resolveLayout(pt);24773 try parent_ty.resolveLayout(pt);
2476824774
...@@ -24912,7 +24918,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24912,7 +24918,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24912 }24918 }
2491324919
24914 if (field.index != field_index) {24920 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}'", .{
24916 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt),24922 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt),
24917 });24923 });
24918 }24924 }
...@@ -25371,10 +25377,10 @@ fn zirMemcpy(...@@ -25371,10 +25377,10 @@ fn zirMemcpy(
25371 const msg = msg: {25377 const msg = msg: {
25372 const msg = try sema.errMsg(src, "unknown copy length", .{});25378 const msg = try sema.errMsg(src, "unknown copy length", .{});
25373 errdefer msg.destroy(sema.gpa);25379 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", .{
25375 dest_ty.fmt(pt),25381 dest_ty.fmt(pt),
25376 });25382 });
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", .{
25378 src_ty.fmt(pt),25384 src_ty.fmt(pt),
25379 });25385 });
25380 break :msg msg;25386 break :msg msg;
...@@ -25398,7 +25404,7 @@ fn zirMemcpy(...@@ -25398,7 +25404,7 @@ fn zirMemcpy(
25398 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {25404 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {
25399 const msg = try sema.errMsg(25405 const msg = try sema.errMsg(
25400 src,25406 src,
25401 "pointer element type '{}' cannot coerce into element type '{}'",25407 "pointer element type '{f}' cannot coerce into element type '{f}'",
25402 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },25408 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },
25403 );25409 );
25404 errdefer msg.destroy(sema.gpa);25410 errdefer msg.destroy(sema.gpa);
...@@ -25417,10 +25423,10 @@ fn zirMemcpy(...@@ -25417,10 +25423,10 @@ fn zirMemcpy(
25417 const msg = msg: {25423 const msg = msg: {
25418 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});25424 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});
25419 errdefer msg.destroy(sema.gpa);25425 errdefer msg.destroy(sema.gpa);
25420 try sema.errNote(dest_src, msg, "length {} here", .{25426 try sema.errNote(dest_src, msg, "length {f} here", .{
25421 dest_len_val.fmtValueSema(pt, sema),25427 dest_len_val.fmtValueSema(pt, sema),
25422 });25428 });
25423 try sema.errNote(src_src, msg, "length {} here", .{25429 try sema.errNote(src_src, msg, "length {f} here", .{
25424 src_len_val.fmtValueSema(pt, sema),25430 src_len_val.fmtValueSema(pt, sema),
25425 });25431 });
25426 break :msg msg;25432 break :msg msg;
...@@ -25635,7 +25641,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25635,7 +25641,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25635 return sema.failWithOwnedErrorMsg(block, msg: {25641 return sema.failWithOwnedErrorMsg(block, msg: {
25636 const msg = try sema.errMsg(src, "unknown @memset length", .{});25642 const msg = try sema.errMsg(src, "unknown @memset length", .{});
25637 errdefer msg.destroy(sema.gpa);25643 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", .{
25639 dest_ptr_ty.fmt(pt),25645 dest_ptr_ty.fmt(pt),
25640 });25646 });
25641 break :msg msg;25647 break :msg msg;
...@@ -25815,7 +25821,7 @@ fn zirCUndef(...@@ -25815,7 +25821,7 @@ fn zirCUndef(
25815 const src = block.builtinCallArgSrc(extra.node, 0);25821 const src = block.builtinCallArgSrc(extra.node, 0);
2581625822
25817 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cUndef_macro_name });25823 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});
25819 return .void_value;25825 return .void_value;
25820}25826}
2582125827
...@@ -25828,7 +25834,7 @@ fn zirCInclude(...@@ -25828,7 +25834,7 @@ fn zirCInclude(
25828 const src = block.builtinCallArgSrc(extra.node, 0);25834 const src = block.builtinCallArgSrc(extra.node, 0);
2582925835
25830 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cInclude_file_name });25836 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});
25832 return .void_value;25838 return .void_value;
25833}25839}
2583425840
...@@ -25847,9 +25853,9 @@ fn zirCDefine(...@@ -25847,9 +25853,9 @@ fn zirCDefine(
25847 const rhs = try sema.resolveInst(extra.rhs);25853 const rhs = try sema.resolveInst(extra.rhs);
25848 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {25854 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {
25849 const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value });25855 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 });
25851 } else {25857 } else {
25852 try block.c_import_buf.?.writer().print("#define {s}\n", .{name});25858 try block.c_import_buf.?.print("#define {s}\n", .{name});
25853 }25859 }
25854 return .void_value;25860 return .void_value;
25855}25861}
...@@ -26067,7 +26073,7 @@ fn zirBuiltinExtern(...@@ -26067,7 +26073,7 @@ fn zirBuiltinExtern(
26067 }26073 }
26068 if (!try sema.validateExternType(ty, .other)) {26074 if (!try sema.validateExternType(ty, .other)) {
26069 const msg = msg: {26075 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)});
26071 errdefer msg.destroy(sema.gpa);26077 errdefer msg.destroy(sema.gpa);
26072 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);26078 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);
26073 break :msg msg;26079 break :msg msg;
...@@ -26307,7 +26313,7 @@ pub fn validateVarType(...@@ -26307,7 +26313,7 @@ pub fn validateVarType(
26307 if (is_extern) {26313 if (is_extern) {
26308 if (!try sema.validateExternType(var_ty, .other)) {26314 if (!try sema.validateExternType(var_ty, .other)) {
26309 const msg = msg: {26315 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)});
26311 errdefer msg.destroy(sema.gpa);26317 errdefer msg.destroy(sema.gpa);
26312 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);26318 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);
26313 break :msg msg;26319 break :msg msg;
...@@ -26319,7 +26325,7 @@ pub fn validateVarType(...@@ -26319,7 +26325,7 @@ pub fn validateVarType(
26319 return sema.fail(26325 return sema.fail(
26320 block,26326 block,
26321 src,26327 src,
26322 "non-extern variable with opaque type '{}'",26328 "non-extern variable with opaque type '{f}'",
26323 .{var_ty.fmt(pt)},26329 .{var_ty.fmt(pt)},
26324 );26330 );
26325 }26331 }
...@@ -26328,7 +26334,7 @@ pub fn validateVarType(...@@ -26328,7 +26334,7 @@ pub fn validateVarType(
26328 if (!try var_ty.comptimeOnlySema(pt)) return;26334 if (!try var_ty.comptimeOnlySema(pt)) return;
2632926335
26330 const msg = msg: {26336 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)});
26332 errdefer msg.destroy(sema.gpa);26338 errdefer msg.destroy(sema.gpa);
2633326339
26334 try sema.explainWhyTypeIsComptime(msg, src, var_ty);26340 try sema.explainWhyTypeIsComptime(msg, src, var_ty);
...@@ -26378,7 +26384,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -26378,7 +26384,7 @@ fn explainWhyTypeIsComptimeInner(
26378 => return,26384 => return,
2637926385
26380 .@"fn" => {26386 .@"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)});
26382 },26388 },
2638326389
26384 .type => {26390 .type => {
...@@ -26394,7 +26400,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -26394,7 +26400,7 @@ fn explainWhyTypeIsComptimeInner(
26394 => return,26400 => return,
2639526401
26396 .@"opaque" => {26402 .@"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)});
26398 },26404 },
2639926405
26400 .array, .vector => {26406 .array, .vector => {
...@@ -26581,7 +26587,7 @@ fn explainWhyTypeIsNotExtern(...@@ -26581,7 +26587,7 @@ fn explainWhyTypeIsNotExtern(
26581 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {26587 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {
26582 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});26588 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});
26583 } else if (try ty.comptimeOnlySema(pt)) {26589 } 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)});
26585 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);26591 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);
26586 }26592 }
26587 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);26593 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);
...@@ -26609,7 +26615,7 @@ fn explainWhyTypeIsNotExtern(...@@ -26609,7 +26615,7 @@ fn explainWhyTypeIsNotExtern(
26609 },26615 },
26610 .@"enum" => {26616 .@"enum" => {
26611 const tag_ty = ty.intTagType(zcu);26617 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)});
26613 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);26619 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
26614 },26620 },
26615 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),26621 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
...@@ -27045,7 +27051,7 @@ fn fieldVal(...@@ -27045,7 +27051,7 @@ fn fieldVal(
27045 return sema.fail(27051 return sema.fail(
27046 block,27052 block,
27047 field_name_src,27053 field_name_src,
27048 "no member named '{}' in '{}'",27054 "no member named '{f}' in '{f}'",
27049 .{ field_name.fmt(ip), object_ty.fmt(pt) },27055 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27050 );27056 );
27051 }27057 }
...@@ -27069,7 +27075,7 @@ fn fieldVal(...@@ -27069,7 +27075,7 @@ fn fieldVal(
27069 return sema.fail(27075 return sema.fail(
27070 block,27076 block,
27071 field_name_src,27077 field_name_src,
27072 "no member named '{}' in '{}'",27078 "no member named '{f}' in '{f}'",
27073 .{ field_name.fmt(ip), object_ty.fmt(pt) },27079 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27074 );27080 );
27075 }27081 }
...@@ -27089,7 +27095,7 @@ fn fieldVal(...@@ -27089,7 +27095,7 @@ fn fieldVal(
27089 switch (ip.indexToKey(child_type.toIntern())) {27095 switch (ip.indexToKey(child_type.toIntern())) {
27090 .error_set_type => |error_set_type| blk: {27096 .error_set_type => |error_set_type| blk: {
27091 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;27097 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}'", .{
27093 field_name.fmt(ip), child_type.fmt(pt),27099 field_name.fmt(ip), child_type.fmt(pt),
27094 });27100 });
27095 },27101 },
...@@ -27144,7 +27150,7 @@ fn fieldVal(...@@ -27144,7 +27150,7 @@ fn fieldVal(
27144 return sema.failWithBadMemberAccess(block, child_type, src, field_name);27150 return sema.failWithBadMemberAccess(block, child_type, src, field_name);
27145 },27151 },
27146 else => return sema.failWithOwnedErrorMsg(block, msg: {27152 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)});
27148 errdefer msg.destroy(sema.gpa);27154 errdefer msg.destroy(sema.gpa);
27149 if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{});27155 if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{});
27150 if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{});27156 if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{});
...@@ -27190,7 +27196,7 @@ fn fieldPtr(...@@ -27190,7 +27196,7 @@ fn fieldPtr(
27190 const object_ptr_ty = sema.typeOf(object_ptr);27196 const object_ptr_ty = sema.typeOf(object_ptr);
27191 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {27197 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {
27192 .pointer => object_ptr_ty.childType(zcu),27198 .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)}),
27194 };27200 };
2719527201
27196 // Zig allows dereferencing a single pointer during field lookup. Note that27202 // Zig allows dereferencing a single pointer during field lookup. Note that
...@@ -27243,7 +27249,7 @@ fn fieldPtr(...@@ -27243,7 +27249,7 @@ fn fieldPtr(
27243 return sema.fail(27249 return sema.fail(
27244 block,27250 block,
27245 field_name_src,27251 field_name_src,
27246 "no member named '{}' in '{}'",27252 "no member named '{f}' in '{f}'",
27247 .{ field_name.fmt(ip), object_ty.fmt(pt) },27253 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27248 );27254 );
27249 }27255 }
...@@ -27298,7 +27304,7 @@ fn fieldPtr(...@@ -27298,7 +27304,7 @@ fn fieldPtr(
27298 return sema.fail(27304 return sema.fail(
27299 block,27305 block,
27300 field_name_src,27306 field_name_src,
27301 "no member named '{}' in '{}'",27307 "no member named '{f}' in '{f}'",
27302 .{ field_name.fmt(ip), object_ty.fmt(pt) },27308 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27303 );27309 );
27304 }27310 }
...@@ -27321,7 +27327,7 @@ fn fieldPtr(...@@ -27321,7 +27327,7 @@ fn fieldPtr(
27321 if (error_set_type.nameIndex(ip, field_name) != null) {27327 if (error_set_type.nameIndex(ip, field_name) != null) {
27322 break :blk;27328 break :blk;
27323 }27329 }
27324 return sema.fail(block, src, "no error named '{}' in '{}'", .{27330 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
27325 field_name.fmt(ip), child_type.fmt(pt),27331 field_name.fmt(ip), child_type.fmt(pt),
27326 });27332 });
27327 },27333 },
...@@ -27375,7 +27381,7 @@ fn fieldPtr(...@@ -27375,7 +27381,7 @@ fn fieldPtr(
27375 }27381 }
27376 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);27382 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
27377 },27383 },
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)}),
27379 }27385 }
27380 },27386 },
27381 .@"struct" => {27387 .@"struct" => {
...@@ -27430,7 +27436,7 @@ fn fieldCallBind(...@@ -27430,7 +27436,7 @@ fn fieldCallBind(
27430 const inner_ty = if (raw_ptr_ty.zigTypeTag(zcu) == .pointer and (raw_ptr_ty.ptrSize(zcu) == .one or raw_ptr_ty.ptrSize(zcu) == .c))27436 const inner_ty = if (raw_ptr_ty.zigTypeTag(zcu) == .pointer and (raw_ptr_ty.ptrSize(zcu) == .one or raw_ptr_ty.ptrSize(zcu) == .c))
27431 raw_ptr_ty.childType(zcu)27437 raw_ptr_ty.childType(zcu)
27432 else27438 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
27435 // Optionally dereference a second pointer to get the concrete type.27441 // Optionally dereference a second pointer to get the concrete type.
27436 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;27442 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;
...@@ -27549,7 +27555,7 @@ fn fieldCallBind(...@@ -27549,7 +27555,7 @@ fn fieldCallBind(
27549 };27555 };
2755027556
27551 const msg = msg: {27557 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}'", .{
27553 field_name.fmt(ip),27559 field_name.fmt(ip),
27554 concrete_ty.fmt(pt),27560 concrete_ty.fmt(pt),
27555 });27561 });
...@@ -27559,7 +27565,7 @@ fn fieldCallBind(...@@ -27559,7 +27565,7 @@ fn fieldCallBind(
27559 try sema.errNote(27565 try sema.errNote(
27560 zcu.navSrcLoc(nav_index),27566 zcu.navSrcLoc(nav_index),
27561 msg,27567 msg,
27562 "'{}' is not a member function",27568 "'{f}' is not a member function",
27563 .{field_name.fmt(ip)},27569 .{field_name.fmt(ip)},
27564 );27570 );
27565 }27571 }
...@@ -27627,7 +27633,7 @@ fn namespaceLookup(...@@ -27627,7 +27633,7 @@ fn namespaceLookup(
27627 if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {27633 if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {
27628 if (!lookup.accessible) {27634 if (!lookup.accessible) {
27629 return sema.failWithOwnedErrorMsg(block, msg: {27635 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'", .{
27631 decl_name.fmt(&zcu.intern_pool),27637 decl_name.fmt(&zcu.intern_pool),
27632 });27638 });
27633 errdefer msg.destroy(gpa);27639 errdefer msg.destroy(gpa);
...@@ -27865,12 +27871,12 @@ fn tupleFieldIndex(...@@ -27865,12 +27871,12 @@ fn tupleFieldIndex(
27865 assert(!field_name.eqlSlice("len", ip));27871 assert(!field_name.eqlSlice("len", ip));
27866 if (field_name.toUnsigned(ip)) |field_index| {27872 if (field_name.toUnsigned(ip)) |field_index| {
27867 if (field_index < tuple_ty.structFieldCount(pt.zcu)) return field_index;27873 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}'", .{
27869 field_name.fmt(ip), tuple_ty.fmt(pt),27875 field_name.fmt(ip), tuple_ty.fmt(pt),
27870 });27876 });
27871 }27877 }
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}'", .{
27874 field_name.fmt(ip), tuple_ty.fmt(pt),27880 field_name.fmt(ip), tuple_ty.fmt(pt),
27875 });27881 });
27876}27882}
...@@ -27957,7 +27963,7 @@ fn unionFieldPtr(...@@ -27957,7 +27963,7 @@ fn unionFieldPtr(
27957 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});27963 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
27958 errdefer msg.destroy(sema.gpa);27964 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", .{
27961 field_name.fmt(ip),27967 field_name.fmt(ip),
27962 });27968 });
27963 try sema.addDeclaredHereNote(msg, union_ty);27969 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -27991,7 +27997,7 @@ fn unionFieldPtr(...@@ -27991,7 +27997,7 @@ fn unionFieldPtr(
27991 const msg = msg: {27997 const msg = msg: {
27992 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;27998 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
27993 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);27999 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", .{
27995 field_name.fmt(ip),28001 field_name.fmt(ip),
27996 active_field_name.fmt(ip),28002 active_field_name.fmt(ip),
27997 });28003 });
...@@ -28059,7 +28065,7 @@ fn unionFieldVal(...@@ -28059,7 +28065,7 @@ fn unionFieldVal(
28059 const msg = msg: {28065 const msg = msg: {
28060 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;28066 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
28061 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);28067 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", .{
28063 field_name.fmt(ip), active_field_name.fmt(ip),28069 field_name.fmt(ip), active_field_name.fmt(ip),
28064 });28070 });
28065 errdefer msg.destroy(sema.gpa);28071 errdefer msg.destroy(sema.gpa);
...@@ -28117,7 +28123,7 @@ fn elemPtr(...@@ -28117,7 +28123,7 @@ fn elemPtr(
2811728123
28118 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {28124 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {
28119 .pointer => indexable_ptr_ty.childType(zcu),28125 .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)}),
28121 };28127 };
28122 try sema.checkIndexable(block, src, indexable_ty);28128 try sema.checkIndexable(block, src, indexable_ty);
2812328129
...@@ -28288,7 +28294,7 @@ fn validateRuntimeElemAccess(...@@ -28288,7 +28294,7 @@ fn validateRuntimeElemAccess(
28288 const msg = msg: {28294 const msg = msg: {
28289 const msg = try sema.errMsg(28295 const msg = try sema.errMsg(
28290 elem_index_src,28296 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",
28292 .{parent_ty.fmt(sema.pt)},28298 .{parent_ty.fmt(sema.pt)},
28293 );28299 );
28294 errdefer msg.destroy(sema.gpa);28300 errdefer msg.destroy(sema.gpa);
...@@ -28304,7 +28310,7 @@ fn validateRuntimeElemAccess(...@@ -28304,7 +28310,7 @@ fn validateRuntimeElemAccess(
28304 const target = zcu.getTarget();28310 const target = zcu.getTarget();
28305 const as = parent_ty.ptrAddressSpace(zcu);28311 const as = parent_ty.ptrAddressSpace(zcu);
28306 if (target_util.arePointersLogical(target, as)) {28312 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)});
28308 }28314 }
28309 }28315 }
28310}28316}
...@@ -29000,7 +29006,7 @@ fn coerceExtra(...@@ -29000,7 +29006,7 @@ fn coerceExtra(
29000 return sema.fail(29006 return sema.fail(
29001 block,29007 block,
29002 inst_src,29008 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}'",
29004 .{dest_ty.fmt(pt)},29010 .{dest_ty.fmt(pt)},
29005 );29011 );
29006 }29012 }
...@@ -29027,7 +29033,7 @@ fn coerceExtra(...@@ -29027,7 +29033,7 @@ fn coerceExtra(
29027 // pointer to tuple to slice29033 // pointer to tuple to slice
29028 if (!dest_info.flags.is_const) {29034 if (!dest_info.flags.is_const) {
29029 const err_msg = err_msg: {29035 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)});
29031 errdefer err_msg.destroy(sema.gpa);29037 errdefer err_msg.destroy(sema.gpa);
29032 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});29038 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
29033 break :err_msg err_msg;29039 break :err_msg err_msg;
...@@ -29082,7 +29088,7 @@ fn coerceExtra(...@@ -29082,7 +29088,7 @@ fn coerceExtra(
29082 // comptime-known integer to other number29088 // comptime-known integer to other number
29083 if (!(try sema.intFitsInType(val, dest_ty, null))) {29089 if (!(try sema.intFitsInType(val, dest_ty, null))) {
29084 if (!opts.report_err) return error.NotCoercible;29090 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) });
29086 }29092 }
29087 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {29093 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
29088 .undef => try pt.undefRef(dest_ty),29094 .undef => try pt.undefRef(dest_ty),
...@@ -29124,7 +29130,7 @@ fn coerceExtra(...@@ -29124,7 +29130,7 @@ fn coerceExtra(
29124 return sema.fail(29130 return sema.fail(
29125 block,29131 block,
29126 inst_src,29132 inst_src,
29127 "type '{}' cannot represent float value '{}'",29133 "type '{f}' cannot represent float value '{f}'",
29128 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },29134 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },
29129 );29135 );
29130 }29136 }
...@@ -29157,7 +29163,7 @@ fn coerceExtra(...@@ -29157,7 +29163,7 @@ fn coerceExtra(
29157 // return sema.fail(29163 // return sema.fail(
29158 // block,29164 // block,
29159 // inst_src,29165 // inst_src,
29160 // "type '{}' cannot represent integer value '{}'",29166 // "type '{f}' cannot represent integer value '{}'",
29161 // .{ dest_ty.fmt(pt), val },29167 // .{ dest_ty.fmt(pt), val },
29162 // );29168 // );
29163 //}29169 //}
...@@ -29171,7 +29177,7 @@ fn coerceExtra(...@@ -29171,7 +29177,7 @@ fn coerceExtra(
29171 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);29177 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
29172 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;29178 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
29173 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {29179 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}'", .{
29175 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),29181 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
29176 });29182 });
29177 };29183 };
...@@ -29320,11 +29326,11 @@ fn coerceExtra(...@@ -29320,11 +29326,11 @@ fn coerceExtra(
29320 }29326 }
2932129327
29322 const msg = msg: {29328 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) });
29324 errdefer msg.destroy(sema.gpa);29330 errdefer msg.destroy(sema.gpa);
2932529331
29326 if (!can_coerce_to) {29332 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)});
29328 }29334 }
2932929335
29330 // E!T to T29336 // E!T to T
...@@ -29513,13 +29519,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29513,13 +29519,13 @@ const InMemoryCoercionResult = union(enum) {
29513 break;29519 break;
29514 },29520 },
29515 .comptime_int_not_coercible => |int| {29521 .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}'", .{
29517 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),29523 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),
29518 });29524 });
29519 break;29525 break;
29520 },29526 },
29521 .error_union_payload => |pair| {29527 .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}'", .{
29523 pair.actual.fmt(pt), pair.wanted.fmt(pt),29529 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29524 });29530 });
29525 cur = pair.child;29531 cur = pair.child;
...@@ -29532,18 +29538,18 @@ const InMemoryCoercionResult = union(enum) {...@@ -29532,18 +29538,18 @@ const InMemoryCoercionResult = union(enum) {
29532 },29538 },
29533 .array_sentinel => |sentinel| {29539 .array_sentinel => |sentinel| {
29534 if (sentinel.actual.toIntern() != .unreachable_value) {29540 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}'", .{
29536 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),29542 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29537 });29543 });
29538 } else {29544 } else {
29539 try sema.errNote(src, msg, "destination array requires '{}' sentinel", .{29545 try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
29540 sentinel.wanted.fmtValueSema(pt, sema),29546 sentinel.wanted.fmtValueSema(pt, sema),
29541 });29547 });
29542 }29548 }
29543 break;29549 break;
29544 },29550 },
29545 .array_elem => |pair| {29551 .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}'", .{
29547 pair.actual.fmt(pt), pair.wanted.fmt(pt),29553 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29548 });29554 });
29549 cur = pair.child;29555 cur = pair.child;
...@@ -29555,19 +29561,19 @@ const InMemoryCoercionResult = union(enum) {...@@ -29555,19 +29561,19 @@ const InMemoryCoercionResult = union(enum) {
29555 break;29561 break;
29556 },29562 },
29557 .vector_elem => |pair| {29563 .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}'", .{
29559 pair.actual.fmt(pt), pair.wanted.fmt(pt),29565 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29560 });29566 });
29561 cur = pair.child;29567 cur = pair.child;
29562 },29568 },
29563 .optional_shape => |pair| {29569 .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}'", .{
29565 pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt),29571 pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt),
29566 });29572 });
29567 break;29573 break;
29568 },29574 },
29569 .optional_child => |pair| {29575 .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}'", .{
29571 pair.actual.fmt(pt), pair.wanted.fmt(pt),29577 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29572 });29578 });
29573 cur = pair.child;29579 cur = pair.child;
...@@ -29578,7 +29584,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29578,7 +29584,7 @@ const InMemoryCoercionResult = union(enum) {
29578 },29584 },
29579 .missing_error => |missing_errors| {29585 .missing_error => |missing_errors| {
29580 for (missing_errors) |err| {29586 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)});
29582 }29588 }
29583 break;29589 break;
29584 },29590 },
...@@ -29631,7 +29637,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29631,7 +29637,7 @@ const InMemoryCoercionResult = union(enum) {
29631 break;29637 break;
29632 },29638 },
29633 .fn_param => |param| {29639 .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}'", .{
29635 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),29641 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),
29636 });29642 });
29637 cur = param.child;29643 cur = param.child;
...@@ -29641,13 +29647,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29641,13 +29647,13 @@ const InMemoryCoercionResult = union(enum) {
29641 break;29647 break;
29642 },29648 },
29643 .fn_return_type => |pair| {29649 .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}'", .{
29645 pair.actual.fmt(pt), pair.wanted.fmt(pt),29651 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29646 });29652 });
29647 cur = pair.child;29653 cur = pair.child;
29648 },29654 },
29649 .ptr_child => |pair| {29655 .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}'", .{
29651 pair.actual.fmt(pt), pair.wanted.fmt(pt),29657 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29652 });29658 });
29653 cur = pair.child;29659 cur = pair.child;
...@@ -29658,11 +29664,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29658,11 +29664,11 @@ const InMemoryCoercionResult = union(enum) {
29658 },29664 },
29659 .ptr_sentinel => |sentinel| {29665 .ptr_sentinel => |sentinel| {
29660 if (sentinel.actual.toIntern() != .unreachable_value) {29666 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}'", .{
29662 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),29668 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29663 });29669 });
29664 } else {29670 } else {
29665 try sema.errNote(src, msg, "destination pointer requires '{}' sentinel", .{29671 try sema.errNote(src, msg, "destination pointer requires '{f}' sentinel", .{
29666 sentinel.wanted.fmtValueSema(pt, sema),29672 sentinel.wanted.fmtValueSema(pt, sema),
29667 });29673 });
29668 }29674 }
...@@ -29676,11 +29682,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29676,11 +29682,11 @@ const InMemoryCoercionResult = union(enum) {
29676 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);29682 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);
29677 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);29683 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);
29678 if (actual_allow_zero and !wanted_allow_zero) {29684 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}'", .{
29680 pair.actual.fmt(pt), pair.wanted.fmt(pt),29686 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29681 });29687 });
29682 } else {29688 } 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}'", .{
29684 pair.wanted.fmt(pt), pair.actual.fmt(pt),29690 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29685 });29691 });
29686 }29692 }
...@@ -29692,7 +29698,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29692,7 +29698,7 @@ const InMemoryCoercionResult = union(enum) {
29692 if (actual_const and !wanted_const) {29698 if (actual_const and !wanted_const) {
29693 try sema.errNote(src, msg, "cast discards const qualifier", .{});29699 try sema.errNote(src, msg, "cast discards const qualifier", .{});
29694 } else {29700 } 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}'", .{
29696 pair.wanted.fmt(pt), pair.actual.fmt(pt),29702 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29697 });29703 });
29698 }29704 }
...@@ -29704,7 +29710,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29704,7 +29710,7 @@ const InMemoryCoercionResult = union(enum) {
29704 if (actual_volatile and !wanted_volatile) {29710 if (actual_volatile and !wanted_volatile) {
29705 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});29711 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});
29706 } else {29712 } 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}'", .{
29708 pair.wanted.fmt(pt), pair.actual.fmt(pt),29714 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29709 });29715 });
29710 }29716 }
...@@ -29730,13 +29736,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29730,13 +29736,13 @@ const InMemoryCoercionResult = union(enum) {
29730 break;29736 break;
29731 },29737 },
29732 .double_ptr_to_anyopaque => |pair| {29738 .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}'", .{
29734 pair.actual.fmt(pt), pair.wanted.fmt(pt),29740 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29735 });29741 });
29736 break;29742 break;
29737 },29743 },
29738 .slice_to_anyopaque => |pair| {29744 .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}'", .{
29740 pair.actual.fmt(pt), pair.wanted.fmt(pt),29746 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29741 });29747 });
29742 try sema.errNote(src, msg, "consider using '.ptr'", .{});29748 try sema.errNote(src, msg, "consider using '.ptr'", .{});
...@@ -30510,7 +30516,7 @@ fn coerceVarArgParam(...@@ -30510,7 +30516,7 @@ fn coerceVarArgParam(
30510 const coerced_ty = sema.typeOf(coerced);30516 const coerced_ty = sema.typeOf(coerced);
30511 if (!try sema.validateExternType(coerced_ty, .param_ty)) {30517 if (!try sema.validateExternType(coerced_ty, .param_ty)) {
30512 const msg = msg: {30518 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)});
30514 errdefer msg.destroy(sema.gpa);30520 errdefer msg.destroy(sema.gpa);
3051530521
30516 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);30522 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);
...@@ -30613,7 +30619,7 @@ fn storePtr2(...@@ -30613,7 +30619,7 @@ fn storePtr2(
30613 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.30619 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.
30614 if (try elem_ty.comptimeOnlySema(pt)) {30620 if (try elem_ty.comptimeOnlySema(pt)) {
30615 return sema.failWithOwnedErrorMsg(block, msg: {30621 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)});
30617 errdefer msg.destroy(sema.gpa);30623 errdefer msg.destroy(sema.gpa);
30618 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});30624 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});
30619 break :msg msg;30625 break :msg msg;
...@@ -30646,7 +30652,7 @@ fn storePtr2(...@@ -30646,7 +30652,7 @@ fn storePtr2(
30646 });30652 });
30647 return;30653 return;
30648 }30654 }
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}'", .{
30650 ptr_ty.fmt(pt),30656 ptr_ty.fmt(pt),
30651 });30657 });
30652 }30658 }
...@@ -30815,19 +30821,19 @@ fn storePtrVal(...@@ -30815,19 +30821,19 @@ fn storePtrVal(
30815 .{},30821 .{},
30816 ),30822 ),
30817 .undef => return sema.failWithUseOfUndef(block, src),30823 .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)}),
30819 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),30825 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),
30820 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),30826 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
30821 .needed_well_defined => |ty| return sema.fail(30827 .needed_well_defined => |ty| return sema.fail(
30822 block,30828 block,
30823 src,30829 src,
30824 "comptime dereference requires '{}' to have a well-defined layout",30830 "comptime dereference requires '{f}' to have a well-defined layout",
30825 .{ty.fmt(pt)},30831 .{ty.fmt(pt)},
30826 ),30832 ),
30827 .out_of_bounds => |ty| return sema.fail(30833 .out_of_bounds => |ty| return sema.fail(
30828 block,30834 block,
30829 src,30835 src,
30830 "dereference of '{}' exceeds bounds of containing decl of type '{}'",30836 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
30831 .{ ptr_ty.fmt(pt), ty.fmt(pt) },30837 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
30832 ),30838 ),
30833 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),30839 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),
...@@ -30853,7 +30859,7 @@ fn bitCast(...@@ -30853,7 +30859,7 @@ fn bitCast(
30853 const old_bits = old_ty.bitSize(zcu);30859 const old_bits = old_ty.bitSize(zcu);
3085430860
30855 if (old_bits != dest_bits) {30861 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", .{
30857 dest_ty.fmt(pt),30863 dest_ty.fmt(pt),
30858 dest_bits,30864 dest_bits,
30859 old_ty.fmt(pt),30865 old_ty.fmt(pt),
...@@ -30971,7 +30977,7 @@ fn coerceCompatiblePtrs(...@@ -30971,7 +30977,7 @@ fn coerceCompatiblePtrs(
30971 const inst_ty = sema.typeOf(inst);30977 const inst_ty = sema.typeOf(inst);
30972 if (try sema.resolveValue(inst)) |val| {30978 if (try sema.resolveValue(inst)) |val| {
30973 if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) {30979 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)});
30975 }30981 }
30976 // The comptime Value representation is compatible with both types.30982 // The comptime Value representation is compatible with both types.
30977 return Air.internedToRef(30983 return Air.internedToRef(
...@@ -31017,7 +31023,7 @@ fn coerceEnumToUnion(...@@ -31017,7 +31023,7 @@ fn coerceEnumToUnion(
3101731023
31018 const tag_ty = union_ty.unionTagType(zcu) orelse {31024 const tag_ty = union_ty.unionTagType(zcu) orelse {
31019 const msg = msg: {31025 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}'", .{
31021 union_ty.fmt(pt), inst_ty.fmt(pt),31027 union_ty.fmt(pt), inst_ty.fmt(pt),
31022 });31028 });
31023 errdefer msg.destroy(sema.gpa);31029 errdefer msg.destroy(sema.gpa);
...@@ -31031,7 +31037,7 @@ fn coerceEnumToUnion(...@@ -31031,7 +31037,7 @@ fn coerceEnumToUnion(
31031 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);31037 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);
31032 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {31038 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {
31033 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {31039 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}'", .{
31035 union_ty.fmt(pt), val.fmtValueSema(pt, sema),31041 union_ty.fmt(pt), val.fmtValueSema(pt, sema),
31036 });31042 });
31037 };31043 };
...@@ -31045,7 +31051,7 @@ fn coerceEnumToUnion(...@@ -31045,7 +31051,7 @@ fn coerceEnumToUnion(
31045 errdefer msg.destroy(sema.gpa);31051 errdefer msg.destroy(sema.gpa);
3104631052
31047 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31053 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", .{
31049 field_name.fmt(ip),31055 field_name.fmt(ip),
31050 });31056 });
31051 try sema.addDeclaredHereNote(msg, union_ty);31057 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -31056,13 +31062,13 @@ fn coerceEnumToUnion(...@@ -31056,13 +31062,13 @@ fn coerceEnumToUnion(
31056 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {31062 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
31057 const msg = msg: {31063 const msg = msg: {
31058 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31064 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}'", .{
31060 inst_ty.fmt(pt), union_ty.fmt(pt),31066 inst_ty.fmt(pt), union_ty.fmt(pt),
31061 field_ty.fmt(pt), field_name.fmt(ip),31067 field_ty.fmt(pt), field_name.fmt(ip),
31062 });31068 });
31063 errdefer msg.destroy(sema.gpa);31069 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", .{
31066 field_name.fmt(ip),31072 field_name.fmt(ip),
31067 });31073 });
31068 try sema.addDeclaredHereNote(msg, union_ty);31074 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -31078,7 +31084,7 @@ fn coerceEnumToUnion(...@@ -31078,7 +31084,7 @@ fn coerceEnumToUnion(
3107831084
31079 if (tag_ty.isNonexhaustiveEnum(zcu)) {31085 if (tag_ty.isNonexhaustiveEnum(zcu)) {
31080 const msg = msg: {31086 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", .{
31082 union_ty.fmt(pt),31088 union_ty.fmt(pt),
31083 });31089 });
31084 errdefer msg.destroy(sema.gpa);31090 errdefer msg.destroy(sema.gpa);
...@@ -31097,7 +31103,7 @@ fn coerceEnumToUnion(...@@ -31097,7 +31103,7 @@ fn coerceEnumToUnion(
31097 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {31103 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {
31098 const err_msg = msg orelse try sema.errMsg(31104 const err_msg = msg orelse try sema.errMsg(
31099 inst_src,31105 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",
31101 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },31107 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
31102 );31108 );
31103 msg = err_msg;31109 msg = err_msg;
...@@ -31120,7 +31126,7 @@ fn coerceEnumToUnion(...@@ -31120,7 +31126,7 @@ fn coerceEnumToUnion(
31120 const msg = msg: {31126 const msg = msg: {
31121 const msg = try sema.errMsg(31127 const msg = try sema.errMsg(
31122 inst_src,31128 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",
31124 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },31130 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
31125 );31131 );
31126 errdefer msg.destroy(sema.gpa);31132 errdefer msg.destroy(sema.gpa);
...@@ -31129,7 +31135,7 @@ fn coerceEnumToUnion(...@@ -31129,7 +31135,7 @@ fn coerceEnumToUnion(
31129 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31135 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31130 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);31136 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
31131 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;31137 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}'", .{
31133 field_name.fmt(ip),31139 field_name.fmt(ip),
31134 field_ty.fmt(pt),31140 field_ty.fmt(pt),
31135 });31141 });
...@@ -31170,7 +31176,7 @@ fn coerceArrayLike(...@@ -31170,7 +31176,7 @@ fn coerceArrayLike(
31170 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));31176 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));
31171 if (dest_len != inst_len) {31177 if (dest_len != inst_len) {
31172 const msg = msg: {31178 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}'", .{
31174 dest_ty.fmt(pt), inst_ty.fmt(pt),31180 dest_ty.fmt(pt), inst_ty.fmt(pt),
31175 });31181 });
31176 errdefer msg.destroy(sema.gpa);31182 errdefer msg.destroy(sema.gpa);
...@@ -31258,7 +31264,7 @@ fn coerceTupleToArray(...@@ -31258,7 +31264,7 @@ fn coerceTupleToArray(
3125831264
31259 if (dest_len != inst_len) {31265 if (dest_len != inst_len) {
31260 const msg = msg: {31266 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}'", .{
31262 dest_ty.fmt(pt), inst_ty.fmt(pt),31268 dest_ty.fmt(pt), inst_ty.fmt(pt),
31263 });31269 });
31264 errdefer msg.destroy(sema.gpa);31270 errdefer msg.destroy(sema.gpa);
...@@ -31734,10 +31740,10 @@ fn analyzeLoad(...@@ -31734,10 +31740,10 @@ fn analyzeLoad(
31734 const ptr_ty = sema.typeOf(ptr);31740 const ptr_ty = sema.typeOf(ptr);
31735 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {31741 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {
31736 .pointer => ptr_ty.childType(zcu),31742 .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)}),
31738 };31744 };
31739 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {31745 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)});
31741 }31747 }
3174231748
31743 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {31749 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {
...@@ -31758,7 +31764,7 @@ fn analyzeLoad(...@@ -31758,7 +31764,7 @@ fn analyzeLoad(
31758 const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;31764 const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
31759 return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);31765 return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
31760 }31766 }
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}'", .{
31762 ptr_ty.fmt(pt),31768 ptr_ty.fmt(pt),
31763 });31769 });
31764 }31770 }
...@@ -32046,7 +32052,7 @@ fn analyzeSlice(...@@ -32046,7 +32052,7 @@ fn analyzeSlice(
32046 const ptr_ptr_ty = sema.typeOf(ptr_ptr);32052 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
32047 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {32053 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {
32048 .pointer => ptr_ptr_ty.childType(zcu),32054 .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)}),
32050 };32056 };
3205132057
32052 var array_ty = ptr_ptr_child_ty;32058 var array_ty = ptr_ptr_child_ty;
...@@ -32095,7 +32101,7 @@ fn analyzeSlice(...@@ -32095,7 +32101,7 @@ fn analyzeSlice(
32095 try sema.errNote(32101 try sema.errNote(
32096 start_src,32102 start_src,
32097 msg,32103 msg,
32098 "expected '{}', found '{}'",32104 "expected '{f}', found '{f}'",
32099 .{32105 .{
32100 Value.zero_comptime_int.fmtValueSema(pt, sema),32106 Value.zero_comptime_int.fmtValueSema(pt, sema),
32101 start_value.fmtValueSema(pt, sema),32107 start_value.fmtValueSema(pt, sema),
...@@ -32111,7 +32117,7 @@ fn analyzeSlice(...@@ -32111,7 +32117,7 @@ fn analyzeSlice(
32111 try sema.errNote(32117 try sema.errNote(
32112 end_src,32118 end_src,
32113 msg,32119 msg,
32114 "expected '{}', found '{}'",32120 "expected '{f}', found '{f}'",
32115 .{32121 .{
32116 Value.one_comptime_int.fmtValueSema(pt, sema),32122 Value.one_comptime_int.fmtValueSema(pt, sema),
32117 end_value.fmtValueSema(pt, sema),32123 end_value.fmtValueSema(pt, sema),
...@@ -32126,7 +32132,7 @@ fn analyzeSlice(...@@ -32126,7 +32132,7 @@ fn analyzeSlice(
32126 return sema.fail(32132 return sema.fail(
32127 block,32133 block,
32128 end_src,32134 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",
32130 .{end_value.fmtValueSema(pt, sema)},32136 .{end_value.fmtValueSema(pt, sema)},
32131 );32137 );
32132 }32138 }
...@@ -32173,7 +32179,7 @@ fn analyzeSlice(...@@ -32173,7 +32179,7 @@ fn analyzeSlice(
32173 elem_ty = ptr_ptr_child_ty.childType(zcu);32179 elem_ty = ptr_ptr_child_ty.childType(zcu);
32174 },32180 },
32175 },32181 },
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)}),
32177 }32183 }
3217832184
32179 const ptr = if (slice_ty.isSlice(zcu))32185 const ptr = if (slice_ty.isSlice(zcu))
...@@ -32220,7 +32226,7 @@ fn analyzeSlice(...@@ -32220,7 +32226,7 @@ fn analyzeSlice(
32220 return sema.fail(32226 return sema.fail(
32221 block,32227 block,
32222 end_src,32228 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}",
32224 .{32230 .{
32225 end_val.fmtValueSema(pt, sema),32231 end_val.fmtValueSema(pt, sema),
32226 len_val.fmtValueSema(pt, sema),32232 len_val.fmtValueSema(pt, sema),
...@@ -32265,7 +32271,7 @@ fn analyzeSlice(...@@ -32265,7 +32271,7 @@ fn analyzeSlice(
32265 return sema.fail(32271 return sema.fail(
32266 block,32272 block,
32267 end_src,32273 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}",
32269 .{32275 .{
32270 end_val.fmtValueSema(pt, sema),32276 end_val.fmtValueSema(pt, sema),
32271 try slice_val.sliceLen(pt),32277 try slice_val.sliceLen(pt),
...@@ -32324,7 +32330,7 @@ fn analyzeSlice(...@@ -32324,7 +32330,7 @@ fn analyzeSlice(
32324 return sema.fail(32330 return sema.fail(
32325 block,32331 block,
32326 start_src,32332 start_src,
32327 "start index {} is larger than end index {}",32333 "start index {f} is larger than end index {f}",
32328 .{32334 .{
32329 start_val.fmtValueSema(pt, sema),32335 start_val.fmtValueSema(pt, sema),
32330 end_val.fmtValueSema(pt, sema),32336 end_val.fmtValueSema(pt, sema),
...@@ -32348,13 +32354,13 @@ fn analyzeSlice(...@@ -32348,13 +32354,13 @@ fn analyzeSlice(
32348 .needed_well_defined => |ty| return sema.fail(32354 .needed_well_defined => |ty| return sema.fail(
32349 block,32355 block,
32350 src,32356 src,
32351 "comptime dereference requires '{}' to have a well-defined layout",32357 "comptime dereference requires '{f}' to have a well-defined layout",
32352 .{ty.fmt(pt)},32358 .{ty.fmt(pt)},
32353 ),32359 ),
32354 .out_of_bounds => |ty| return sema.fail(32360 .out_of_bounds => |ty| return sema.fail(
32355 block,32361 block,
32356 end_src,32362 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}'",
32358 .{ end_int, ty.fmt(pt) },32364 .{ end_int, ty.fmt(pt) },
32359 ),32365 ),
32360 };32366 };
...@@ -32363,7 +32369,7 @@ fn analyzeSlice(...@@ -32363,7 +32369,7 @@ fn analyzeSlice(
32363 const msg = msg: {32369 const msg = msg: {
32364 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});32370 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});
32365 errdefer msg.destroy(sema.gpa);32371 errdefer msg.destroy(sema.gpa);
32366 try sema.errNote(src, msg, "expected '{}', found '{}'", .{32372 try sema.errNote(src, msg, "expected '{f}', found '{f}'", .{
32367 expected_sentinel.fmtValueSema(pt, sema),32373 expected_sentinel.fmtValueSema(pt, sema),
32368 actual_sentinel.fmtValueSema(pt, sema),32374 actual_sentinel.fmtValueSema(pt, sema),
32369 });32375 });
...@@ -33251,7 +33257,7 @@ const PeerResolveResult = union(enum) {...@@ -33251,7 +33257,7 @@ const PeerResolveResult = union(enum) {
33251 };33257 };
33252 },33258 },
33253 .field_error => |field_error| {33259 .field_error => |field_error| {
33254 const fmt = "struct field '{}' has conflicting types";33260 const fmt = "struct field '{f}' has conflicting types";
33255 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};33261 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};
33256 if (opt_msg) |msg| {33262 if (opt_msg) |msg| {
33257 try sema.errNote(src, msg, fmt, args);33263 try sema.errNote(src, msg, fmt, args);
...@@ -33282,7 +33288,7 @@ const PeerResolveResult = union(enum) {...@@ -33282,7 +33288,7 @@ const PeerResolveResult = union(enum) {
33282 candidate_srcs.resolve(block, conflict_idx[1]),33288 candidate_srcs.resolve(block, conflict_idx[1]),
33283 };33289 };
3328433290
33285 const fmt = "incompatible types: '{}' and '{}'";33291 const fmt = "incompatible types: '{f}' and '{f}'";
33286 const args = .{33292 const args = .{
33287 conflict_tys[0].fmt(pt),33293 conflict_tys[0].fmt(pt),
33288 conflict_tys[1].fmt(pt),33294 conflict_tys[1].fmt(pt),
...@@ -33296,8 +33302,8 @@ const PeerResolveResult = union(enum) {...@@ -33296,8 +33302,8 @@ const PeerResolveResult = union(enum) {
33296 break :msg msg;33302 break :msg msg;
33297 };33303 };
3329833304
33299 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(pt)});33305 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' 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)});33306 if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[1].fmt(pt)});
3330133307
33302 // No child error33308 // No child error
33303 break;33309 break;
...@@ -34609,7 +34615,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34609,7 +34615,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34609 if (struct_type.setLayoutWip(ip)) {34615 if (struct_type.setLayoutWip(ip)) {
34610 const msg = try sema.errMsg(34616 const msg = try sema.errMsg(
34611 ty.srcLoc(zcu),34617 ty.srcLoc(zcu),
34612 "struct '{}' depends on itself",34618 "struct '{f}' depends on itself",
34613 .{ty.fmt(pt)},34619 .{ty.fmt(pt)},
34614 );34620 );
34615 return sema.failWithOwnedErrorMsg(null, msg);34621 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -34828,13 +34834,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_...@@ -34828,13 +34834,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_
34828 const zcu = pt.zcu;34834 const zcu = pt.zcu;
3482934835
34830 if (!backing_int_ty.isInt(zcu)) {34836 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)});
34832 }34838 }
34833 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {34839 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {
34834 return sema.fail(34840 return sema.fail(
34835 block,34841 block,
34836 src,34842 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 {}",
34838 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },34844 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },
34839 );34845 );
34840 }34846 }
...@@ -34844,7 +34850,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -34844,7 +34850,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
34844 const pt = sema.pt;34850 const pt = sema.pt;
34845 if (!ty.isIndexable(pt.zcu)) {34851 if (!ty.isIndexable(pt.zcu)) {
34846 const msg = msg: {34852 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)});
34848 errdefer msg.destroy(sema.gpa);34854 errdefer msg.destroy(sema.gpa);
34849 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});34855 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});
34850 break :msg msg;34856 break :msg msg;
...@@ -34868,7 +34874,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void...@@ -34868,7 +34874,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
34868 }34874 }
34869 }34875 }
34870 const msg = msg: {34876 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)});
34872 errdefer msg.destroy(sema.gpa);34878 errdefer msg.destroy(sema.gpa);
34873 try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});34879 try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});
34874 break :msg msg;34880 break :msg msg;
...@@ -34936,7 +34942,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34936,7 +34942,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
34936 .field_types_wip, .layout_wip => {34942 .field_types_wip, .layout_wip => {
34937 const msg = try sema.errMsg(34943 const msg = try sema.errMsg(
34938 ty.srcLoc(pt.zcu),34944 ty.srcLoc(pt.zcu),
34939 "union '{}' depends on itself",34945 "union '{f}' depends on itself",
34940 .{ty.fmt(pt)},34946 .{ty.fmt(pt)},
34941 );34947 );
34942 return sema.failWithOwnedErrorMsg(null, msg);34948 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35124,7 +35130,7 @@ pub fn resolveStructFieldTypes(...@@ -35124,7 +35130,7 @@ pub fn resolveStructFieldTypes(
35124 if (struct_type.setFieldTypesWip(ip)) {35130 if (struct_type.setFieldTypesWip(ip)) {
35125 const msg = try sema.errMsg(35131 const msg = try sema.errMsg(
35126 Type.fromInterned(ty).srcLoc(zcu),35132 Type.fromInterned(ty).srcLoc(zcu),
35127 "struct '{}' depends on itself",35133 "struct '{f}' depends on itself",
35128 .{Type.fromInterned(ty).fmt(pt)},35134 .{Type.fromInterned(ty).fmt(pt)},
35129 );35135 );
35130 return sema.failWithOwnedErrorMsg(null, msg);35136 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35153,7 +35159,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -35153,7 +35159,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
35153 if (struct_type.setInitsWip(ip)) {35159 if (struct_type.setInitsWip(ip)) {
35154 const msg = try sema.errMsg(35160 const msg = try sema.errMsg(
35155 ty.srcLoc(zcu),35161 ty.srcLoc(zcu),
35156 "struct '{}' depends on itself",35162 "struct '{f}' depends on itself",
35157 .{ty.fmt(pt)},35163 .{ty.fmt(pt)},
35158 );35164 );
35159 return sema.failWithOwnedErrorMsg(null, msg);35165 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35179,7 +35185,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -35179,7 +35185,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
35179 .field_types_wip => {35185 .field_types_wip => {
35180 const msg = try sema.errMsg(35186 const msg = try sema.errMsg(
35181 ty.srcLoc(zcu),35187 ty.srcLoc(zcu),
35182 "union '{}' depends on itself",35188 "union '{f}' depends on itself",
35183 .{ty.fmt(pt)},35189 .{ty.fmt(pt)},
35184 );35190 );
35185 return sema.failWithOwnedErrorMsg(null, msg);35191 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35549,7 +35555,7 @@ fn structFields(...@@ -35549,7 +35555,7 @@ fn structFields(
35549 switch (struct_type.layout) {35555 switch (struct_type.layout) {
35550 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {35556 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
35551 const msg = msg: {35557 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)});
35553 errdefer msg.destroy(sema.gpa);35559 errdefer msg.destroy(sema.gpa);
3555435560
35555 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);35561 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);
...@@ -35561,7 +35567,7 @@ fn structFields(...@@ -35561,7 +35567,7 @@ fn structFields(
35561 },35567 },
35562 .@"packed" => if (!try sema.validatePackedType(field_ty)) {35568 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
35563 const msg = msg: {35569 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)});
35565 errdefer msg.destroy(sema.gpa);35571 errdefer msg.destroy(sema.gpa);
3556635572
35567 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);35573 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
...@@ -35808,7 +35814,7 @@ fn unionFields(...@@ -35808,7 +35814,7 @@ fn unionFields(
35808 // The provided type is an integer type and we must construct the enum tag type here.35814 // The provided type is an integer type and we must construct the enum tag type here.
35809 int_tag_ty = provided_ty;35815 int_tag_ty = provided_ty;
35810 if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) {35816 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)});
35812 }35818 }
3581335819
35814 if (fields_len > 0) {35820 if (fields_len > 0) {
...@@ -35817,7 +35823,7 @@ fn unionFields(...@@ -35817,7 +35823,7 @@ fn unionFields(
35817 const msg = msg: {35823 const msg = msg: {
35818 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});35824 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});
35819 errdefer msg.destroy(sema.gpa);35825 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}", .{
35821 int_tag_ty.fmt(pt),35827 int_tag_ty.fmt(pt),
35822 fields_len - 1,35828 fields_len - 1,
35823 });35829 });
...@@ -35832,7 +35838,7 @@ fn unionFields(...@@ -35832,7 +35838,7 @@ fn unionFields(
35832 // The provided type is the enum tag type.35838 // The provided type is the enum tag type.
35833 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {35839 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
35834 .enum_type => ip.loadEnumType(provided_ty.toIntern()),35840 .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)}),
35836 };35842 };
35837 union_type.setTagType(ip, provided_ty.toIntern());35843 union_type.setTagType(ip, provided_ty.toIntern());
35838 // The fields of the union must match the enum exactly.35844 // The fields of the union must match the enum exactly.
...@@ -35929,7 +35935,7 @@ fn unionFields(...@@ -35929,7 +35935,7 @@ fn unionFields(
35929 if (result.overflow) return sema.fail(35935 if (result.overflow) return sema.fail(
35930 &block_scope,35936 &block_scope,
35931 value_src,35937 value_src,
35932 "enumeration value '{}' too large for type '{}'",35938 "enumeration value '{f}' too large for type '{f}'",
35933 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },35939 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
35934 );35940 );
35935 last_tag_val = result.val;35941 last_tag_val = result.val;
...@@ -35947,7 +35953,7 @@ fn unionFields(...@@ -35947,7 +35953,7 @@ fn unionFields(
35947 const msg = msg: {35953 const msg = msg: {
35948 const msg = try sema.errMsg(35954 const msg = try sema.errMsg(
35949 value_src,35955 value_src,
35950 "enum tag value {} already taken",35956 "enum tag value {f} already taken",
35951 .{enum_tag_val.fmtValueSema(pt, sema)},35957 .{enum_tag_val.fmtValueSema(pt, sema)},
35952 );35958 );
35953 errdefer msg.destroy(gpa);35959 errdefer msg.destroy(gpa);
...@@ -35975,7 +35981,7 @@ fn unionFields(...@@ -35975,7 +35981,7 @@ fn unionFields(
35975 const tag_ty = union_type.tagTypeUnordered(ip);35981 const tag_ty = union_type.tagTypeUnordered(ip);
35976 const tag_info = ip.loadEnumType(tag_ty);35982 const tag_info = ip.loadEnumType(tag_ty);
35977 const enum_index = tag_info.nameIndex(ip, field_name) orelse {35983 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}'", .{
35979 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),35985 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),
35980 });35986 });
35981 };35987 };
...@@ -35992,7 +35998,7 @@ fn unionFields(...@@ -35992,7 +35998,7 @@ fn unionFields(
35992 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,35998 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,
35993 .offset = .{ .container_field_name = enum_index },35999 .offset = .{ .container_field_name = enum_index },
35994 };36000 };
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", .{
35996 field_name.fmt(ip),36002 field_name.fmt(ip),
35997 });36003 });
35998 errdefer msg.destroy(sema.gpa);36004 errdefer msg.destroy(sema.gpa);
...@@ -36018,7 +36024,7 @@ fn unionFields(...@@ -36018,7 +36024,7 @@ fn unionFields(
36018 !try sema.validateExternType(field_ty, .union_field))36024 !try sema.validateExternType(field_ty, .union_field))
36019 {36025 {
36020 const msg = msg: {36026 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)});
36022 errdefer msg.destroy(sema.gpa);36028 errdefer msg.destroy(sema.gpa);
3602336029
36024 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);36030 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);
...@@ -36029,7 +36035,7 @@ fn unionFields(...@@ -36029,7 +36035,7 @@ fn unionFields(
36029 return sema.failWithOwnedErrorMsg(&block_scope, msg);36035 return sema.failWithOwnedErrorMsg(&block_scope, msg);
36030 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {36036 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
36031 const msg = msg: {36037 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)});
36033 errdefer msg.destroy(sema.gpa);36039 errdefer msg.destroy(sema.gpa);
3603436040
36035 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);36041 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);
...@@ -36065,7 +36071,7 @@ fn unionFields(...@@ -36065,7 +36071,7 @@ fn unionFields(
3606536071
36066 for (tag_info.names.get(ip), 0..) |field_name, field_index| {36072 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
36067 if (explicit_tags_seen[field_index]) continue;36073 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", .{
36069 field_name.fmt(ip),36075 field_name.fmt(ip),
36070 });36076 });
36071 }36077 }
...@@ -36101,7 +36107,7 @@ fn generateUnionTagTypeNumbered(...@@ -36101,7 +36107,7 @@ fn generateUnionTagTypeNumbered(
36101 const name = try ip.getOrPutStringFmt(36107 const name = try ip.getOrPutStringFmt(
36102 gpa,36108 gpa,
36103 pt.tid,36109 pt.tid,
36104 "@typeInfo({}).@\"union\".tag_type.?",36110 "@typeInfo({f}).@\"union\".tag_type.?",
36105 .{union_name.fmt(ip)},36111 .{union_name.fmt(ip)},
36106 .no_embedded_nulls,36112 .no_embedded_nulls,
36107 );36113 );
...@@ -36137,7 +36143,7 @@ fn generateUnionTagTypeSimple(...@@ -36137,7 +36143,7 @@ fn generateUnionTagTypeSimple(
36137 const name = try ip.getOrPutStringFmt(36143 const name = try ip.getOrPutStringFmt(
36138 gpa,36144 gpa,
36139 pt.tid,36145 pt.tid,
36140 "@typeInfo({}).@\"union\".tag_type.?",36146 "@typeInfo({f}).@\"union\".tag_type.?",
36141 .{union_name.fmt(ip)},36147 .{union_name.fmt(ip)},
36142 .no_embedded_nulls,36148 .no_embedded_nulls,
36143 );36149 );
...@@ -36671,13 +36677,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr...@@ -36671,13 +36677,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
36671 .needed_well_defined => |ty| return sema.fail(36677 .needed_well_defined => |ty| return sema.fail(
36672 block,36678 block,
36673 src,36679 src,
36674 "comptime dereference requires '{}' to have a well-defined layout",36680 "comptime dereference requires '{f}' to have a well-defined layout",
36675 .{ty.fmt(pt)},36681 .{ty.fmt(pt)},
36676 ),36682 ),
36677 .out_of_bounds => |ty| return sema.fail(36683 .out_of_bounds => |ty| return sema.fail(
36678 block,36684 block,
36679 src,36685 src,
36680 "dereference of '{}' exceeds bounds of containing decl of type '{}'",36686 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
36681 .{ ptr_ty.fmt(pt), ty.fmt(pt) },36687 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
36682 ),36688 ),
36683 }36689 }
...@@ -36697,7 +36703,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -36697,7 +36703,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
36697 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },36703 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },
36698 .runtime_load => return .runtime_load,36704 .runtime_load => return .runtime_load,
36699 .undef => return sema.failWithUseOfUndef(block, src),36705 .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)}),
36701 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),36707 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),
36702 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),36708 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
36703 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },36709 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },
...@@ -36822,12 +36828,12 @@ fn intFromFloatScalar(...@@ -36822,12 +36828,12 @@ fn intFromFloatScalar(
3682236828
36823 const float = val.toFloat(f128, zcu);36829 const float = val.toFloat(f128, zcu);
36824 if (std.math.isNan(float)) {36830 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}'", .{
36826 int_ty.fmt(pt),36832 int_ty.fmt(pt),
36827 });36833 });
36828 }36834 }
36829 if (std.math.isInf(float)) {36835 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}'", .{
36831 int_ty.fmt(pt),36837 int_ty.fmt(pt),
36832 });36838 });
36833 }36839 }
...@@ -36842,7 +36848,7 @@ fn intFromFloatScalar(...@@ -36842,7 +36848,7 @@ fn intFromFloatScalar(
36842 .exact => return sema.fail(36848 .exact => return sema.fail(
36843 block,36849 block,
36844 src,36850 src,
36845 "fractional component prevents float value '{}' from coercion to type '{}'",36851 "fractional component prevents float value '{f}' from coercion to type '{f}'",
36846 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },36852 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },
36847 ),36853 ),
36848 .truncate => {},36854 .truncate => {},
...@@ -36854,7 +36860,7 @@ fn intFromFloatScalar(...@@ -36854,7 +36860,7 @@ fn intFromFloatScalar(
3685436860
36855 const int_info = int_ty.intInfo(zcu);36861 const int_info = int_ty.intInfo(zcu);
36856 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {36862 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}'", .{
36858 val.fmtValueSema(pt, sema), int_ty.fmt(pt),36864 val.fmtValueSema(pt, sema), int_ty.fmt(pt),
36859 });36865 });
36860 }36866 }
...@@ -37186,9 +37192,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37186,9 +37192,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3718637192
37187 var first_path: std.ArrayListUnmanaged(u8) = .empty;37193 var first_path: std.ArrayListUnmanaged(u8) = .empty;
37188 if (intermediate_value_count == 0) {37194 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)});
37190 } else {37196 } else {
37191 try first_path.writer(arena).print("v{}", .{intermediate_value_count - 1});37197 try first_path.print(arena, "v{}", .{intermediate_value_count - 1});
37192 }37198 }
3719337199
37194 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);37200 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);
...@@ -37213,30 +37219,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37213,30 +37219,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
37213 error.AnalysisFail => unreachable,37219 error.AnalysisFail => unreachable,
37214 };37220 };
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();
37217 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});37224 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});
37218 const deriv_start = @import("print_value.zig").printPtrDerivation(37225 const deriv_start = @import("print_value.zig").printPtrDerivation(
37219 derivation,37226 derivation,
37220 second_path.writer(arena),37227 &second_path_aw.interface,
37221 pt,37228 pt,
37222 .lvalue,37229 .lvalue,
37223 .{ .str = inter_name },37230 .{ .str = inter_name },
37224 20,37231 20,
37225 ) catch |err| switch (err) {37232 ) catch return error.OutOfMemory;
37226 error.OutOfMemory => |e| return e,
37227 error.AnalysisFail => unreachable,
37228 error.ComptimeReturn => unreachable,
37229 error.ComptimeBreak => unreachable,
37230 };
3723137233
37232 switch (deriv_start) {37234 switch (deriv_start) {
37233 .int, .nav_ptr => unreachable,37235 .int, .nav_ptr => unreachable,
37234 .uav_ptr => |uav| {37236 .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() });
37236 return .{ .new_val = .fromInterned(uav.val) };37238 return .{ .new_val = .fromInterned(uav.val) };
37237 },37239 },
37238 .comptime_alloc_ptr => |cta_info| {37240 .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() });
37240 const cta = sema.getComptimeAlloc(cta_info.idx);37242 const cta = sema.getComptimeAlloc(cta_info.idx);
37241 if (cta.is_const) {37243 if (cta.is_const) {
37242 return .{ .new_val = cta_info.val };37244 return .{ .new_val = cta_info.val };
...@@ -37246,7 +37248,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37246,7 +37248,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
37246 }37248 }
37247 },37249 },
37248 .comptime_field_ptr => {37250 .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() });
37250 try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name});37252 try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name});
37251 return .done;37253 return .done;
37252 },37254 },
...@@ -37286,7 +37288,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList...@@ -37286,7 +37288,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
37286 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);37288 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);
37287 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;37289 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;
37288 const field_name = backing_enum.enumFieldName(field_idx, zcu);37290 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)});
37290 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);37292 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);
37291 },37293 },
37292 .aggregate => |agg| {37294 .aggregate => |agg| {
...@@ -37301,17 +37303,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList...@@ -37301,17 +37303,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
37301 };37303 };
37302 const agg_ty: Type = .fromInterned(agg.ty);37304 const agg_ty: Type = .fromInterned(agg.ty);
37303 switch (agg_ty.zigTypeTag(zcu)) {37305 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}),
37305 .pointer => switch (elem_idx) {37307 .pointer => switch (elem_idx) {
37306 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),37308 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),
37307 Value.slice_len_index => try path.appendSlice(arena, ".len"),37309 Value.slice_len_index => try path.appendSlice(arena, ".len"),
37308 else => unreachable,37310 else => unreachable,
37309 },37311 },
37310 .@"struct" => if (agg_ty.isTuple(zcu)) {37312 .@"struct" => if (agg_ty.isTuple(zcu)) {
37311 try path.writer(arena).print("[{d}]", .{elem_idx});37313 try path.print(arena, "[{d}]", .{elem_idx});
37312 } else {37314 } else {
37313 const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;37315 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)});
37315 },37317 },
37316 else => unreachable,37318 else => unreachable,
37317 }37319 }
...@@ -37588,7 +37590,7 @@ fn resolveDeclaredEnumInner(...@@ -37588,7 +37590,7 @@ fn resolveDeclaredEnumInner(
37588 if (tag_type_ref != .none) {37590 if (tag_type_ref != .none) {
37589 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);37591 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
37590 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {37592 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)});
37592 }37594 }
37593 break :ty ty;37595 break :ty ty;
37594 } else if (fields_len == 0) {37596 } else if (fields_len == 0) {
...@@ -37642,7 +37644,7 @@ fn resolveDeclaredEnumInner(...@@ -37642,7 +37644,7 @@ fn resolveDeclaredEnumInner(
37642 .offset = .{ .container_field_value = conflict.prev_field_idx },37644 .offset = .{ .container_field_value = conflict.prev_field_idx },
37643 };37645 };
37644 const msg = msg: {37646 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)});
37646 errdefer msg.destroy(gpa);37648 errdefer msg.destroy(gpa);
37647 try sema.errNote(other_field_src, msg, "other occurrence here", .{});37649 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37648 break :msg msg;37650 break :msg msg;
...@@ -37665,7 +37667,7 @@ fn resolveDeclaredEnumInner(...@@ -37665,7 +37667,7 @@ fn resolveDeclaredEnumInner(
37665 .offset = .{ .container_field_value = conflict.prev_field_idx },37667 .offset = .{ .container_field_value = conflict.prev_field_idx },
37666 };37668 };
37667 const msg = msg: {37669 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)});
37669 errdefer msg.destroy(gpa);37671 errdefer msg.destroy(gpa);
37670 try sema.errNote(other_field_src, msg, "other occurrence here", .{});37672 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37671 break :msg msg;37673 break :msg msg;
...@@ -37682,7 +37684,7 @@ fn resolveDeclaredEnumInner(...@@ -37682,7 +37684,7 @@ fn resolveDeclaredEnumInner(
37682 };37684 };
3768337685
37684 if (tag_overflow) {37686 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}'", .{
37686 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),37688 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),
37687 });37689 });
37688 return sema.failWithOwnedErrorMsg(block, msg);37690 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...@@ -661,7 +661,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I
661 const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse {661 const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse {
662 return self.fail(662 return self.fail(
663 node,663 node,
664 "enum {} has no member named '{}'",664 "enum {f} has no member named '{f}'",
665 .{665 .{
666 res_ty.fmt(self.sema.pt),666 res_ty.fmt(self.sema.pt),
667 std.zig.fmtId(field_name.get(self.file.zoir.?)),667 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...@@ -382,7 +382,9 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
382 }382 }
383 }383 }
384 switch (fn_info.cc) {384 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 }),
386 else => try writer.print("callconv({any}) ", .{fn_info.cc}),388 else => try writer.print("callconv({any}) ", .{fn_info.cc}),
387 }389 }
388 }390 }
src/Zcu.zig+1-1
...@@ -2811,7 +2811,7 @@ comptime {...@@ -2811,7 +2811,7 @@ comptime {
2811}2811}
28122812
2813pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {2813pub 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);
2815}2815}
28162816
2817pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {2817pub 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(...@@ -341,7 +341,7 @@ fn loadZirZoirCache(
341 };341 };
342342
343 // First we read the header to determine the lengths of arrays.343 // 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) {
345 // This can happen if Zig bails out of this function between creating345 // This can happen if Zig bails out of this function between creating
346 // the cached file and writing it.346 // the cached file and writing it.
347 error.EndOfStream => return .invalid,347 error.EndOfStream => return .invalid,
...@@ -477,11 +477,11 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -477,11 +477,11 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
477 if (std.zig.srcHashEql(old_hash, new_hash)) {477 if (std.zig.srcHashEql(old_hash, new_hash)) {
478 break :hash_changed;478 break :hash_changed;
479 }479 }
480 log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{480 log.debug("hash for (%{d} -> %{d}) changed: {x} -> {x}", .{
481 old_inst,481 old_inst,
482 new_inst,482 new_inst,
483 std.fmt.fmtSliceHexLower(&old_hash),483 &old_hash,
484 std.fmt.fmtSliceHexLower(&new_hash),484 &new_hash,
485 });485 });
486 }486 }
487 // The source hash associated with this instruction changed - invalidate relevant dependencies.487 // 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...@@ -4378,7 +4378,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4378 if (build_options.enable_debug_extensions and comp.verbose_air) {4378 if (build_options.enable_debug_extensions and comp.verbose_air) {
4379 std.debug.lockStdErr();4379 std.debug.lockStdErr();
4380 defer std.debug.unlockStdErr();4380 defer std.debug.unlockStdErr();
4381 const stderr = std.fs.File.stderr().writer();4381 const stderr = std.fs.File.stderr().deprecatedWriter();
4382 stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {};4382 stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {};
4383 air.write(stderr, pt, liveness);4383 air.write(stderr, pt, liveness);
4384 stderr.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}) catch {};4384 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(...@@ -187,7 +187,7 @@ pub fn format(
187 },187 },
188 }188 }
189189
190 try writer.print(".{}", .{std.fmt.fmtSliceHexUpper(opc[0 .. opc.len - 1])});190 try writer.print(".{X}", .{opc[0 .. opc.len - 1]});
191 opc = opc[opc.len - 1 ..];191 opc = opc[opc.len - 1 ..];
192192
193 try writer.writeAll(".W");193 try writer.writeAll(".W");
src/arch/x86_64/encoder.zig+2-2
...@@ -1205,9 +1205,9 @@ pub const Vex = struct {...@@ -1205,9 +1205,9 @@ pub const Vex = struct {
1205fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {1205fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {
1206 assert(expected.len > 0);1206 assert(expected.len > 0);
1207 if (std.mem.eql(u8, expected, given)) return;1207 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});
1209 defer testing.allocator.free(expected_fmt);1209 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});
1211 defer testing.allocator.free(given_fmt);1211 defer testing.allocator.free(given_fmt);
1212 const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;1212 const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
1213 const padding = try testing.allocator.alloc(u8, idx + 5);1213 const padding = try testing.allocator.alloc(u8, idx + 5);
src/codegen/llvm.zig+1-1
...@@ -2486,7 +2486,7 @@ pub const Object = struct {...@@ -2486,7 +2486,7 @@ pub const Object = struct {
2486 var union_name_buf: ?[:0]const u8 = null;2486 var union_name_buf: ?[:0]const u8 = null;
2487 defer if (union_name_buf) |buf| gpa.free(buf);2487 defer if (union_name_buf) |buf| gpa.free(buf);
2488 const union_name = if (layout.tag_size == 0) name else name: {2488 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);
2490 break :name union_name_buf.?;2490 break :name union_name_buf.?;
2491 };2491 };
24922492
src/crash_report.zig+7-7
...@@ -80,7 +80,7 @@ fn dumpStatusReport() !void {...@@ -80,7 +80,7 @@ fn dumpStatusReport() !void {
80 var fba = std.heap.FixedBufferAllocator.init(&crash_heap);80 var fba = std.heap.FixedBufferAllocator.init(&crash_heap);
81 const allocator = fba.allocator();81 const allocator = fba.allocator();
8282
83 const stderr = std.fs.File.stderr().writer();83 const stderr = std.fs.File.stderr().deprecatedWriter();
84 const block: *Sema.Block = anal.block;84 const block: *Sema.Block = anal.block;
85 const zcu = anal.sema.pt.zcu;85 const zcu = anal.sema.pt.zcu;
8686
...@@ -271,7 +271,7 @@ const StackContext = union(enum) {...@@ -271,7 +271,7 @@ const StackContext = union(enum) {
271 debug.dumpStackTraceFromBase(context);271 debug.dumpStackTraceFromBase(context);
272 },272 },
273 .not_supported => {273 .not_supported => {
274 const stderr = std.fs.File.stderr().writer();274 const stderr = std.fs.File.stderr().deprecatedWriter();
275 stderr.writeAll("Stack trace not supported on this platform.\n") catch {};275 stderr.writeAll("Stack trace not supported on this platform.\n") catch {};
276 },276 },
277 }277 }
...@@ -379,7 +379,7 @@ const PanicSwitch = struct {...@@ -379,7 +379,7 @@ const PanicSwitch = struct {
379379
380 state.recover_stage = .release_mutex;380 state.recover_stage = .release_mutex;
381381
382 const stderr = std.fs.File.stderr().writer();382 const stderr = std.fs.File.stderr().deprecatedWriter();
383 if (builtin.single_threaded) {383 if (builtin.single_threaded) {
384 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});384 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});
385 } else {385 } else {
...@@ -406,7 +406,7 @@ const PanicSwitch = struct {...@@ -406,7 +406,7 @@ const PanicSwitch = struct {
406 recover(state, trace, stack, msg);406 recover(state, trace, stack, msg);
407407
408 state.recover_stage = .release_mutex;408 state.recover_stage = .release_mutex;
409 const stderr = std.fs.File.stderr().writer();409 const stderr = std.fs.File.stderr().deprecatedWriter();
410 stderr.writeAll("\nOriginal Error:\n") catch {};410 stderr.writeAll("\nOriginal Error:\n") catch {};
411 goTo(reportStack, .{state});411 goTo(reportStack, .{state});
412 }412 }
...@@ -477,7 +477,7 @@ const PanicSwitch = struct {...@@ -477,7 +477,7 @@ const PanicSwitch = struct {
477 recover(state, trace, stack, msg);477 recover(state, trace, stack, msg);
478478
479 state.recover_stage = .silent_abort;479 state.recover_stage = .silent_abort;
480 const stderr = std.fs.File.stderr().writer();480 const stderr = std.fs.File.stderr().deprecatedWriter();
481 stderr.writeAll("Aborting...\n") catch {};481 stderr.writeAll("Aborting...\n") catch {};
482 goTo(abort, .{});482 goTo(abort, .{});
483 }483 }
...@@ -505,7 +505,7 @@ const PanicSwitch = struct {...@@ -505,7 +505,7 @@ const PanicSwitch = struct {
505 // lower the verbosity, and restore it at the end if we don't panic.505 // lower the verbosity, and restore it at the end if we don't panic.
506 state.recover_verbosity = .message_only;506 state.recover_verbosity = .message_only;
507507
508 const stderr = std.fs.File.stderr().writer();508 const stderr = std.fs.File.stderr().deprecatedWriter();
509 stderr.writeAll("\nPanicked during a panic: ") catch {};509 stderr.writeAll("\nPanicked during a panic: ") catch {};
510 stderr.writeAll(msg) catch {};510 stderr.writeAll(msg) catch {};
511 stderr.writeAll("\nInner panic stack:\n") catch {};511 stderr.writeAll("\nInner panic stack:\n") catch {};
...@@ -519,7 +519,7 @@ const PanicSwitch = struct {...@@ -519,7 +519,7 @@ const PanicSwitch = struct {
519 .message_only => {519 .message_only => {
520 state.recover_verbosity = .silent;520 state.recover_verbosity = .silent;
521521
522 const stderr = std.fs.File.stderr().writer();522 const stderr = std.fs.File.stderr().deprecatedWriter();
523 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};523 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
524 stderr.writeAll(msg) catch {};524 stderr.writeAll(msg) catch {};
525 stderr.writeAll("\n") catch {};525 stderr.writeAll("\n") catch {};
src/fmt.zig+3-3
...@@ -60,7 +60,7 @@ pub fn run(...@@ -60,7 +60,7 @@ pub fn run(
60 const arg = args[i];60 const arg = args[i];
61 if (mem.startsWith(u8, arg, "-")) {61 if (mem.startsWith(u8, arg, "-")) {
62 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {62 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();
64 try stdout.writeAll(usage_fmt);64 try stdout.writeAll(usage_fmt);
65 return process.cleanExit();65 return process.cleanExit();
66 } else if (mem.eql(u8, arg, "--color")) {66 } else if (mem.eql(u8, arg, "--color")) {
...@@ -371,7 +371,7 @@ fn fmtPathFile(...@@ -371,7 +371,7 @@ fn fmtPathFile(
371 return;371 return;
372372
373 if (check_mode) {373 if (check_mode) {
374 const stdout = std.fs.File.stdout().writer();374 const stdout = std.fs.File.stdout().deprecatedWriter();
375 try stdout.print("{s}\n", .{file_path});375 try stdout.print("{s}\n", .{file_path});
376 fmt.any_error = true;376 fmt.any_error = true;
377 } else {377 } else {
...@@ -380,7 +380,7 @@ fn fmtPathFile(...@@ -380,7 +380,7 @@ fn fmtPathFile(
380380
381 try af.file.writeAll(fmt.out_buffer.items);381 try af.file.writeAll(fmt.out_buffer.items);
382 try af.finish();382 try af.finish();
383 const stdout = std.fs.File.stdout().writer();383 const stdout = std.fs.File.stdout().deprecatedWriter();
384 try stdout.print("{s}\n", .{file_path});384 try stdout.print("{s}\n", .{file_path});
385 }385 }
386}386}
src/libs/libtsan.zig+1-1
...@@ -268,7 +268,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -268,7 +268,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
268 const skip_linker_dependencies = !target.os.tag.isDarwin();268 const skip_linker_dependencies = !target.os.tag.isDarwin();
269 const linker_allow_shlib_undefined = target.os.tag.isDarwin();269 const linker_allow_shlib_undefined = target.os.tag.isDarwin();
270 const install_name = if (target.os.tag.isDarwin())270 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)
272 else272 else
273 null;273 null;
274 // Workaround for https://github.com/llvm/llvm-project/issues/97627274 // 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 {...@@ -306,7 +306,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
306 if (comp.verbose_cc) print: {306 if (comp.verbose_cc) print: {
307 std.debug.lockStdErr();307 std.debug.lockStdErr();
308 defer std.debug.unlockStdErr();308 defer std.debug.unlockStdErr();
309 const stderr = std.fs.File.stderr().writer();309 const stderr = std.fs.File.stderr().deprecatedWriter();
310 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;310 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;
311 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;311 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
312 nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print;312 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 {...@@ -335,7 +335,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
335 // new scope to ensure definition file is written before passing the path to WriteImportLibrary335 // new scope to ensure definition file is written before passing the path to WriteImportLibrary
336 const def_final_file = try o_dir.createFile(final_def_basename, .{ .truncate = true });336 const def_final_file = try o_dir.createFile(final_def_basename, .{ .truncate = true });
337 defer def_final_file.close();337 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);
339 }339 }
340340
341 const lib_final_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });341 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...@@ -830,8 +830,8 @@ fn debugMem(allocator: Allocator, handle: std.process.Child.Id, pvaddr: std.os.w
830 const buffer = try allocator.alloc(u8, code.len);830 const buffer = try allocator.alloc(u8, code.len);
831 defer allocator.free(buffer);831 defer allocator.free(buffer);
832 const memread = try std.os.windows.ReadProcessMemory(handle, pvaddr, buffer);832 const memread = try std.os.windows.ReadProcessMemory(handle, pvaddr, buffer);
833 log.debug("to write: {x}", .{std.fmt.fmtSliceHexLower(code)});833 log.debug("to write: {x}", .{code});
834 log.debug("in memory: {x}", .{std.fmt.fmtSliceHexLower(memread)});834 log.debug("in memory: {x}", .{memread});
835}835}
836836
837fn writeMemProtected(handle: std.process.Child.Id, pvaddr: std.os.windows.LPVOID, code: []const u8) !void {837fn 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(...@@ -44,8 +44,8 @@ pub fn parse(
44 pos += @sizeOf(elf.ar_hdr);44 pos += @sizeOf(elf.ar_hdr);
4545
46 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) {46 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) {
47 return diags.failParse(path, "invalid archive header delimiter: {s}", .{47 return diags.failParse(path, "invalid archive header delimiter: {f}", .{
48 std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),48 std.ascii.hexEscape(&hdr.ar_fmag, .lower),
49 });49 });
50 }50 }
5151
...@@ -288,7 +288,7 @@ pub const ArStrtab = struct {...@@ -288,7 +288,7 @@ pub const ArStrtab = struct {
288 ) !void {288 ) !void {
289 _ = unused_fmt_string;289 _ = unused_fmt_string;
290 _ = options;290 _ = options;
291 try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});291 try writer.print("{f}", .{std.ascii.hexEscape(ar.buffer.items, .lower)});
292 }292 }
293};293};
294294
src/link/Elf/LinkerDefined.zig+2-2
...@@ -147,9 +147,9 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {...@@ -147,9 +147,9 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
147 for (slice.items(.shdr)) |shdr| {147 for (slice.items(.shdr)) |shdr| {
148 // TODO use getOrPut for incremental so that we don't create duplicates148 // TODO use getOrPut for incremental so that we don't create duplicates
149 if (elf_file.getStartStopBasename(shdr)) |name| {149 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);
151 defer gpa.free(start_name);151 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);
153 defer gpa.free(stop_name);153 defer gpa.free(stop_name);
154154
155 for (&[_][]const u8{ start_name, stop_name }) |nn| {155 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 {...@@ -803,9 +803,9 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void {
803 const out_shndx = atom_ptr.output_section_index;803 const out_shndx = atom_ptr.output_section_index;
804 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];804 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];
805 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;805 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}", .{
807 elf_file.getShString(out_shdr.sh_name),807 elf_file.getShString(out_shdr.sh_name),
808 });808 }, 0);
809 defer gpa.free(rela_sect_name);809 defer gpa.free(rela_sect_name);
810 _ = elf_file.sectionByName(rela_sect_name) orelse810 _ = elf_file.sectionByName(rela_sect_name) orelse
811 try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), out_shndx);811 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 {...@@ -824,9 +824,9 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
824 const out_shndx = atom_ptr.output_section_index;824 const out_shndx = atom_ptr.output_section_index;
825 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];825 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];
826 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;826 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}", .{
828 elf_file.getShString(out_shdr.sh_name),828 elf_file.getShString(out_shdr.sh_name),
829 });829 }, 0);
830 defer gpa.free(rela_sect_name);830 defer gpa.free(rela_sect_name);
831 const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?;831 const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?;
832 const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx];832 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 {...@@ -163,7 +163,7 @@ fn prune(elf_file: *Elf) void {
163}163}
164164
165pub fn dumpPrunedAtoms(elf_file: *Elf) !void {165pub fn dumpPrunedAtoms(elf_file: *Elf) !void {
166 const stderr = std.fs.File.stderr().writer();166 const stderr = std.fs.File.stderr().deprecatedWriter();
167 for (elf_file.objects.items) |index| {167 for (elf_file.objects.items) |index| {
168 const file = elf_file.file(index).?;168 const file = elf_file.file(index).?;
169 for (file.atoms()) |atom_index| {169 for (file.atoms()) |atom_index| {
src/link/LdScript.zig+2-2
...@@ -41,8 +41,8 @@ pub fn parse(...@@ -41,8 +41,8 @@ pub fn parse(
41 try line_col.append(gpa, .{ .line = line, .column = column });41 try line_col.append(gpa, .{ .line = line, .column = column });
42 switch (tok.id) {42 switch (tok.id) {
43 .invalid => {43 .invalid => {
44 return diags.failParse(path, "invalid token in LD script: '{s}' ({d}:{d})", .{44 return diags.failParse(path, "invalid token in LD script: '{f}' ({d}:{d})", .{
45 std.fmt.fmtSliceEscapeLower(tok.get(data)), line, column,45 std.ascii.hexEscape(tok.get(data), .lower), line, column,
46 });46 });
47 },47 },
48 .new_line => {48 .new_line => {
src/link/Lld.zig+3-7
...@@ -933,9 +933,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -933,9 +933,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
933 .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{933 .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
934 @tagName(base.build_id),934 @tagName(base.build_id),
935 })),935 })),
936 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{936 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()})),
937 std.fmt.fmtSliceHexLower(hs.toSlice()),
938 })),
939 }937 }
940938
941 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{elf.image_base}));939 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 {...@@ -1511,9 +1509,7 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
1511 .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{1509 .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
1512 @tagName(base.build_id),1510 @tagName(base.build_id),
1513 })),1511 })),
1514 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{1512 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()})),
1515 std.fmt.fmtSliceHexLower(hs.toSlice()),
1516 })),
1517 .md5 => {},1513 .md5 => {},
1518 }1514 }
15191515
...@@ -1667,7 +1663,7 @@ fn spawnLld(...@@ -1667,7 +1663,7 @@ fn spawnLld(
1667 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });1663 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
1668 {1664 {
1669 defer rsp_file.close();1665 defer rsp_file.close();
1670 var rsp_buf = std.io.bufferedWriter(rsp_file.writer());1666 var rsp_buf = std.io.bufferedWriter(rsp_file.deprecatedWriter());
1671 const rsp_writer = rsp_buf.writer();1667 const rsp_writer = rsp_buf.writer();
1672 for (argv[2..]) |arg| {1668 for (argv[2..]) |arg| {
1673 try rsp_writer.writeByte('"');1669 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...@@ -29,8 +29,8 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
29 pos += @sizeOf(ar_hdr);29 pos += @sizeOf(ar_hdr);
3030
31 if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) {31 if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) {
32 return diags.failParse(path, "invalid header delimiter: expected '{s}', found '{s}'", .{32 return diags.failParse(path, "invalid header delimiter: expected '{f}', found '{f}'", .{
33 std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),33 std.ascii.hexEscape(ARFMAG, .lower), std.ascii.hexEscape(&hdr.ar_fmag, .lower),
34 });34 });
35 }35 }
3636
src/link/MachO/Object.zig+7-7
...@@ -308,7 +308,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {...@@ -308,7 +308,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {
308 } else nlists.len;308 } else nlists.len;
309309
310 if (nlist_start == nlist_end or nlists[nlist_start].nlist.n_value > sect.addr) {310 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);
312 defer allocator.free(name);312 defer allocator.free(name);
313 const size = if (nlist_start == nlist_end) sect.size else nlists[nlist_start].nlist.n_value - sect.addr;313 const size = if (nlist_start == nlist_end) sect.size else nlists[nlist_start].nlist.n_value - sect.addr;
314 const atom_index = try self.addAtom(allocator, .{314 const atom_index = try self.addAtom(allocator, .{
...@@ -364,7 +364,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {...@@ -364,7 +364,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {
364 // which cannot be contained in any non-zero atom (since then this atom364 // which cannot be contained in any non-zero atom (since then this atom
365 // would exceed section boundaries). In order to facilitate this behaviour,365 // would exceed section boundaries). In order to facilitate this behaviour,
366 // we create a dummy zero-sized atom at section end (addr + size).366 // 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);
368 defer allocator.free(name);368 defer allocator.free(name);
369 const atom_index = try self.addAtom(allocator, .{369 const atom_index = try self.addAtom(allocator, .{
370 .name = try self.addString(allocator, name),370 .name = try self.addString(allocator, name),
...@@ -394,7 +394,7 @@ fn initSections(self: *Object, allocator: Allocator, nlists: anytype) !void {...@@ -394,7 +394,7 @@ fn initSections(self: *Object, allocator: Allocator, nlists: anytype) !void {
394 if (isFixedSizeLiteral(sect)) continue;394 if (isFixedSizeLiteral(sect)) continue;
395 if (isPtrLiteral(sect)) continue;395 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);
398 defer allocator.free(name);398 defer allocator.free(name);
399399
400 const atom_index = try self.addAtom(allocator, .{400 const atom_index = try self.addAtom(allocator, .{
...@@ -462,7 +462,7 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m...@@ -462,7 +462,7 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m
462 }462 }
463 end += 1;463 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);
466 defer allocator.free(name);466 defer allocator.free(name);
467 const name_str = try self.addString(allocator, name);467 const name_str = try self.addString(allocator, name);
468468
...@@ -529,7 +529,7 @@ fn initFixedSizeLiterals(self: *Object, allocator: Allocator, macho_file: *MachO...@@ -529,7 +529,7 @@ fn initFixedSizeLiterals(self: *Object, allocator: Allocator, macho_file: *MachO
529 pos += rec_size;529 pos += rec_size;
530 count += 1;530 count += 1;
531 }) {531 }) {
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);
533 defer allocator.free(name);533 defer allocator.free(name);
534 const name_str = try self.addString(allocator, name);534 const name_str = try self.addString(allocator, name);
535535
...@@ -587,7 +587,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO)...@@ -587,7 +587,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO)
587 for (0..num_ptrs) |i| {587 for (0..num_ptrs) |i| {
588 const pos: u32 = @as(u32, @intCast(i)) * rec_size;588 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);
591 defer allocator.free(name);591 defer allocator.free(name);
592 const name_str = try self.addString(allocator, name);592 const name_str = try self.addString(allocator, name);
593593
...@@ -1558,7 +1558,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {...@@ -1558,7 +1558,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {
1558 const nlist = &self.symtab.items(.nlist)[nlist_idx];1558 const nlist = &self.symtab.items(.nlist)[nlist_idx];
1559 const nlist_atom = &self.symtab.items(.atom)[nlist_idx];1559 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);
1562 defer gpa.free(name);1562 defer gpa.free(name);
15631563
1564 const alignment = (nlist.n_desc >> 8) & 0x0f;1564 const alignment = (nlist.n_desc >> 8) & 0x0f;
src/link/MachO/ZigObject.zig+1-1
...@@ -959,7 +959,7 @@ fn updateNavCode(...@@ -959,7 +959,7 @@ fn updateNavCode(
959 sym.out_n_sect = sect_index;959 sym.out_n_sect = sect_index;
960 atom.out_n_sect = sect_index;960 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);
963 defer gpa.free(sym_name);963 defer gpa.free(sym_name);
964 sym.name = try self.addString(gpa, sym_name);964 sym.name = try self.addString(gpa, sym_name);
965 atom.setAlive(true);965 atom.setAlive(true);
src/link/MachO/dyld_info/Trie.zig+2-2
...@@ -336,9 +336,9 @@ const Edge = struct {...@@ -336,9 +336,9 @@ const Edge = struct {
336fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {336fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
337 assert(expected.len > 0);337 assert(expected.len > 0);
338 if (mem.eql(u8, expected, given)) return;338 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});
340 defer testing.allocator.free(expected_fmt);340 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});
342 defer testing.allocator.free(given_fmt);342 defer testing.allocator.free(given_fmt);
343 const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;343 const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
344 const padding = try testing.allocator.alloc(u8, idx + 5);344 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 {...@@ -1035,20 +1035,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1035 var id: [16]u8 = undefined;1035 var id: [16]u8 = undefined;
1036 std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});1036 std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
1037 var uuid: [36]u8 = undefined;1037 var uuid: [36]u8 = undefined;
1038 _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{1038 _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{
1039 std.fmt.fmtSliceHexLower(id[0..4]),1039 id[0..4], id[4..6], id[6..8], id[8..10], id[10..],
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..]),
1044 });1040 });
1045 try emitBuildIdSection(gpa, binary_bytes, &uuid);1041 try emitBuildIdSection(gpa, binary_bytes, &uuid);
1046 },1042 },
1047 .hexstring => |hs| {1043 .hexstring => |hs| {
1048 var buffer: [32 * 2]u8 = undefined;1044 var buffer: [32 * 2]u8 = undefined;
1049 const str = std.fmt.bufPrint(&buffer, "{s}", .{1045 const str = std.fmt.bufPrint(&buffer, "{x}", .{hs.toSlice()}) catch unreachable;
1050 std.fmt.fmtSliceHexLower(hs.toSlice()),
1051 }) catch unreachable;
1052 try emitBuildIdSection(gpa, binary_bytes, str);1046 try emitBuildIdSection(gpa, binary_bytes, str);
1053 },1047 },
1054 else => |mode| {1048 else => |mode| {
src/link/tapi/parse.zig+10-39
...@@ -57,14 +57,9 @@ pub const Node = struct {...@@ -57,14 +57,9 @@ pub const Node = struct {
57 }57 }
58 }58 }
5959
60 pub fn format(60 pub fn format(self: *const Node, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
61 self: *const Node,
62 comptime fmt: []const u8,
63 options: std.fmt.FormatOptions,
64 writer: anytype,
65 ) !void {
66 switch (self.tag) {61 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),
68 }63 }
69 }64 }
7065
...@@ -86,14 +81,8 @@ pub const Node = struct {...@@ -86,14 +81,8 @@ pub const Node = struct {
86 }81 }
87 }82 }
8883
89 pub fn format(84 pub fn format(self: *const Doc, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
90 self: *const Doc,85 comptime assert(fmt.len == 0);
91 comptime fmt: []const u8,
92 options: std.fmt.FormatOptions,
93 writer: anytype,
94 ) !void {
95 _ = options;
96 _ = fmt;
97 if (self.directive) |id| {86 if (self.directive) |id| {
98 try std.fmt.format(writer, "{{ ", .{});87 try std.fmt.format(writer, "{{ ", .{});
99 const directive = self.base.tree.getRaw(id, id);88 const directive = self.base.tree.getRaw(id, id);
...@@ -133,14 +122,8 @@ pub const Node = struct {...@@ -133,14 +122,8 @@ pub const Node = struct {
133 self.values.deinit(allocator);122 self.values.deinit(allocator);
134 }123 }
135124
136 pub fn format(125 pub fn format(self: *const Map, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
137 self: *const Map,126 comptime assert(fmt.len == 0);
138 comptime fmt: []const u8,
139 options: std.fmt.FormatOptions,
140 writer: anytype,
141 ) !void {
142 _ = options;
143 _ = fmt;
144 try std.fmt.format(writer, "{{ ", .{});127 try std.fmt.format(writer, "{{ ", .{});
145 for (self.values.items) |entry| {128 for (self.values.items) |entry| {
146 const key = self.base.tree.getRaw(entry.key, entry.key);129 const key = self.base.tree.getRaw(entry.key, entry.key);
...@@ -172,14 +155,8 @@ pub const Node = struct {...@@ -172,14 +155,8 @@ pub const Node = struct {
172 self.values.deinit(allocator);155 self.values.deinit(allocator);
173 }156 }
174157
175 pub fn format(158 pub fn format(self: *const List, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
176 self: *const List,159 comptime assert(fmt.len == 0);
177 comptime fmt: []const u8,
178 options: std.fmt.FormatOptions,
179 writer: anytype,
180 ) !void {
181 _ = options;
182 _ = fmt;
183 try std.fmt.format(writer, "[ ", .{});160 try std.fmt.format(writer, "[ ", .{});
184 for (self.values.items) |node| {161 for (self.values.items) |node| {
185 try std.fmt.format(writer, "{}, ", .{node});162 try std.fmt.format(writer, "{}, ", .{node});
...@@ -203,14 +180,8 @@ pub const Node = struct {...@@ -203,14 +180,8 @@ pub const Node = struct {
203 self.string_value.deinit(allocator);180 self.string_value.deinit(allocator);
204 }181 }
205182
206 pub fn format(183 pub fn format(self: *const Value, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
207 self: *const Value,184 comptime assert(fmt.len == 0);
208 comptime fmt: []const u8,
209 options: std.fmt.FormatOptions,
210 writer: anytype,
211 ) !void {
212 _ = options;
213 _ = fmt;
214 const raw = self.base.tree.getRaw(self.base.start, self.base.end);185 const raw = self.base.tree.getRaw(self.base.start, self.base.end);
215 return std.fmt.format(writer, "{s}", .{raw});186 return std.fmt.format(writer, "{s}", .{raw});
216 }187 }
src/main.zig+22-23
...@@ -340,7 +340,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -340,7 +340,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
340 } else if (mem.eql(u8, cmd, "targets")) {340 } else if (mem.eql(u8, cmd, "targets")) {
341 dev.check(.targets_command);341 dev.check(.targets_command);
342 const host = std.zig.resolveTargetQueryOrFatal(.{});342 const host = std.zig.resolveTargetQueryOrFatal(.{});
343 const stdout = fs.File.stdout().writer();343 const stdout = fs.File.stdout().deprecatedWriter();
344 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host);344 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host);
345 } else if (mem.eql(u8, cmd, "version")) {345 } else if (mem.eql(u8, cmd, "version")) {
346 dev.check(.version_command);346 dev.check(.version_command);
...@@ -352,7 +352,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -352,7 +352,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
352 } else if (mem.eql(u8, cmd, "env")) {352 } else if (mem.eql(u8, cmd, "env")) {
353 dev.check(.env_command);353 dev.check(.env_command);
354 verifyLibcxxCorrectlyLinked();354 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());
356 } else if (mem.eql(u8, cmd, "reduce")) {356 } else if (mem.eql(u8, cmd, "reduce")) {
357 return jitCmd(gpa, arena, cmd_args, .{357 return jitCmd(gpa, arena, cmd_args, .{
358 .cmd_name = "reduce",358 .cmd_name = "reduce",
...@@ -3333,9 +3333,8 @@ fn buildOutputType(...@@ -3333,9 +3333,8 @@ fn buildOutputType(
3333 var bin_digest: Cache.BinDigest = undefined;3333 var bin_digest: Cache.BinDigest = undefined;
3334 hasher.final(&bin_digest);3334 hasher.final(&bin_digest);
33353335
3336 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{s}-stdin{s}", .{3336 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
3337 std.fmt.fmtSliceHexLower(&bin_digest),3337 &bin_digest, ext.canonicalName(target),
3338 ext.canonicalName(target),
3339 });3338 });
3340 try dirs.local_cache.handle.rename(dump_path, sub_path);3339 try dirs.local_cache.handle.rename(dump_path, sub_path);
33413340
...@@ -6110,7 +6109,7 @@ fn cmdAstCheck(...@@ -6110,7 +6109,7 @@ fn cmdAstCheck(
6110 const stdout = fs.File.stdout();6109 const stdout = fs.File.stdout();
6111 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;6110 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
6112 // zig fmt: off6111 // zig fmt: off
6113 try stdout.writer().print(6112 try stdout.deprecatedWriter().print(
6114 \\# Source bytes: {}6113 \\# Source bytes: {}
6115 \\# Tokens: {} ({})6114 \\# Tokens: {} ({})
6116 \\# AST Nodes: {} ({})6115 \\# AST Nodes: {} ({})
...@@ -6186,7 +6185,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {...@@ -6186,7 +6185,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {
6186 const arg = args[i];6185 const arg = args[i];
6187 if (mem.startsWith(u8, arg, "-")) {6186 if (mem.startsWith(u8, arg, "-")) {
6188 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6187 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();
6190 try stdout.writeAll(detect_cpu_usage);6189 try stdout.writeAll(detect_cpu_usage);
6191 return cleanExit();6190 return cleanExit();
6192 } else if (mem.eql(u8, arg, "--llvm")) {6191 } else if (mem.eql(u8, arg, "--llvm")) {
...@@ -6279,7 +6278,7 @@ fn detectNativeCpuWithLLVM(...@@ -6279,7 +6278,7 @@ fn detectNativeCpuWithLLVM(
6279}6278}
62806279
6281fn printCpu(cpu: std.Target.Cpu) !void {6280fn printCpu(cpu: std.Target.Cpu) !void {
6282 var bw = io.bufferedWriter(fs.File.stdout().writer());6281 var bw = io.bufferedWriter(fs.File.stdout().deprecatedWriter());
6283 const stdout = bw.writer();6282 const stdout = bw.writer();
62846283
6285 if (cpu.model.llvm_name) |llvm_name| {6284 if (cpu.model.llvm_name) |llvm_name| {
...@@ -6328,7 +6327,7 @@ fn cmdDumpLlvmInts(...@@ -6328,7 +6327,7 @@ fn cmdDumpLlvmInts(
6328 const dl = tm.createTargetDataLayout();6327 const dl = tm.createTargetDataLayout();
6329 const context = llvm.Context.create();6328 const context = llvm.Context.create();
63306329
6331 var bw = io.bufferedWriter(fs.File.stdout().writer());6330 var bw = io.bufferedWriter(fs.File.stdout().deprecatedWriter());
6332 const stdout = bw.writer();6331 const stdout = bw.writer();
63336332
6334 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {6333 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
...@@ -6371,7 +6370,7 @@ fn cmdDumpZir(...@@ -6371,7 +6370,7 @@ fn cmdDumpZir(
6371 const stdout = fs.File.stdout();6370 const stdout = fs.File.stdout();
6372 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;6371 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
6373 // zig fmt: off6372 // zig fmt: off
6374 try stdout.writer().print(6373 try stdout.deprecatedWriter().print(
6375 \\# Total ZIR bytes: {}6374 \\# Total ZIR bytes: {}
6376 \\# Instructions: {d} ({})6375 \\# Instructions: {d} ({})
6377 \\# String Table Bytes: {}6376 \\# String Table Bytes: {}
...@@ -6444,7 +6443,7 @@ fn cmdChangelist(...@@ -6444,7 +6443,7 @@ fn cmdChangelist(
6444 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;6443 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
6445 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);6444 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());
6448 const stdout = bw.writer();6447 const stdout = bw.writer();
6449 {6448 {
6450 try stdout.print("Instruction mappings:\n", .{});6449 try stdout.print("Instruction mappings:\n", .{});
...@@ -6794,7 +6793,7 @@ fn cmdFetch(...@@ -6794,7 +6793,7 @@ fn cmdFetch(
6794 const arg = args[i];6793 const arg = args[i];
6795 if (mem.startsWith(u8, arg, "-")) {6794 if (mem.startsWith(u8, arg, "-")) {
6796 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6795 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();
6798 try stdout.writeAll(usage_fetch);6797 try stdout.writeAll(usage_fetch);
6799 return cleanExit();6798 return cleanExit();
6800 } else if (mem.eql(u8, arg, "--global-cache-dir")) {6799 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
...@@ -6908,7 +6907,7 @@ fn cmdFetch(...@@ -6908,7 +6907,7 @@ fn cmdFetch(
69086907
6909 const name = switch (save) {6908 const name = switch (save) {
6910 .no => {6909 .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});
6912 return cleanExit();6911 return cleanExit();
6913 },6912 },
6914 .yes, .exact => |name| name: {6913 .yes, .exact => |name| name: {
...@@ -6973,16 +6972,16 @@ fn cmdFetch(...@@ -6973,16 +6972,16 @@ fn cmdFetch(
69736972
6974 const new_node_init = try std.fmt.allocPrint(arena,6973 const new_node_init = try std.fmt.allocPrint(arena,
6975 \\.{{6974 \\.{{
6976 \\ .url = "{}",6975 \\ .url = "{f}",
6977 \\ .hash = "{}",6976 \\ .hash = "{f}",
6978 \\ }}6977 \\ }}
6979 , .{6978 , .{
6980 std.zig.fmtEscapes(saved_path_or_url),6979 std.zig.fmtString(saved_path_or_url),
6981 std.zig.fmtEscapes(package_hash_slice),6980 std.zig.fmtString(package_hash_slice),
6982 });6981 });
69836982
6984 const new_node_text = try std.fmt.allocPrint(arena, ".{p_} = {s},\n", .{6983 const new_node_text = try std.fmt.allocPrint(arena, ".{f} = {s},\n", .{
6985 std.zig.fmtId(name), new_node_init,6984 std.zig.fmtIdPU(name), new_node_init,
6986 });6985 });
69876986
6988 const dependencies_init = try std.fmt.allocPrint(arena, ".{{\n {s} }}", .{6987 const dependencies_init = try std.fmt.allocPrint(arena, ".{{\n {s} }}", .{
...@@ -7008,13 +7007,13 @@ fn cmdFetch(...@@ -7008,13 +7007,13 @@ fn cmdFetch(
70087007
7009 const location_replace = try std.fmt.allocPrint(7008 const location_replace = try std.fmt.allocPrint(
7010 arena,7009 arena,
7011 "\"{}\"",7010 "\"{f}\"",
7012 .{std.zig.fmtEscapes(saved_path_or_url)},7011 .{std.zig.fmtString(saved_path_or_url)},
7013 );7012 );
7014 const hash_replace = try std.fmt.allocPrint(7013 const hash_replace = try std.fmt.allocPrint(
7015 arena,7014 arena,
7016 "\"{}\"",7015 "\"{f}\"",
7017 .{std.zig.fmtEscapes(package_hash_slice)},7016 .{std.zig.fmtString(package_hash_slice)},
7018 );7017 );
70197018
7020 warn("overwriting existing dependency named '{s}'", .{name});7019 warn("overwriting existing dependency named '{s}'", .{name});
src/print_value.zig+2-2
...@@ -232,7 +232,7 @@ fn printAggregate(...@@ -232,7 +232,7 @@ fn printAggregate(
232 const len = ty.arrayLenIncludingSentinel(zcu);232 const len = ty.arrayLenIncludingSentinel(zcu);
233 if (len == 0) break :string;233 if (len == 0) break :string;
234 const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip);234 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)});
236 if (!is_ref) try writer.writeAll(".*");236 if (!is_ref) try writer.writeAll(".*");
237 return;237 return;
238 },238 },
...@@ -249,7 +249,7 @@ fn printAggregate(...@@ -249,7 +249,7 @@ fn printAggregate(
249 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);249 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);
250 if (elem_val.isUndef(zcu)) break :one_byte_str;250 if (elem_val.isUndef(zcu)) break :one_byte_str;
251 const byte = elem_val.toUnsignedInt(zcu);251 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)})});
253 if (!is_ref) try writer.writeAll(".*");253 if (!is_ref) try writer.writeAll(".*");
254 return;254 return;
255 },255 },
src/print_zir.zig+29-33
...@@ -30,7 +30,7 @@ pub fn renderAsTextToFile(...@@ -30,7 +30,7 @@ pub fn renderAsTextToFile(
30 .recurse_blocks = true,30 .recurse_blocks = true,
31 };31 };
3232
33 var raw_stream = std.io.bufferedWriter(fs_file.writer());33 var raw_stream = std.io.bufferedWriter(fs_file.deprecatedWriter());
34 const stream = raw_stream.writer();34 const stream = raw_stream.writer();
3535
36 const main_struct_inst: Zir.Inst.Index = .main_struct_inst;36 const main_struct_inst: Zir.Inst.Index = .main_struct_inst;
...@@ -49,8 +49,8 @@ pub fn renderAsTextToFile(...@@ -49,8 +49,8 @@ pub fn renderAsTextToFile(
49 extra_index = item.end;49 extra_index = item.end;
5050
51 const import_path = zir.nullTerminatedString(item.data.name);51 const import_path = zir.nullTerminatedString(item.data.name);
52 try stream.print(" @import(\"{}\") ", .{52 try stream.print(" @import(\"{f}\") ", .{
53 std.zig.fmtEscapes(import_path),53 std.zig.fmtString(import_path),
54 });54 });
55 try writer.writeSrcTokAbs(stream, item.data.token);55 try writer.writeSrcTokAbs(stream, item.data.token);
56 try stream.writeAll("\n");56 try stream.writeAll("\n");
...@@ -789,7 +789,7 @@ const Writer = struct {...@@ -789,7 +789,7 @@ const Writer = struct {
789 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {789 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
790 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;790 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
791 const str = inst_data.get(self.code);791 const str = inst_data.get(self.code);
792 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});792 try stream.print("\"{f}\")", .{std.zig.fmtString(str)});
793 }793 }
794794
795 fn writeSliceStart(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {795 fn writeSliceStart(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
...@@ -932,8 +932,8 @@ const Writer = struct {...@@ -932,8 +932,8 @@ const Writer = struct {
932 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;932 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
933 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);933 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
934 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);934 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
935 try stream.print("\"{}\", ", .{935 try stream.print("\"{f}\", ", .{
936 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),936 std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)),
937 });937 });
938938
939 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");939 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
...@@ -1203,7 +1203,7 @@ const Writer = struct {...@@ -1203,7 +1203,7 @@ const Writer = struct {
1203 try stream.writeAll(", ");1203 try stream.writeAll(", ");
1204 } else {1204 } else {
1205 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);1205 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)});
1207 }1207 }
1208 try stream.writeAll(", ");1208 try stream.writeAll(", ");
12091209
...@@ -1220,8 +1220,8 @@ const Writer = struct {...@@ -1220,8 +1220,8 @@ const Writer = struct {
12201220
1221 const name = self.code.nullTerminatedString(output.data.name);1221 const name = self.code.nullTerminatedString(output.data.name);
1222 const constraint = self.code.nullTerminatedString(output.data.constraint);1222 const constraint = self.code.nullTerminatedString(output.data.constraint);
1223 try stream.print("output({p}, \"{}\", ", .{1223 try stream.print("output({f}, \"{f}\", ", .{
1224 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),1224 std.zig.fmtIdFlags(name, .{ .allow_primitive = true }), std.zig.fmtString(constraint),
1225 });1225 });
1226 try self.writeFlag(stream, "->", is_type);1226 try self.writeFlag(stream, "->", is_type);
1227 try self.writeInstRef(stream, output.data.operand);1227 try self.writeInstRef(stream, output.data.operand);
...@@ -1239,8 +1239,8 @@ const Writer = struct {...@@ -1239,8 +1239,8 @@ const Writer = struct {
12391239
1240 const name = self.code.nullTerminatedString(input.data.name);1240 const name = self.code.nullTerminatedString(input.data.name);
1241 const constraint = self.code.nullTerminatedString(input.data.constraint);1241 const constraint = self.code.nullTerminatedString(input.data.constraint);
1242 try stream.print("input({p}, \"{}\", ", .{1242 try stream.print("input({f}, \"{f}\", ", .{
1243 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),1243 std.zig.fmtIdFlags(name, .{ .allow_primitive = true }), std.zig.fmtString(constraint),
1244 });1244 });
1245 try self.writeInstRef(stream, input.data.operand);1245 try self.writeInstRef(stream, input.data.operand);
1246 try stream.writeAll(")");1246 try stream.writeAll(")");
...@@ -1255,7 +1255,7 @@ const Writer = struct {...@@ -1255,7 +1255,7 @@ const Writer = struct {
1255 const str_index = self.code.extra[extra_i];1255 const str_index = self.code.extra[extra_i];
1256 extra_i += 1;1256 extra_i += 1;
1257 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));1257 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 })});
1259 if (i + 1 < clobbers_len) {1259 if (i + 1 < clobbers_len) {
1260 try stream.writeAll(", ");1260 try stream.writeAll(", ");
1261 }1261 }
...@@ -1299,7 +1299,7 @@ const Writer = struct {...@@ -1299,7 +1299,7 @@ const Writer = struct {
1299 .field => {1299 .field => {
1300 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);1300 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
1301 try self.writeInstRef(stream, extra.data.obj_ptr);1301 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)});
1303 },1303 },
1304 }1304 }
1305 try stream.writeAll(", [");1305 try stream.writeAll(", [");
...@@ -1388,7 +1388,7 @@ const Writer = struct {...@@ -1388,7 +1388,7 @@ const Writer = struct {
1388 extra.data.fields_hash_3,1388 extra.data.fields_hash_3,
1389 });1389 });
13901390
1391 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});1391 try stream.print("hash({x}) ", .{&fields_hash});
13921392
1393 var extra_index: usize = extra.end;1393 var extra_index: usize = extra.end;
13941394
...@@ -1519,7 +1519,7 @@ const Writer = struct {...@@ -1519,7 +1519,7 @@ const Writer = struct {
1519 try self.writeFlag(stream, "comptime ", field.is_comptime);1519 try self.writeFlag(stream, "comptime ", field.is_comptime);
1520 if (field.name != .empty) {1520 if (field.name != .empty) {
1521 const field_name = self.code.nullTerminatedString(field.name);1521 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 })});
1523 } else {1523 } else {
1524 try stream.print("@\"{d}\": ", .{i});1524 try stream.print("@\"{d}\": ", .{i});
1525 }1525 }
...@@ -1580,7 +1580,7 @@ const Writer = struct {...@@ -1580,7 +1580,7 @@ const Writer = struct {
1580 extra.data.fields_hash_3,1580 extra.data.fields_hash_3,
1581 });1581 });
15821582
1583 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});1583 try stream.print("hash({x}) ", .{&fields_hash});
15841584
1585 var extra_index: usize = extra.end;1585 var extra_index: usize = extra.end;
15861586
...@@ -1682,7 +1682,7 @@ const Writer = struct {...@@ -1682,7 +1682,7 @@ const Writer = struct {
1682 extra_index += 1;1682 extra_index += 1;
16831683
1684 try stream.writeByteNTimes(' ', self.indent);1684 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
1687 if (has_type) {1687 if (has_type) {
1688 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1688 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
...@@ -1731,7 +1731,7 @@ const Writer = struct {...@@ -1731,7 +1731,7 @@ const Writer = struct {
1731 extra.data.fields_hash_3,1731 extra.data.fields_hash_3,
1732 });1732 });
17331733
1734 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});1734 try stream.print("hash({x}) ", .{&fields_hash});
17351735
1736 var extra_index: usize = extra.end;1736 var extra_index: usize = extra.end;
17371737
...@@ -1816,7 +1816,7 @@ const Writer = struct {...@@ -1816,7 +1816,7 @@ const Writer = struct {
1816 extra_index += 1;1816 extra_index += 1;
18171817
1818 try stream.writeByteNTimes(' ', self.indent);1818 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
1821 if (has_tag_value) {1821 if (has_tag_value) {
1822 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1822 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
...@@ -1921,7 +1921,7 @@ const Writer = struct {...@@ -1921,7 +1921,7 @@ const Writer = struct {
1921 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);1921 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1922 const name = self.code.nullTerminatedString(name_index);1922 const name = self.code.nullTerminatedString(name_index);
1923 try stream.writeByteNTimes(' ', self.indent);1923 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 })});
1925 }1925 }
19261926
1927 self.indent -= 2;1927 self.indent -= 2;
...@@ -2203,7 +2203,7 @@ const Writer = struct {...@@ -2203,7 +2203,7 @@ const Writer = struct {
2203 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;2203 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
2204 const name = self.code.nullTerminatedString(extra.field_name_start);2204 const name = self.code.nullTerminatedString(extra.field_name_start);
2205 try self.writeInstRef(stream, extra.lhs);2205 try self.writeInstRef(stream, extra.lhs);
2206 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});2206 try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)});
2207 try self.writeSrcNode(stream, inst_data.src_node);2207 try self.writeSrcNode(stream, inst_data.src_node);
2208 }2208 }
22092209
...@@ -2244,7 +2244,7 @@ const Writer = struct {...@@ -2244,7 +2244,7 @@ const Writer = struct {
2244 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {2244 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2245 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;2245 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
2246 const str = inst_data.get(self.code);2246 const str = inst_data.get(self.code);
2247 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});2247 try stream.print("\"{f}\") ", .{std.zig.fmtString(str)});
2248 try self.writeSrcTok(stream, inst_data.src_tok);2248 try self.writeSrcTok(stream, inst_data.src_tok);
2249 }2249 }
22502250
...@@ -2252,7 +2252,7 @@ const Writer = struct {...@@ -2252,7 +2252,7 @@ const Writer = struct {
2252 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;2252 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
2253 const str = inst_data.getStr(self.code);2253 const str = inst_data.getStr(self.code);
2254 try self.writeInstRef(stream, inst_data.operand);2254 try self.writeInstRef(stream, inst_data.operand);
2255 try stream.print(", \"{}\")", .{std.zig.fmtEscapes(str)});2255 try stream.print(", \"{f}\")", .{std.zig.fmtString(str)});
2256 }2256 }
22572257
2258 fn writeFunc(2258 fn writeFunc(
...@@ -2594,11 +2594,7 @@ const Writer = struct {...@@ -2594,11 +2594,7 @@ const Writer = struct {
2594 },2594 },
2595 }2595 }
2596 const src_hash = self.code.getAssociatedSrcHash(inst).?;2596 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2597 try stream.print(" line({d}) column({d}) hash({})", .{2597 try stream.print(" line({d}) column({d}) hash({x})", .{ decl.src_line, decl.src_column, &src_hash });
2598 decl.src_line,
2599 decl.src_column,
2600 std.fmt.fmtSliceHexLower(&src_hash),
2601 });
26022598
2603 {2599 {
2604 if (decl.type_body) |b| {2600 if (decl.type_body) |b| {
...@@ -2694,11 +2690,11 @@ const Writer = struct {...@@ -2694,11 +2690,11 @@ const Writer = struct {
2694 try stream.writeAll("load ");2690 try stream.writeAll("load ");
2695 try self.writeInstIndex(stream, ptr_inst);2691 try self.writeInstIndex(stream, ptr_inst);
2696 },2692 },
2697 .decl_val => |str| try stream.print("decl_val \"{}\"", .{2693 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{
2698 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),2694 std.zig.fmtString(self.code.nullTerminatedString(str)),
2699 }),2695 }),
2700 .decl_ref => |str| try stream.print("decl_ref \"{}\"", .{2696 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
2701 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),2697 std.zig.fmtString(self.code.nullTerminatedString(str)),
2702 }),2698 }),
2703 }2699 }
2704 }2700 }
...@@ -2831,7 +2827,7 @@ const Writer = struct {...@@ -2831,7 +2827,7 @@ const Writer = struct {
2831 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;2827 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
2832 try self.writeInstRef(stream, extra.res_ty);2828 try self.writeInstRef(stream, extra.res_ty);
2833 const import_path = self.code.nullTerminatedString(extra.path);2829 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)});
2835 try self.writeSrcTok(stream, inst_data.src_tok);2831 try self.writeSrcTok(stream, inst_data.src_tok);
2836 }2832 }
2837};2833};
src/print_zoir.zig+3-3
...@@ -77,8 +77,8 @@ const PrintZon = struct {...@@ -77,8 +77,8 @@ const PrintZon = struct {
77 },77 },
78 .float_literal => |x| try pz.w.print("float({d})", .{x}),78 .float_literal => |x| try pz.w.print("float({d})", .{x}),
79 .char_literal => |x| try pz.w.print("char({d})", .{x}),79 .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))}),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(\"{}\")", .{std.zig.fmtEscapes(x)}),81 .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtString(x)}),
82 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),82 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),
83 .array_literal => |vals| {83 .array_literal => |vals| {
84 try pz.w.writeAll("array_literal({");84 try pz.w.writeAll("array_literal({");
...@@ -97,7 +97,7 @@ const PrintZon = struct {...@@ -97,7 +97,7 @@ const PrintZon = struct {
97 pz.indent += 1;97 pz.indent += 1;
98 for (s.names, 0..s.vals.len) |name, idx| {98 for (s.names, 0..s.vals.len) |name, idx| {
99 try pz.newline();99 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))});
101 try pz.renderNode(s.vals.at(@intCast(idx)));101 try pz.renderNode(s.vals.at(@intCast(idx)));
102 try pz.w.writeByte(',');102 try pz.w.writeByte(',');
103 }103 }
src/translate_c.zig+11-11
...@@ -357,7 +357,7 @@ fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.Fi...@@ -357,7 +357,7 @@ fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.Fi
357 var len: usize = undefined;357 var len: usize = undefined;
358 const bytes_ptr = asm_string.getString_bytes_begin_size(&len);358 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])});
361 const str_node = try Tag.string_literal.create(c.arena, str);361 const str_node = try Tag.string_literal.create(c.arena, str);
362362
363 const asm_node = try Tag.asm_simple.create(c.arena, str_node);363 const asm_node = try Tag.asm_simple.create(c.arena, str_node);
...@@ -2276,7 +2276,7 @@ fn transNarrowStringLiteral(...@@ -2276,7 +2276,7 @@ fn transNarrowStringLiteral(
2276 var len: usize = undefined;2276 var len: usize = undefined;
2277 const bytes_ptr = stmt.getString_bytes_begin_size(&len);2277 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])});
2280 const node = try Tag.string_literal.create(c.arena, str);2280 const node = try Tag.string_literal.create(c.arena, str);
2281 return maybeSuppressResult(c, result_used, node);2281 return maybeSuppressResult(c, result_used, node);
2282}2282}
...@@ -3338,7 +3338,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined...@@ -3338,7 +3338,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined
33383338
3339fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {3339fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
3340 return Tag.char_literal.create(c.arena, if (narrow)3340 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))})})
3342 else3342 else
3343 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));3343 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
3344}3344}
...@@ -5832,7 +5832,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5832,7 +5832,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5832 num += c - 'A' + 10;5832 num += c - 'A' + 10;
5833 },5833 },
5834 else => {5834 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 });
5836 num = 0;5836 num = 0;
5837 if (c == '\\')5837 if (c == '\\')
5838 state = .escape5838 state = .escape
...@@ -5858,7 +5858,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5858,7 +5858,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5858 };5858 };
5859 num += c - '0';5859 num += c - '0';
5860 } else {5860 } 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 });
5862 num = 0;5862 num = 0;
5863 count = 0;5863 count = 0;
5864 if (c == '\\')5864 if (c == '\\')
...@@ -5872,21 +5872,21 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5872,21 +5872,21 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5872 }5872 }
5873 }5873 }
5874 if (state == .hex or state == .octal)5874 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 });
5876 return bytes[0..i];5876 return bytes[0..i];
5877}5877}
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.
5880/// If a C string literal or char literal in a macro is not valid UTF-8, we need to escape5880/// If a C string literal or char literal in a macro is not valid UTF-8, we need to escape
5881/// non-ASCII characters so that the Zig source we output will itself be UTF-8.5881/// non-ASCII characters so that the Zig source we output will itself be UTF-8.
5882fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 {5882fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 {
5883 const zigified = try zigifyEscapeSequences(ctx, m);5883 const zigified = try zigifyEscapeSequences(ctx, m);
5884 if (std.unicode.utf8ValidateSlice(zigified)) return zigified;5884 if (std.unicode.utf8ValidateSlice(zigified)) return zigified;
58855885
5886 const formatter = std.fmt.fmtSliceEscapeLower(zigified);5886 const formatter = std.ascii.hexEscape(zigified, .lower);
5887 const encoded_size = @as(usize, @intCast(std.fmt.count("{s}", .{formatter})));5887 const encoded_size = @as(usize, @intCast(std.fmt.count("{fs}", .{formatter})));
5888 const output = try ctx.arena.alloc(u8, encoded_size);5888 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) {
5890 error.NoSpaceLeft => unreachable,5890 error.NoSpaceLeft => unreachable,
5891 else => |e| return e,5891 else => |e| return e,
5892 };5892 };
...@@ -5905,7 +5905,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -5905,7 +5905,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5905 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {5905 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
5906 return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m));5906 return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m));
5907 } else {5907 } 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]});
5909 return Tag.integer_literal.create(c.arena, str);5909 return Tag.integer_literal.create(c.arena, str);
5910 }5910 }
5911 },5911 },
test/behavior/union_with_members.zig+2-2
...@@ -10,8 +10,8 @@ const ET = union(enum) {...@@ -10,8 +10,8 @@ const ET = union(enum) {
1010
11 pub fn print(a: *const ET, buf: []u8) anyerror!usize {11 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
12 return switch (a.*) {12 return switch (a.*) {
13 ET.SINT => |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.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}),14 ET.UINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}),
15 };15 };
16 }16 }
17};17};
test/link/elf.zig+2-2
...@@ -1316,7 +1316,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {...@@ -1316,7 +1316,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {
1316 \\extern fn live_fn2() void;1316 \\extern fn live_fn2() void;
1317 \\pub fn main() void {1317 \\pub fn main() void {
1318 \\ const stdout = std.io.getStdOut();1318 \\ 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;
1320 \\ live_fn2();1320 \\ live_fn2();
1321 \\}1321 \\}
1322 ,1322 ,
...@@ -1358,7 +1358,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {...@@ -1358,7 +1358,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {
1358 \\extern fn live_fn2() void;1358 \\extern fn live_fn2() void;
1359 \\pub fn main() void {1359 \\pub fn main() void {
1360 \\ const stdout = std.io.getStdOut();1360 \\ 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;
1362 \\ live_fn2();1362 \\ live_fn2();
1363 \\}1363 \\}
1364 ,1364 ,
test/standalone/run_output_paths/create_file.zig+1-1
...@@ -10,7 +10,7 @@ pub fn main() !void {...@@ -10,7 +10,7 @@ pub fn main() !void {
10 dir_name, .{});10 dir_name, .{});
11 const file_name = args.next().?;11 const file_name = args.next().?;
12 const file = try dir.createFile(file_name, .{});12 const file = try dir.createFile(file_name, .{});
13 try file.writer().print(13 try file.deprecatedWriter().print(
14 \\{s}14 \\{s}
15 \\{s}15 \\{s}
16 \\Hello, world!16 \\Hello, world!
test/standalone/simple/brace_expansion.zig+1-1
...@@ -228,7 +228,7 @@ pub fn main() !void {...@@ -228,7 +228,7 @@ pub fn main() !void {
228 const stdin_file = io.getStdIn();228 const stdin_file = io.getStdIn();
229 const stdout_file = io.getStdOut();229 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));
232 defer global_allocator.free(stdin);232 defer global_allocator.free(stdin);
233233
234 var result_buf = ArrayList(u8).init(global_allocator);234 var result_buf = ArrayList(u8).init(global_allocator);
test/standalone/windows_argv/fuzz.zig+1-1
...@@ -58,7 +58,7 @@ pub fn main() !void {...@@ -58,7 +58,7 @@ pub fn main() !void {
58 std.debug.print(">>> found discrepancy <<<\n", .{});58 std.debug.print(">>> found discrepancy <<<\n", .{});
59 const cmd_line_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, cmd_line_w);59 const cmd_line_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, cmd_line_w);
60 defer allocator.free(cmd_line_wtf8);60 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
63 errors += 1;63 errors += 1;
64 }64 }
test/standalone/windows_argv/lib.zig+6-6
...@@ -27,8 +27,8 @@ fn testArgv(expected_args: []const [*:0]const u16) !void {...@@ -27,8 +27,8 @@ fn testArgv(expected_args: []const [*:0]const u16) !void {
27 wtf8_buf.clearRetainingCapacity();27 wtf8_buf.clearRetainingCapacity();
28 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(expected_arg));28 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(expected_arg));
29 if (!std.mem.eql(u8, wtf8_buf.items, arg_wtf8)) {29 if (!std.mem.eql(u8, wtf8_buf.items, arg_wtf8)) {
30 std.debug.print("{}: expected: \"{}\"\n", .{ i, std.zig.fmtEscapes(wtf8_buf.items) });30 std.debug.print("{}: expected: \"{f}\"\n", .{ i, std.zig.fmtString(wtf8_buf.items) });
31 std.debug.print("{}: actual: \"{}\"\n", .{ i, std.zig.fmtEscapes(arg_wtf8) });31 std.debug.print("{}: actual: \"{f}\"\n", .{ i, std.zig.fmtString(arg_wtf8) });
32 eql = false;32 eql = false;
33 }33 }
34 }34 }
...@@ -36,22 +36,22 @@ fn testArgv(expected_args: []const [*:0]const u16) !void {...@@ -36,22 +36,22 @@ fn testArgv(expected_args: []const [*:0]const u16) !void {
36 for (expected_args[min_len..], min_len..) |arg, i| {36 for (expected_args[min_len..], min_len..) |arg, i| {
37 wtf8_buf.clearRetainingCapacity();37 wtf8_buf.clearRetainingCapacity();
38 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(arg));38 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) });
40 }40 }
41 for (args[min_len..], min_len..) |arg, i| {41 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) });
43 }43 }
44 const peb = std.os.windows.peb();44 const peb = std.os.windows.peb();
45 const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer);45 const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer);
46 wtf8_buf.clearRetainingCapacity();46 wtf8_buf.clearRetainingCapacity();
47 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(lpCmdLine));47 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)});
49 std.debug.print("expected argv:\n", .{});49 std.debug.print("expected argv:\n", .{});
50 std.debug.print("&.{{\n", .{});50 std.debug.print("&.{{\n", .{});
51 for (expected_args) |arg| {51 for (expected_args) |arg| {
52 wtf8_buf.clearRetainingCapacity();52 wtf8_buf.clearRetainingCapacity();
53 try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(arg));53 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)});
55 }55 }
56 std.debug.print("}}\n", .{});56 std.debug.print("}}\n", .{});
57 return error.ArgvMismatch;57 return error.ArgvMismatch;
test/tests.zig+1-1
...@@ -2753,7 +2753,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {...@@ -2753,7 +2753,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
27532753
2754 run.addArg(b.graph.zig_exe);2754 run.addArg(b.graph.zig_exe);
2755 run.addFileArg(b.path("test/incremental/").path(b, entry.path));2755 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
2758 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });2758 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
27592759