authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-10 12:04:27+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-10 12:04:27+02:00
log1a998886c863a1829d649f196093f1058cd9cf13
treedb1b3b0a043a113cfb6544e8103cb64f8e4e4d8f
parent5b4b033236a7bed19c90faf7fefbc1990911cfef
parent10d6db5d7d1fb62ee2915a7ad2c7feb771ea3bbb
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24329 from ziglang/writergate

Deprecates all existing std.io readers and writers in favor of the newly provided std.io.Reader and std.io.Writer which are non-generic and have the buffer above the vtable - in other words the buffer is in the interface, not the implementation. This means that although Reader and Writer are no longer generic, they are still transparent to optimization; all of the interface functions have a concrete hot path operating on the buffer, and only make vtable calls when the buffer is full.

357 files changed, 16918 insertions(+), 15115 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
doc/langref.html.in+2-1
...@@ -374,7 +374,8 @@...@@ -374,7 +374,8 @@
374 <p>374 <p>
375 Most of the time, it is more appropriate to write to stderr rather than stdout, and375 Most of the time, it is more appropriate to write to stderr rather than stdout, and
376 whether or not the message is successfully written to the stream is irrelevant.376 whether or not the message is successfully written to the stream is irrelevant.
377 For this common case, there is a simpler API:377 Also, formatted printing often comes in handy. For this common case,
378 there is a simpler API:
378 </p>379 </p>
379 {#code|hello_again.zig#}380 {#code|hello_again.zig#}
380381
doc/langref/bad_default_value.zig+1-1
...@@ -17,7 +17,7 @@ pub fn main() !void {...@@ -17,7 +17,7 @@ pub fn main() !void {
17 .maximum = 0.20,17 .maximum = 0.20,
18 };18 };
19 const category = threshold.categorize(0.90);19 const category = threshold.categorize(0.90);
20 try std.io.getStdOut().writeAll(@tagName(category));20 try std.fs.File.stdout().writeAll(@tagName(category));
21}21}
2222
23const std = @import("std");23const std = @import("std");
doc/langref/hello.zig+1-2
...@@ -1,8 +1,7 @@...@@ -1,8 +1,7 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() !void {3pub fn main() !void {
4 const stdout = std.io.getStdOut().writer();4 try std.fs.File.stdout().writeAll("Hello, World!\n");
5 try stdout.print("Hello, {s}!\n", .{"world"});
6}5}
76
8// exe=succeed7// exe=succeed
doc/langref/hello_again.zig+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() void {3pub fn main() void {
4 std.debug.print("Hello, world!\n", .{});4 std.debug.print("Hello, {s}!\n", .{"World"});
5}5}
66
7// exe=succeed7// exe=succeed
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+19-29
...@@ -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");
...@@ -323,12 +324,13 @@ pub fn addExtra(...@@ -323,12 +324,13 @@ pub fn addExtra(
323324
324pub fn render(comp: *Compilation, config: std.io.tty.Config) void {325pub fn render(comp: *Compilation, config: std.io.tty.Config) void {
325 if (comp.diagnostics.list.items.len == 0) return;326 if (comp.diagnostics.list.items.len == 0) return;
326 var m = defaultMsgWriter(config);327 var buffer: [1000]u8 = undefined;
328 var m = defaultMsgWriter(config, &buffer);
327 defer m.deinit();329 defer m.deinit();
328 renderMessages(comp, &m);330 renderMessages(comp, &m);
329}331}
330pub fn defaultMsgWriter(config: std.io.tty.Config) MsgWriter {332pub fn defaultMsgWriter(config: std.io.tty.Config, buffer: []u8) MsgWriter {
331 return MsgWriter.init(config);333 return MsgWriter.init(config, buffer);
332}334}
333335
334pub fn renderMessages(comp: *Compilation, m: anytype) void {336pub fn renderMessages(comp: *Compilation, m: anytype) void {
...@@ -443,18 +445,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {...@@ -443,18 +445,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
443 printRt(m, prop.msg, .{"{s}"}, .{&str});445 printRt(m, prop.msg, .{"{s}"}, .{&str});
444 } else {446 } else {
445 var buf: [3]u8 = undefined;447 var buf: [3]u8 = undefined;
446 const str = std.fmt.bufPrint(&buf, "x{x}", .{std.fmt.fmtSliceHexLower(&.{msg.extra.invalid_escape.char})}) catch unreachable;448 const str = std.fmt.bufPrint(&buf, "x{x}", .{msg.extra.invalid_escape.char}) catch unreachable;
447 printRt(m, prop.msg, .{"{s}"}, .{str});449 printRt(m, prop.msg, .{"{s}"}, .{str});
448 }450 }
449 },451 },
450 .normalized => {452 .normalized => {
451 const f = struct {453 const f = struct {
452 pub fn f(454 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 = .{455 var it: std.unicode.Utf8Iterator = .{
459 .bytes = bytes,456 .bytes = bytes,
460 .i = 0,457 .i = 0,
...@@ -464,22 +461,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {...@@ -464,22 +461,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
464 try writer.writeByte(@intCast(codepoint));461 try writer.writeByte(@intCast(codepoint));
465 } else if (codepoint < 0xFFFF) {462 } else if (codepoint < 0xFFFF) {
466 try writer.writeAll("\\u");463 try writer.writeAll("\\u");
467 try std.fmt.formatInt(codepoint, 16, .upper, .{464 try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 4 });
468 .fill = '0',
469 .width = 4,
470 }, writer);
471 } else {465 } else {
472 try writer.writeAll("\\U");466 try writer.writeAll("\\U");
473 try std.fmt.formatInt(codepoint, 16, .upper, .{467 try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 8 });
474 .fill = '0',
475 .width = 8,
476 }, writer);
477 }468 }
478 }469 }
479 }470 }
480 }.f;471 }.f;
481 printRt(m, prop.msg, .{"{s}"}, .{472 printRt(m, prop.msg, .{"{f}"}, .{
482 std.fmt.Formatter(f){ .data = msg.extra.normalized },473 std.fmt.Formatter([]const u8, f){ .data = msg.extra.normalized },
483 });474 });
484 },475 },
485 .none, .offset => m.write(prop.msg),476 .none, .offset => m.write(prop.msg),
...@@ -535,32 +526,31 @@ fn tagKind(d: *Diagnostics, tag: Tag, langopts: LangOpts) Kind {...@@ -535,32 +526,31 @@ fn tagKind(d: *Diagnostics, tag: Tag, langopts: LangOpts) Kind {
535}526}
536527
537const MsgWriter = struct {528const MsgWriter = struct {
538 w: std.io.BufferedWriter(4096, std.fs.File.Writer),529 writer: *std.io.Writer,
539 config: std.io.tty.Config,530 config: std.io.tty.Config,
540531
541 fn init(config: std.io.tty.Config) MsgWriter {532 fn init(config: std.io.tty.Config, buffer: []u8) MsgWriter {
542 std.debug.lockStdErr();
543 return .{533 return .{
544 .w = std.io.bufferedWriter(std.io.getStdErr().writer()),534 .writer = std.debug.lockStderrWriter(buffer),
545 .config = config,535 .config = config,
546 };536 };
547 }537 }
548538
549 pub fn deinit(m: *MsgWriter) void {539 pub fn deinit(m: *MsgWriter) void {
550 m.w.flush() catch {};540 std.debug.unlockStderrWriter();
551 std.debug.unlockStdErr();541 m.* = undefined;
552 }542 }
553543
554 pub fn print(m: *MsgWriter, comptime fmt: []const u8, args: anytype) void {544 pub fn print(m: *MsgWriter, comptime fmt: []const u8, args: anytype) void {
555 m.w.writer().print(fmt, args) catch {};545 m.writer.print(fmt, args) catch {};
556 }546 }
557547
558 fn write(m: *MsgWriter, msg: []const u8) void {548 fn write(m: *MsgWriter, msg: []const u8) void {
559 m.w.writer().writeAll(msg) catch {};549 m.writer.writeAll(msg) catch {};
560 }550 }
561551
562 fn setColor(m: *MsgWriter, color: std.io.tty.Color) void {552 fn setColor(m: *MsgWriter, color: std.io.tty.Color) void {
563 m.config.setColor(m.w.writer(), color) catch {};553 m.config.setColor(m.writer, color) catch {};
564 }554 }
565555
566 fn location(m: *MsgWriter, path: []const u8, line: u32, col: u32) void {556 fn location(m: *MsgWriter, path: []const u8, line: u32, col: u32) void {
lib/compiler/aro/aro/Driver.zig+11-11
...@@ -519,7 +519,7 @@ fn option(arg: []const u8, name: []const u8) ?[]const u8 {...@@ -519,7 +519,7 @@ fn option(arg: []const u8, name: []const u8) ?[]const u8 {
519519
520fn addSource(d: *Driver, path: []const u8) !Source {520fn addSource(d: *Driver, path: []const u8) !Source {
521 if (mem.eql(u8, "-", path)) {521 if (mem.eql(u8, "-", path)) {
522 const stdin = std.io.getStdIn().reader();522 const stdin = std.fs.File.stdin().deprecatedReader();
523 const input = try stdin.readAllAlloc(d.comp.gpa, std.math.maxInt(u32));523 const input = try stdin.readAllAlloc(d.comp.gpa, std.math.maxInt(u32));
524 defer d.comp.gpa.free(input);524 defer d.comp.gpa.free(input);
525 return d.comp.addSourceFromBuffer("<stdin>", input);525 return d.comp.addSourceFromBuffer("<stdin>", input);
...@@ -541,7 +541,7 @@ pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{ FatalEr...@@ -541,7 +541,7 @@ pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{ FatalEr
541}541}
542542
543pub fn renderErrors(d: *Driver) void {543pub fn renderErrors(d: *Driver) void {
544 Diagnostics.render(d.comp, d.detectConfig(std.io.getStdErr()));544 Diagnostics.render(d.comp, d.detectConfig(std.fs.File.stderr()));
545}545}
546546
547pub fn detectConfig(d: *Driver, file: std.fs.File) std.io.tty.Config {547pub fn detectConfig(d: *Driver, file: std.fs.File) std.io.tty.Config {
...@@ -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.io.getStdOut().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);
...@@ -686,10 +686,10 @@ fn processSource(...@@ -686,10 +686,10 @@ fn processSource(
686 std.fs.cwd().createFile(some, .{}) catch |er|686 std.fs.cwd().createFile(some, .{}) catch |er|
687 return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) })687 return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) })
688 else688 else
689 std.io.getStdOut();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)});
...@@ -704,8 +704,8 @@ fn processSource(...@@ -704,8 +704,8 @@ fn processSource(
704 defer tree.deinit();704 defer tree.deinit();
705705
706 if (d.verbose_ast) {706 if (d.verbose_ast) {
707 const stdout = std.io.getStdOut();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 }
...@@ -734,8 +734,8 @@ fn processSource(...@@ -734,8 +734,8 @@ fn processSource(
734 defer ir.deinit(d.comp.gpa);734 defer ir.deinit(d.comp.gpa);
735735
736 if (d.verbose_ir) {736 if (d.verbose_ir) {
737 const stdout = std.io.getStdOut();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.io.getStdOut().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.io.getStdErr().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.printInt(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+2-2
...@@ -961,7 +961,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w...@@ -961,7 +961,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w
961 switch (key) {961 switch (key) {
962 .null => return w.writeAll("nullptr_t"),962 .null => return w.writeAll("nullptr_t"),
963 .int => |repr| switch (repr) {963 .int => |repr| switch (repr) {
964 inline else => |x| return w.print("{d}", .{x}),964 inline .u64, .i64, .big_int => |x| return w.print("{d}", .{x}),
965 },965 },
966 .float => |repr| switch (repr) {966 .float => |repr| switch (repr) {
967 .f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}),967 .f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}),
...@@ -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.zig+3-2
...@@ -1781,7 +1781,8 @@ test "Macro matching" {...@@ -1781,7 +1781,8 @@ test "Macro matching" {
1781fn renderErrorsAndExit(comp: *aro.Compilation) noreturn {1781fn renderErrorsAndExit(comp: *aro.Compilation) noreturn {
1782 defer std.process.exit(1);1782 defer std.process.exit(1);
17831783
1784 var writer = aro.Diagnostics.defaultMsgWriter(std.io.tty.detectConfig(std.io.getStdErr()));1784 var buffer: [1000]u8 = undefined;
1785 var writer = aro.Diagnostics.defaultMsgWriter(std.io.tty.detectConfig(std.fs.File.stderr()), &buffer);
1785 defer writer.deinit(); // writer deinit must run *before* exit so that stderr is flushed1786 defer writer.deinit(); // writer deinit must run *before* exit so that stderr is flushed
17861787
1787 var saw_error = false;1788 var saw_error = false;
...@@ -1824,6 +1825,6 @@ pub fn main() !void {...@@ -1824,6 +1825,6 @@ pub fn main() !void {
1824 defer tree.deinit(gpa);1825 defer tree.deinit(gpa);
18251826
1826 const formatted = try tree.render(arena);1827 const formatted = try tree.render(arena);
1827 try std.io.getStdOut().writeAll(formatted);1828 try std.fs.File.stdout().writeAll(formatted);
1828 return std.process.cleanExit();1829 return std.process.cleanExit();
1829}1830}
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+82-67
...@@ -12,6 +12,7 @@ const Watch = std.Build.Watch;...@@ -12,6 +12,7 @@ const Watch = std.Build.Watch;
12const Fuzz = std.Build.Fuzz;12const Fuzz = std.Build.Fuzz;
13const Allocator = std.mem.Allocator;13const Allocator = std.mem.Allocator;
14const fatal = std.process.fatal;14const fatal = std.process.fatal;
15const Writer = std.io.Writer;
15const runner = @This();16const runner = @This();
1617
17pub const root = @import("@build");18pub const root = @import("@build");
...@@ -330,7 +331,7 @@ pub fn main() !void {...@@ -330,7 +331,7 @@ pub fn main() !void {
330 }331 }
331 }332 }
332333
333 const stderr = std.io.getStdErr();334 const stderr: std.fs.File = .stderr();
334 const ttyconf = get_tty_conf(color, stderr);335 const ttyconf = get_tty_conf(color, stderr);
335 switch (ttyconf) {336 switch (ttyconf) {
336 .no_color => try graph.env_map.put("NO_COLOR", "1"),337 .no_color => try graph.env_map.put("NO_COLOR", "1"),
...@@ -365,7 +366,7 @@ pub fn main() !void {...@@ -365,7 +366,7 @@ pub fn main() !void {
365 .data = buffer.items,366 .data = buffer.items,
366 .flags = .{ .exclusive = true },367 .flags = .{ .exclusive = true },
367 }) catch |err| {368 }) catch |err| {
368 fatal("unable to write configuration results to '{}{s}': {s}", .{369 fatal("unable to write configuration results to '{f}{s}': {s}", .{
369 local_cache_directory, tmp_sub_path, @errorName(err),370 local_cache_directory, tmp_sub_path, @errorName(err),
370 });371 });
371 };372 };
...@@ -378,13 +379,19 @@ pub fn main() !void {...@@ -378,13 +379,19 @@ pub fn main() !void {
378379
379 validateSystemLibraryOptions(builder);380 validateSystemLibraryOptions(builder);
380381
381 const stdout_writer = io.getStdOut().writer();382 if (help_menu) {
382383 var w = initStdoutWriter();
383 if (help_menu)384 printUsage(builder, w) catch return stdout_writer_allocation.err.?;
384 return usage(builder, stdout_writer);385 w.flush() catch return stdout_writer_allocation.err.?;
386 return;
387 }
385388
386 if (steps_menu)389 if (steps_menu) {
387 return steps(builder, stdout_writer);390 var w = initStdoutWriter();
391 printSteps(builder, w) catch return stdout_writer_allocation.err.?;
392 w.flush() catch return stdout_writer_allocation.err.?;
393 return;
394 }
388395
389 var run: Run = .{396 var run: Run = .{
390 .max_rss = max_rss,397 .max_rss = max_rss,
...@@ -696,24 +703,23 @@ fn runStepNames(...@@ -696,24 +703,23 @@ fn runStepNames(
696 const ttyconf = run.ttyconf;703 const ttyconf = run.ttyconf;
697704
698 if (run.summary != .none) {705 if (run.summary != .none) {
699 std.debug.lockStdErr();706 const w = std.debug.lockStderrWriter(&stdio_buffer_allocation);
700 defer std.debug.unlockStdErr();707 defer std.debug.unlockStderrWriter();
701 const stderr = run.stderr;
702708
703 const total_count = success_count + failure_count + pending_count + skipped_count;709 const total_count = success_count + failure_count + pending_count + skipped_count;
704 ttyconf.setColor(stderr, .cyan) catch {};710 ttyconf.setColor(w, .cyan) catch {};
705 stderr.writeAll("Build Summary:") catch {};711 w.writeAll("Build Summary:") catch {};
706 ttyconf.setColor(stderr, .reset) catch {};712 ttyconf.setColor(w, .reset) catch {};
707 stderr.writer().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};713 w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
708 if (skipped_count > 0) stderr.writer().print("; {d} skipped", .{skipped_count}) catch {};714 if (skipped_count > 0) w.print("; {d} skipped", .{skipped_count}) catch {};
709 if (failure_count > 0) stderr.writer().print("; {d} failed", .{failure_count}) catch {};715 if (failure_count > 0) w.print("; {d} failed", .{failure_count}) catch {};
710716
711 if (test_count > 0) stderr.writer().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};717 if (test_count > 0) w.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 {};718 if (test_skip_count > 0) w.print("; {d} skipped", .{test_skip_count}) catch {};
713 if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};719 if (test_fail_count > 0) w.print("; {d} failed", .{test_fail_count}) catch {};
714 if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};720 if (test_leak_count > 0) w.print("; {d} leaked", .{test_leak_count}) catch {};
715721
716 stderr.writeAll("\n") catch {};722 w.writeAll("\n") catch {};
717723
718 // Print a fancy tree with build results.724 // Print a fancy tree with build results.
719 var step_stack_copy = try step_stack.clone(gpa);725 var step_stack_copy = try step_stack.clone(gpa);
...@@ -722,7 +728,7 @@ fn runStepNames(...@@ -722,7 +728,7 @@ fn runStepNames(
722 var print_node: PrintNode = .{ .parent = null };728 var print_node: PrintNode = .{ .parent = null };
723 if (step_names.len == 0) {729 if (step_names.len == 0) {
724 print_node.last = true;730 print_node.last = true;
725 printTreeStep(b, b.default_step, run, stderr, ttyconf, &print_node, &step_stack_copy) catch {};731 printTreeStep(b, b.default_step, run, w, ttyconf, &print_node, &step_stack_copy) catch {};
726 } else {732 } else {
727 const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: {733 const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: {
728 var i: usize = step_names.len;734 var i: usize = step_names.len;
...@@ -741,9 +747,10 @@ fn runStepNames(...@@ -741,9 +747,10 @@ fn runStepNames(
741 for (step_names, 0..) |step_name, i| {747 for (step_names, 0..) |step_name, i| {
742 const tls = b.top_level_steps.get(step_name).?;748 const tls = b.top_level_steps.get(step_name).?;
743 print_node.last = i + 1 == last_index;749 print_node.last = i + 1 == last_index;
744 printTreeStep(b, &tls.step, run, stderr, ttyconf, &print_node, &step_stack_copy) catch {};750 printTreeStep(b, &tls.step, run, w, ttyconf, &print_node, &step_stack_copy) catch {};
745 }751 }
746 }752 }
753 w.writeByte('\n') catch {};
747 }754 }
748755
749 if (failure_count == 0) {756 if (failure_count == 0) {
...@@ -775,7 +782,7 @@ const PrintNode = struct {...@@ -775,7 +782,7 @@ const PrintNode = struct {
775 last: bool = false,782 last: bool = false,
776};783};
777784
778fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void {785fn printPrefix(node: *PrintNode, stderr: *Writer, ttyconf: std.io.tty.Config) !void {
779 const parent = node.parent orelse return;786 const parent = node.parent orelse return;
780 if (parent.parent == null) return;787 if (parent.parent == null) return;
781 try printPrefix(parent, stderr, ttyconf);788 try printPrefix(parent, stderr, ttyconf);
...@@ -789,7 +796,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void...@@ -789,7 +796,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void
789 }796 }
790}797}
791798
792fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void {799fn printChildNodePrefix(stderr: *Writer, ttyconf: std.io.tty.Config) !void {
793 try stderr.writeAll(switch (ttyconf) {800 try stderr.writeAll(switch (ttyconf) {
794 .no_color, .windows_api => "+- ",801 .no_color, .windows_api => "+- ",
795 .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─802 .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─
...@@ -798,7 +805,7 @@ fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void {...@@ -798,7 +805,7 @@ fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void {
798805
799fn printStepStatus(806fn printStepStatus(
800 s: *Step,807 s: *Step,
801 stderr: File,808 stderr: *Writer,
802 ttyconf: std.io.tty.Config,809 ttyconf: std.io.tty.Config,
803 run: *const Run,810 run: *const Run,
804) !void {811) !void {
...@@ -820,10 +827,10 @@ fn printStepStatus(...@@ -820,10 +827,10 @@ fn printStepStatus(
820 try stderr.writeAll(" cached");827 try stderr.writeAll(" cached");
821 } else if (s.test_results.test_count > 0) {828 } else if (s.test_results.test_count > 0) {
822 const pass_count = s.test_results.passCount();829 const pass_count = s.test_results.passCount();
823 try stderr.writer().print(" {d} passed", .{pass_count});830 try stderr.print(" {d} passed", .{pass_count});
824 if (s.test_results.skip_count > 0) {831 if (s.test_results.skip_count > 0) {
825 try ttyconf.setColor(stderr, .yellow);832 try ttyconf.setColor(stderr, .yellow);
826 try stderr.writer().print(" {d} skipped", .{s.test_results.skip_count});833 try stderr.print(" {d} skipped", .{s.test_results.skip_count});
827 }834 }
828 } else {835 } else {
829 try stderr.writeAll(" success");836 try stderr.writeAll(" success");
...@@ -832,15 +839,15 @@ fn printStepStatus(...@@ -832,15 +839,15 @@ fn printStepStatus(
832 if (s.result_duration_ns) |ns| {839 if (s.result_duration_ns) |ns| {
833 try ttyconf.setColor(stderr, .dim);840 try ttyconf.setColor(stderr, .dim);
834 if (ns >= std.time.ns_per_min) {841 if (ns >= std.time.ns_per_min) {
835 try stderr.writer().print(" {d}m", .{ns / std.time.ns_per_min});842 try stderr.print(" {d}m", .{ns / std.time.ns_per_min});
836 } else if (ns >= std.time.ns_per_s) {843 } else if (ns >= std.time.ns_per_s) {
837 try stderr.writer().print(" {d}s", .{ns / std.time.ns_per_s});844 try stderr.print(" {d}s", .{ns / std.time.ns_per_s});
838 } else if (ns >= std.time.ns_per_ms) {845 } else if (ns >= std.time.ns_per_ms) {
839 try stderr.writer().print(" {d}ms", .{ns / std.time.ns_per_ms});846 try stderr.print(" {d}ms", .{ns / std.time.ns_per_ms});
840 } else if (ns >= std.time.ns_per_us) {847 } else if (ns >= std.time.ns_per_us) {
841 try stderr.writer().print(" {d}us", .{ns / std.time.ns_per_us});848 try stderr.print(" {d}us", .{ns / std.time.ns_per_us});
842 } else {849 } else {
843 try stderr.writer().print(" {d}ns", .{ns});850 try stderr.print(" {d}ns", .{ns});
844 }851 }
845 try ttyconf.setColor(stderr, .reset);852 try ttyconf.setColor(stderr, .reset);
846 }853 }
...@@ -848,13 +855,13 @@ fn printStepStatus(...@@ -848,13 +855,13 @@ fn printStepStatus(
848 const rss = s.result_peak_rss;855 const rss = s.result_peak_rss;
849 try ttyconf.setColor(stderr, .dim);856 try ttyconf.setColor(stderr, .dim);
850 if (rss >= 1000_000_000) {857 if (rss >= 1000_000_000) {
851 try stderr.writer().print(" MaxRSS:{d}G", .{rss / 1000_000_000});858 try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000});
852 } else if (rss >= 1000_000) {859 } else if (rss >= 1000_000) {
853 try stderr.writer().print(" MaxRSS:{d}M", .{rss / 1000_000});860 try stderr.print(" MaxRSS:{d}M", .{rss / 1000_000});
854 } else if (rss >= 1000) {861 } else if (rss >= 1000) {
855 try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000});862 try stderr.print(" MaxRSS:{d}K", .{rss / 1000});
856 } else {863 } else {
857 try stderr.writer().print(" MaxRSS:{d}B", .{rss});864 try stderr.print(" MaxRSS:{d}B", .{rss});
858 }865 }
859 try ttyconf.setColor(stderr, .reset);866 try ttyconf.setColor(stderr, .reset);
860 }867 }
...@@ -866,7 +873,7 @@ fn printStepStatus(...@@ -866,7 +873,7 @@ fn printStepStatus(
866 if (skip == .skipped_oom) {873 if (skip == .skipped_oom) {
867 try stderr.writeAll(" (not enough memory)");874 try stderr.writeAll(" (not enough memory)");
868 try ttyconf.setColor(stderr, .dim);875 try ttyconf.setColor(stderr, .dim);
869 try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });876 try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
870 try ttyconf.setColor(stderr, .yellow);877 try ttyconf.setColor(stderr, .yellow);
871 }878 }
872 try stderr.writeAll("\n");879 try stderr.writeAll("\n");
...@@ -878,23 +885,23 @@ fn printStepStatus(...@@ -878,23 +885,23 @@ fn printStepStatus(
878885
879fn printStepFailure(886fn printStepFailure(
880 s: *Step,887 s: *Step,
881 stderr: File,888 stderr: *Writer,
882 ttyconf: std.io.tty.Config,889 ttyconf: std.io.tty.Config,
883) !void {890) !void {
884 if (s.result_error_bundle.errorMessageCount() > 0) {891 if (s.result_error_bundle.errorMessageCount() > 0) {
885 try ttyconf.setColor(stderr, .red);892 try ttyconf.setColor(stderr, .red);
886 try stderr.writer().print(" {d} errors\n", .{893 try stderr.print(" {d} errors\n", .{
887 s.result_error_bundle.errorMessageCount(),894 s.result_error_bundle.errorMessageCount(),
888 });895 });
889 try ttyconf.setColor(stderr, .reset);896 try ttyconf.setColor(stderr, .reset);
890 } else if (!s.test_results.isSuccess()) {897 } else if (!s.test_results.isSuccess()) {
891 try stderr.writer().print(" {d}/{d} passed", .{898 try stderr.print(" {d}/{d} passed", .{
892 s.test_results.passCount(), s.test_results.test_count,899 s.test_results.passCount(), s.test_results.test_count,
893 });900 });
894 if (s.test_results.fail_count > 0) {901 if (s.test_results.fail_count > 0) {
895 try stderr.writeAll(", ");902 try stderr.writeAll(", ");
896 try ttyconf.setColor(stderr, .red);903 try ttyconf.setColor(stderr, .red);
897 try stderr.writer().print("{d} failed", .{904 try stderr.print("{d} failed", .{
898 s.test_results.fail_count,905 s.test_results.fail_count,
899 });906 });
900 try ttyconf.setColor(stderr, .reset);907 try ttyconf.setColor(stderr, .reset);
...@@ -902,7 +909,7 @@ fn printStepFailure(...@@ -902,7 +909,7 @@ fn printStepFailure(
902 if (s.test_results.skip_count > 0) {909 if (s.test_results.skip_count > 0) {
903 try stderr.writeAll(", ");910 try stderr.writeAll(", ");
904 try ttyconf.setColor(stderr, .yellow);911 try ttyconf.setColor(stderr, .yellow);
905 try stderr.writer().print("{d} skipped", .{912 try stderr.print("{d} skipped", .{
906 s.test_results.skip_count,913 s.test_results.skip_count,
907 });914 });
908 try ttyconf.setColor(stderr, .reset);915 try ttyconf.setColor(stderr, .reset);
...@@ -910,7 +917,7 @@ fn printStepFailure(...@@ -910,7 +917,7 @@ fn printStepFailure(
910 if (s.test_results.leak_count > 0) {917 if (s.test_results.leak_count > 0) {
911 try stderr.writeAll(", ");918 try stderr.writeAll(", ");
912 try ttyconf.setColor(stderr, .red);919 try ttyconf.setColor(stderr, .red);
913 try stderr.writer().print("{d} leaked", .{920 try stderr.print("{d} leaked", .{
914 s.test_results.leak_count,921 s.test_results.leak_count,
915 });922 });
916 try ttyconf.setColor(stderr, .reset);923 try ttyconf.setColor(stderr, .reset);
...@@ -932,7 +939,7 @@ fn printTreeStep(...@@ -932,7 +939,7 @@ fn printTreeStep(
932 b: *std.Build,939 b: *std.Build,
933 s: *Step,940 s: *Step,
934 run: *const Run,941 run: *const Run,
935 stderr: File,942 stderr: *Writer,
936 ttyconf: std.io.tty.Config,943 ttyconf: std.io.tty.Config,
937 parent_node: *PrintNode,944 parent_node: *PrintNode,
938 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),945 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
...@@ -992,7 +999,7 @@ fn printTreeStep(...@@ -992,7 +999,7 @@ fn printTreeStep(
992 if (s.dependencies.items.len == 0) {999 if (s.dependencies.items.len == 0) {
993 try stderr.writeAll(" (reused)\n");1000 try stderr.writeAll(" (reused)\n");
994 } else {1001 } else {
995 try stderr.writer().print(" (+{d} more reused dependencies)\n", .{1002 try stderr.print(" (+{d} more reused dependencies)\n", .{
996 s.dependencies.items.len,1003 s.dependencies.items.len,
997 });1004 });
998 }1005 }
...@@ -1129,11 +1136,11 @@ fn workerMakeOneStep(...@@ -1129,11 +1136,11 @@ fn workerMakeOneStep(
1129 const show_stderr = s.result_stderr.len > 0;1136 const show_stderr = s.result_stderr.len > 0;
11301137
1131 if (show_error_msgs or show_compile_errors or show_stderr) {1138 if (show_error_msgs or show_compile_errors or show_stderr) {
1132 std.debug.lockStdErr();1139 const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation);
1133 defer std.debug.unlockStdErr();1140 defer std.debug.unlockStderrWriter();
11341141
1135 const gpa = b.allocator;1142 const gpa = b.allocator;
1136 printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, run.stderr, run.prominent_compile_errors) catch {};1143 printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.prominent_compile_errors) catch {};
1137 }1144 }
11381145
1139 handle_result: {1146 handle_result: {
...@@ -1190,7 +1197,7 @@ pub fn printErrorMessages(...@@ -1190,7 +1197,7 @@ pub fn printErrorMessages(
1190 gpa: Allocator,1197 gpa: Allocator,
1191 failing_step: *Step,1198 failing_step: *Step,
1192 options: std.zig.ErrorBundle.RenderOptions,1199 options: std.zig.ErrorBundle.RenderOptions,
1193 stderr: File,1200 stderr: *Writer,
1194 prominent_compile_errors: bool,1201 prominent_compile_errors: bool,
1195) !void {1202) !void {
1196 // Provide context for where these error messages are coming from by1203 // Provide context for where these error messages are coming from by
...@@ -1209,7 +1216,7 @@ pub fn printErrorMessages(...@@ -1209,7 +1216,7 @@ pub fn printErrorMessages(
1209 var indent: usize = 0;1216 var indent: usize = 0;
1210 while (step_stack.pop()) |s| : (indent += 1) {1217 while (step_stack.pop()) |s| : (indent += 1) {
1211 if (indent > 0) {1218 if (indent > 0) {
1212 try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3);1219 try stderr.splatByteAll(' ', (indent - 1) * 3);
1213 try printChildNodePrefix(stderr, ttyconf);1220 try printChildNodePrefix(stderr, ttyconf);
1214 }1221 }
12151222
...@@ -1231,7 +1238,7 @@ pub fn printErrorMessages(...@@ -1231,7 +1238,7 @@ pub fn printErrorMessages(
1231 }1238 }
12321239
1233 if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {1240 if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {
1234 try failing_step.result_error_bundle.renderToWriter(options, stderr.writer());1241 try failing_step.result_error_bundle.renderToWriter(options, stderr);
1235 }1242 }
12361243
1237 for (failing_step.result_error_msgs.items) |msg| {1244 for (failing_step.result_error_msgs.items) |msg| {
...@@ -1243,27 +1250,27 @@ pub fn printErrorMessages(...@@ -1243,27 +1250,27 @@ pub fn printErrorMessages(
1243 }1250 }
1244}1251}
12451252
1246fn steps(builder: *std.Build, out_stream: anytype) !void {1253fn printSteps(builder: *std.Build, w: *Writer) !void {
1247 const allocator = builder.allocator;1254 const allocator = builder.allocator;
1248 for (builder.top_level_steps.values()) |top_level_step| {1255 for (builder.top_level_steps.values()) |top_level_step| {
1249 const name = if (&top_level_step.step == builder.default_step)1256 const name = if (&top_level_step.step == builder.default_step)
1250 try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})1257 try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})
1251 else1258 else
1252 top_level_step.step.name;1259 top_level_step.step.name;
1253 try out_stream.print(" {s:<28} {s}\n", .{ name, top_level_step.description });1260 try w.print(" {s:<28} {s}\n", .{ name, top_level_step.description });
1254 }1261 }
1255}1262}
12561263
1257fn usage(b: *std.Build, out_stream: anytype) !void {1264fn printUsage(b: *std.Build, w: *Writer) !void {
1258 try out_stream.print(1265 try w.print(
1259 \\Usage: {s} build [steps] [options]1266 \\Usage: {s} build [steps] [options]
1260 \\1267 \\
1261 \\Steps:1268 \\Steps:
1262 \\1269 \\
1263 , .{b.graph.zig_exe});1270 , .{b.graph.zig_exe});
1264 try steps(b, out_stream);1271 try printSteps(b, w);
12651272
1266 try out_stream.writeAll(1273 try w.writeAll(
1267 \\1274 \\
1268 \\General Options:1275 \\General Options:
1269 \\ -p, --prefix [path] Where to install files (default: zig-out)1276 \\ -p, --prefix [path] Where to install files (default: zig-out)
...@@ -1319,25 +1326,25 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1319,25 +1326,25 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
13191326
1320 const arena = b.allocator;1327 const arena = b.allocator;
1321 if (b.available_options_list.items.len == 0) {1328 if (b.available_options_list.items.len == 0) {
1322 try out_stream.print(" (none)\n", .{});1329 try w.print(" (none)\n", .{});
1323 } else {1330 } else {
1324 for (b.available_options_list.items) |option| {1331 for (b.available_options_list.items) |option| {
1325 const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{1332 const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{
1326 option.name,1333 option.name,
1327 @tagName(option.type_id),1334 @tagName(option.type_id),
1328 });1335 });
1329 try out_stream.print("{s:<30} {s}\n", .{ name, option.description });1336 try w.print("{s:<30} {s}\n", .{ name, option.description });
1330 if (option.enum_options) |enum_options| {1337 if (option.enum_options) |enum_options| {
1331 const padding = " " ** 33;1338 const padding = " " ** 33;
1332 try out_stream.writeAll(padding ++ "Supported Values:\n");1339 try w.writeAll(padding ++ "Supported Values:\n");
1333 for (enum_options) |enum_option| {1340 for (enum_options) |enum_option| {
1334 try out_stream.print(padding ++ " {s}\n", .{enum_option});1341 try w.print(padding ++ " {s}\n", .{enum_option});
1335 }1342 }
1336 }1343 }
1337 }1344 }
1338 }1345 }
13391346
1340 try out_stream.writeAll(1347 try w.writeAll(
1341 \\1348 \\
1342 \\System Integration Options:1349 \\System Integration Options:
1343 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers1350 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
...@@ -1352,7 +1359,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1352,7 +1359,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1352 \\1359 \\
1353 );1360 );
1354 if (b.graph.system_library_options.entries.len == 0) {1361 if (b.graph.system_library_options.entries.len == 0) {
1355 try out_stream.writeAll(" (none) -\n");1362 try w.writeAll(" (none) -\n");
1356 } else {1363 } else {
1357 for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| {1364 for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| {
1358 const status = switch (v) {1365 const status = switch (v) {
...@@ -1360,11 +1367,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1360,11 +1367,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1360 .declared_disabled => "no",1367 .declared_disabled => "no",
1361 .user_enabled, .user_disabled => unreachable, // already emitted error1368 .user_enabled, .user_disabled => unreachable, // already emitted error
1362 };1369 };
1363 try out_stream.print(" {s:<43} {s}\n", .{ k, status });1370 try w.print(" {s:<43} {s}\n", .{ k, status });
1364 }1371 }
1365 }1372 }
13661373
1367 try out_stream.writeAll(1374 try w.writeAll(
1368 \\1375 \\
1369 \\Advanced Options:1376 \\Advanced Options:
1370 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error1377 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
...@@ -1544,3 +1551,11 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {...@@ -1544,3 +1551,11 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {
1544 };1551 };
1545 }1552 }
1546}1553}
1554
1555var stdio_buffer_allocation: [256]u8 = undefined;
1556var stdout_writer_allocation: std.fs.File.Writer = undefined;
1557
1558fn initStdoutWriter() *Writer {
1559 stdout_writer_allocation = std.fs.File.stdout().writerStreaming(&stdio_buffer_allocation);
1560 return &stdout_writer_allocation.interface;
1561}
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.io.getStdOut().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.io.getStdOut().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.io.getStdOut().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+6-6
...@@ -54,7 +54,7 @@ fn cmdObjCopy(...@@ -54,7 +54,7 @@ fn cmdObjCopy(
54 fatal("unexpected positional argument: '{s}'", .{arg});54 fatal("unexpected positional argument: '{s}'", .{arg});
55 }55 }
56 } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {56 } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
57 return std.io.getStdOut().writeAll(usage);57 return std.fs.File.stdout().writeAll(usage);
58 } else if (mem.eql(u8, arg, "-O") or mem.eql(u8, arg, "--output-target")) {58 } else if (mem.eql(u8, arg, "-O") or mem.eql(u8, arg, "--output-target")) {
59 i += 1;59 i += 1;
60 if (i >= args.len) fatal("expected another argument after '{s}'", .{arg});60 if (i >= args.len) fatal("expected another argument after '{s}'", .{arg});
...@@ -227,8 +227,8 @@ fn cmdObjCopy(...@@ -227,8 +227,8 @@ fn cmdObjCopy(
227 if (listen) {227 if (listen) {
228 var server = try Server.init(.{228 var server = try Server.init(.{
229 .gpa = gpa,229 .gpa = gpa,
230 .in = std.io.getStdIn(),230 .in = .stdin(),
231 .out = std.io.getStdOut(),231 .out = .stdout(),
232 .zig_version = builtin.zig_version_string,232 .zig_version = builtin.zig_version_string,
233 });233 });
234 defer server.deinit();234 defer server.deinit();
...@@ -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.io.getStdOut().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+13-14
...@@ -125,13 +125,12 @@ pub const Diagnostics = struct {...@@ -125,13 +125,12 @@ pub const Diagnostics = struct {
125 }125 }
126126
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 const stderr = std.debug.lockStderrWriter(&.{});
129 defer std.debug.unlockStdErr();129 defer std.debug.unlockStderrWriter();
130 const stderr = std.io.getStdErr().writer();
131 self.renderToWriter(args, stderr, config) catch return;130 self.renderToWriter(args, stderr, config) catch return;
132 }131 }
133132
134 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: anytype, config: std.io.tty.Config) !void {133 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.io.Writer, config: std.io.tty.Config) !void {
135 for (self.errors.items) |err_details| {134 for (self.errors.items) |err_details| {
136 try renderErrorMessage(writer, config, err_details, args);135 try renderErrorMessage(writer, config, err_details, args);
137 }136 }
...@@ -1403,7 +1402,7 @@ test parsePercent {...@@ -1403,7 +1402,7 @@ test parsePercent {
1403 try std.testing.expectError(error.InvalidFormat, parsePercent("~1"));1402 try std.testing.expectError(error.InvalidFormat, parsePercent("~1"));
1404}1403}
14051404
1406pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void {1405pub fn renderErrorMessage(writer: *std.io.Writer, config: std.io.tty.Config, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void {
1407 try config.setColor(writer, .dim);1406 try config.setColor(writer, .dim);
1408 try writer.writeAll("<cli>");1407 try writer.writeAll("<cli>");
1409 try config.setColor(writer, .reset);1408 try config.setColor(writer, .reset);
...@@ -1481,27 +1480,27 @@ pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, err_detail...@@ -1481,27 +1480,27 @@ pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, err_detail
1481 try writer.writeByte('\n');1480 try writer.writeByte('\n');
14821481
1483 try config.setColor(writer, .green);1482 try config.setColor(writer, .green);
1484 try writer.writeByteNTimes(' ', prefix.len);1483 try writer.splatByteAll(' ', prefix.len);
1485 // Special case for when the option is *only* a prefix (e.g. invalid option: -)1484 // Special case for when the option is *only* a prefix (e.g. invalid option: -)
1486 if (err_details.arg_span.prefix_len == arg_with_name.len) {1485 if (err_details.arg_span.prefix_len == arg_with_name.len) {
1487 try writer.writeByteNTimes('^', err_details.arg_span.prefix_len);1486 try writer.splatByteAll('^', err_details.arg_span.prefix_len);
1488 } else {1487 } else {
1489 try writer.writeByteNTimes('~', err_details.arg_span.prefix_len);1488 try writer.splatByteAll('~', err_details.arg_span.prefix_len);
1490 try writer.writeByteNTimes(' ', err_details.arg_span.name_offset - err_details.arg_span.prefix_len);1489 try writer.splatByteAll(' ', err_details.arg_span.name_offset - err_details.arg_span.prefix_len);
1491 if (!err_details.arg_span.point_at_next_arg and err_details.arg_span.value_offset == 0) {1490 if (!err_details.arg_span.point_at_next_arg and err_details.arg_span.value_offset == 0) {
1492 try writer.writeByte('^');1491 try writer.writeByte('^');
1493 try writer.writeByteNTimes('~', name_slice.len - 1);1492 try writer.splatByteAll('~', name_slice.len - 1);
1494 } else if (err_details.arg_span.value_offset > 0) {1493 } else if (err_details.arg_span.value_offset > 0) {
1495 try writer.writeByteNTimes('~', err_details.arg_span.value_offset - err_details.arg_span.name_offset);1494 try writer.splatByteAll('~', err_details.arg_span.value_offset - err_details.arg_span.name_offset);
1496 try writer.writeByte('^');1495 try writer.writeByte('^');
1497 if (err_details.arg_span.value_offset < arg_with_name.len) {1496 if (err_details.arg_span.value_offset < arg_with_name.len) {
1498 try writer.writeByteNTimes('~', arg_with_name.len - err_details.arg_span.value_offset - 1);1497 try writer.splatByteAll('~', arg_with_name.len - err_details.arg_span.value_offset - 1);
1499 }1498 }
1500 } else if (err_details.arg_span.point_at_next_arg) {1499 } else if (err_details.arg_span.point_at_next_arg) {
1501 try writer.writeByteNTimes('~', arg_with_name.len - err_details.arg_span.name_offset + 1);1500 try writer.splatByteAll('~', arg_with_name.len - err_details.arg_span.name_offset + 1);
1502 try writer.writeByte('^');1501 try writer.writeByte('^');
1503 if (next_arg_len > 0) {1502 if (next_arg_len > 0) {
1504 try writer.writeByteNTimes('~', next_arg_len - 1);1503 try writer.splatByteAll('~', next_arg_len - 1);
1505 }1504 }
1506 }1505 }
1507 }1506 }
lib/compiler/resinator/compile.zig+11-11
...@@ -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(
...@@ -2949,7 +2949,7 @@ pub fn HeaderSlurpingReader(comptime size: usize, comptime ReaderType: anytype)...@@ -2949,7 +2949,7 @@ pub fn HeaderSlurpingReader(comptime size: usize, comptime ReaderType: anytype)
2949 slurped_header: [size]u8 = [_]u8{0x00} ** size,2949 slurped_header: [size]u8 = [_]u8{0x00} ** size,
29502950
2951 pub const Error = ReaderType.Error;2951 pub const Error = ReaderType.Error;
2952 pub const Reader = std.io.Reader(*@This(), Error, read);2952 pub const Reader = std.io.GenericReader(*@This(), Error, read);
29532953
2954 pub fn read(self: *@This(), buf: []u8) Error!usize {2954 pub fn read(self: *@This(), buf: []u8) Error!usize {
2955 const amt = try self.child_reader.read(buf);2955 const amt = try self.child_reader.read(buf);
...@@ -2983,7 +2983,7 @@ pub fn LimitedWriter(comptime WriterType: type) type {...@@ -2983,7 +2983,7 @@ pub fn LimitedWriter(comptime WriterType: type) type {
2983 bytes_left: u64,2983 bytes_left: u64,
29842984
2985 pub const Error = error{NoSpaceLeft} || WriterType.Error;2985 pub const Error = error{NoSpaceLeft} || WriterType.Error;
2986 pub const Writer = std.io.Writer(*Self, Error, write);2986 pub const Writer = std.io.GenericWriter(*Self, Error, write);
29872987
2988 const Self = @This();2988 const Self = @This();
29892989
lib/compiler/resinator/errors.zig+29-33
...@@ -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");
...@@ -61,16 +62,15 @@ pub const Diagnostics = struct {...@@ -61,16 +62,15 @@ pub const Diagnostics = struct {
61 }62 }
6263
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 const stderr = std.debug.lockStderrWriter(&.{});
65 defer std.debug.unlockStdErr();66 defer std.debug.unlockStderrWriter();
66 const stderr = std.io.getStdErr().writer();
67 for (self.errors.items) |err_details| {67 for (self.errors.items) |err_details| {
68 renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;68 renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
69 }69 }
70 }70 }
7171
72 pub fn renderToStdErrDetectTTY(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void {72 pub fn renderToStdErrDetectTTY(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
73 const tty_config = std.io.tty.detectConfig(std.io.getStdErr());73 const tty_config = std.io.tty.detectConfig(std.fs.File.stderr());
74 return self.renderToStdErr(cwd, source, tty_config, source_mappings);74 return self.renderToStdErr(cwd, source, tty_config, source_mappings);
75 }75 }
7676
...@@ -409,15 +409,7 @@ pub const ErrorDetails = struct {...@@ -409,15 +409,7 @@ pub const ErrorDetails = struct {
409 failed_to_open_cwd,409 failed_to_open_cwd,
410 };410 };
411411
412 fn formatToken(412 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) {413 switch (ctx.token.id) {
422 .eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),414 .eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),
423 else => {},415 else => {},
...@@ -441,7 +433,7 @@ pub const ErrorDetails = struct {...@@ -441,7 +433,7 @@ pub const ErrorDetails = struct {
441 code_page: SupportedCodePage,433 code_page: SupportedCodePage,
442 };434 };
443435
444 fn fmtToken(self: ErrorDetails, source: []const u8) std.fmt.Formatter(formatToken) {436 fn fmtToken(self: ErrorDetails, source: []const u8) std.fmt.Formatter(TokenFormatContext, formatToken) {
445 return .{ .data = .{437 return .{ .data = .{
446 .token = self.token,438 .token = self.token,
447 .code_page = self.code_page,439 .code_page = self.code_page,
...@@ -452,7 +444,7 @@ pub const ErrorDetails = struct {...@@ -452,7 +444,7 @@ pub const ErrorDetails = struct {
452 pub fn render(self: ErrorDetails, writer: anytype, source: []const u8, strings: []const []const u8) !void {444 pub fn render(self: ErrorDetails, writer: anytype, source: []const u8, strings: []const []const u8) !void {
453 switch (self.err) {445 switch (self.err) {
454 .unfinished_string_literal => {446 .unfinished_string_literal => {
455 return writer.print("unfinished string literal at '{s}', expected closing '\"'", .{self.fmtToken(source)});447 return writer.print("unfinished string literal at '{f}', expected closing '\"'", .{self.fmtToken(source)});
456 },448 },
457 .string_literal_too_long => {449 .string_literal_too_long => {
458 return writer.print("string literal too long (max is currently {} characters)", .{self.extra.number});450 return writer.print("string literal too long (max is currently {} characters)", .{self.extra.number});
...@@ -466,10 +458,14 @@ pub const ErrorDetails = struct {...@@ -466,10 +458,14 @@ pub const ErrorDetails = struct {
466 .hint => return,458 .hint => return,
467 },459 },
468 .illegal_byte => {460 .illegal_byte => {
469 return writer.print("character '{s}' is not allowed", .{std.fmt.fmtSliceEscapeUpper(self.token.slice(source))});461 return writer.print("character '{f}' is not allowed", .{
462 std.ascii.hexEscape(self.token.slice(source), .upper),
463 });
470 },464 },
471 .illegal_byte_outside_string_literals => {465 .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))});466 return writer.print("character '{f}' is not allowed outside of string literals", .{
467 std.ascii.hexEscape(self.token.slice(source), .upper),
468 });
473 },469 },
474 .illegal_codepoint_outside_string_literals => {470 .illegal_codepoint_outside_string_literals => {
475 // This is somewhat hacky, but we know that:471 // This is somewhat hacky, but we know that:
...@@ -527,26 +523,26 @@ pub const ErrorDetails = struct {...@@ -527,26 +523,26 @@ pub const ErrorDetails = struct {
527 return writer.print("unsupported code page '{s} (id={})' in #pragma code_page", .{ @tagName(code_page), number });523 return writer.print("unsupported code page '{s} (id={})' in #pragma code_page", .{ @tagName(code_page), number });
528 },524 },
529 .unfinished_raw_data_block => {525 .unfinished_raw_data_block => {
530 return writer.print("unfinished raw data block at '{s}', expected closing '}}' or 'END'", .{self.fmtToken(source)});526 return writer.print("unfinished raw data block at '{f}', expected closing '}}' or 'END'", .{self.fmtToken(source)});
531 },527 },
532 .unfinished_string_table_block => {528 .unfinished_string_table_block => {
533 return writer.print("unfinished STRINGTABLE block at '{s}', expected closing '}}' or 'END'", .{self.fmtToken(source)});529 return writer.print("unfinished STRINGTABLE block at '{f}', expected closing '}}' or 'END'", .{self.fmtToken(source)});
534 },530 },
535 .expected_token => {531 .expected_token => {
536 return writer.print("expected '{s}', got '{s}'", .{ self.extra.expected.nameForErrorDisplay(), self.fmtToken(source) });532 return writer.print("expected '{s}', got '{f}'", .{ self.extra.expected.nameForErrorDisplay(), self.fmtToken(source) });
537 },533 },
538 .expected_something_else => {534 .expected_something_else => {
539 try writer.writeAll("expected ");535 try writer.writeAll("expected ");
540 try self.extra.expected_types.writeCommaSeparated(writer);536 try self.extra.expected_types.writeCommaSeparated(writer);
541 return writer.print("; got '{s}'", .{self.fmtToken(source)});537 return writer.print("; got '{f}'", .{self.fmtToken(source)});
542 },538 },
543 .resource_type_cant_use_raw_data => switch (self.type) {539 .resource_type_cant_use_raw_data => switch (self.type) {
544 .err, .warning => try writer.print("expected '<filename>', found '{s}' (resource type '{s}' can't use raw data)", .{ self.fmtToken(source), self.extra.resource.nameForErrorDisplay() }),540 .err, .warning => try writer.print("expected '<filename>', found '{f}' (resource type '{s}' can't use raw data)", .{ self.fmtToken(source), self.extra.resource.nameForErrorDisplay() }),
545 .note => try writer.print("if '{s}' is intended to be a filename, it must be specified as a quoted string literal", .{self.fmtToken(source)}),541 .note => try writer.print("if '{f}' is intended to be a filename, it must be specified as a quoted string literal", .{self.fmtToken(source)}),
546 .hint => return,542 .hint => return,
547 },543 },
548 .id_must_be_ordinal => {544 .id_must_be_ordinal => {
549 try writer.print("id of resource type '{s}' must be an ordinal (u16), got '{s}'", .{ self.extra.resource.nameForErrorDisplay(), self.fmtToken(source) });545 try writer.print("id of resource type '{s}' must be an ordinal (u16), got '{f}'", .{ self.extra.resource.nameForErrorDisplay(), self.fmtToken(source) });
550 },546 },
551 .name_or_id_not_allowed => {547 .name_or_id_not_allowed => {
552 try writer.print("name or id is not allowed for resource type '{s}'", .{self.extra.resource.nameForErrorDisplay()});548 try writer.print("name or id is not allowed for resource type '{s}'", .{self.extra.resource.nameForErrorDisplay()});
...@@ -562,7 +558,7 @@ pub const ErrorDetails = struct {...@@ -562,7 +558,7 @@ pub const ErrorDetails = struct {
562 try writer.writeAll("ASCII character not equivalent to virtual key code");558 try writer.writeAll("ASCII character not equivalent to virtual key code");
563 },559 },
564 .empty_menu_not_allowed => {560 .empty_menu_not_allowed => {
565 try writer.print("empty menu of type '{s}' not allowed", .{self.fmtToken(source)});561 try writer.print("empty menu of type '{f}' not allowed", .{self.fmtToken(source)});
566 },562 },
567 .rc_would_miscompile_version_value_padding => switch (self.type) {563 .rc_would_miscompile_version_value_padding => switch (self.type) {
568 .err, .warning => return writer.print("the padding before this quoted string value would be miscompiled by the Win32 RC compiler", .{}),564 .err, .warning => return writer.print("the padding before this quoted string value would be miscompiled by the Win32 RC compiler", .{}),
...@@ -627,7 +623,7 @@ pub const ErrorDetails = struct {...@@ -627,7 +623,7 @@ pub const ErrorDetails = struct {
627 .string_already_defined => switch (self.type) {623 .string_already_defined => switch (self.type) {
628 .err, .warning => {624 .err, .warning => {
629 const language = self.extra.string_and_language.language;625 const language = self.extra.string_and_language.language;
630 return writer.print("string with id {d} (0x{X}) already defined for language {}", .{ self.extra.string_and_language.id, self.extra.string_and_language.id, language });626 return writer.print("string with id {d} (0x{X}) already defined for language {f}", .{ self.extra.string_and_language.id, self.extra.string_and_language.id, language });
631 },627 },
632 .note => return writer.print("previous definition of string with id {d} (0x{X}) here", .{ self.extra.string_and_language.id, self.extra.string_and_language.id }),628 .note => return writer.print("previous definition of string with id {d} (0x{X}) here", .{ self.extra.string_and_language.id, self.extra.string_and_language.id }),
633 .hint => return,629 .hint => return,
...@@ -642,7 +638,7 @@ pub const ErrorDetails = struct {...@@ -642,7 +638,7 @@ pub const ErrorDetails = struct {
642 try writer.print("unable to open file '{s}': {s}", .{ strings[self.extra.file_open_error.filename_string_index], @tagName(self.extra.file_open_error.err) });638 try writer.print("unable to open file '{s}': {s}", .{ strings[self.extra.file_open_error.filename_string_index], @tagName(self.extra.file_open_error.err) });
643 },639 },
644 .invalid_accelerator_key => {640 .invalid_accelerator_key => {
645 try writer.print("invalid accelerator key '{s}': {s}", .{ self.fmtToken(source), @tagName(self.extra.accelerator_error.err) });641 try writer.print("invalid accelerator key '{f}': {s}", .{ self.fmtToken(source), @tagName(self.extra.accelerator_error.err) });
646 },642 },
647 .accelerator_type_required => {643 .accelerator_type_required => {
648 try writer.writeAll("accelerator type [ASCII or VIRTKEY] required when key is an integer");644 try writer.writeAll("accelerator type [ASCII or VIRTKEY] required when key is an integer");
...@@ -898,7 +894,7 @@ fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usiz...@@ -898,7 +894,7 @@ fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usiz
898894
899const truncated_str = "<...truncated...>";895const truncated_str = "<...truncated...>";
900896
901pub fn renderErrorMessage(writer: anytype, tty_config: std.io.tty.Config, cwd: std.fs.Dir, err_details: ErrorDetails, source: []const u8, strings: []const []const u8, source_mappings: ?SourceMappings) !void {897pub fn renderErrorMessage(writer: *std.io.Writer, tty_config: std.io.tty.Config, cwd: std.fs.Dir, err_details: ErrorDetails, source: []const u8, strings: []const []const u8, source_mappings: ?SourceMappings) !void {
902 if (err_details.type == .hint) return;898 if (err_details.type == .hint) return;
903899
904 const source_line_start = err_details.token.getLineStartForErrorDisplay(source);900 const source_line_start = err_details.token.getLineStartForErrorDisplay(source);
...@@ -981,10 +977,10 @@ pub fn renderErrorMessage(writer: anytype, tty_config: std.io.tty.Config, cwd: s...@@ -981,10 +977,10 @@ pub fn renderErrorMessage(writer: anytype, tty_config: std.io.tty.Config, cwd: s
981977
982 try tty_config.setColor(writer, .green);978 try tty_config.setColor(writer, .green);
983 const num_spaces = truncated_visual_info.point_offset - truncated_visual_info.before_len;979 const num_spaces = truncated_visual_info.point_offset - truncated_visual_info.before_len;
984 try writer.writeByteNTimes(' ', num_spaces);980 try writer.splatByteAll(' ', num_spaces);
985 try writer.writeByteNTimes('~', truncated_visual_info.before_len);981 try writer.splatByteAll('~', truncated_visual_info.before_len);
986 try writer.writeByte('^');982 try writer.writeByte('^');
987 try writer.writeByteNTimes('~', truncated_visual_info.after_len);983 try writer.splatByteAll('~', truncated_visual_info.after_len);
988 try writer.writeByte('\n');984 try writer.writeByte('\n');
989 try tty_config.setColor(writer, .reset);985 try tty_config.setColor(writer, .reset);
990986
...@@ -1085,7 +1081,7 @@ const CorrespondingLines = struct {...@@ -1085,7 +1081,7 @@ const CorrespondingLines = struct {
1085 buffered_reader: BufferedReaderType,1081 buffered_reader: BufferedReaderType,
1086 code_page: SupportedCodePage,1082 code_page: SupportedCodePage,
10871083
1088 const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.Reader);1084 const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.DeprecatedReader);
10891085
1090 pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines {1086 pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines {
1091 // We don't do line comparison for this error, so don't print the note if the line1087 // We don't do line comparison for this error, so don't print the note if the line
...@@ -1106,7 +1102,7 @@ const CorrespondingLines = struct {...@@ -1106,7 +1102,7 @@ const CorrespondingLines = struct {
1106 .code_page = err_details.code_page,1102 .code_page = err_details.code_page,
1107 };1103 };
1108 corresponding_lines.buffered_reader = BufferedReaderType{1104 corresponding_lines.buffered_reader = BufferedReaderType{
1109 .unbuffered_reader = corresponding_lines.file.reader(),1105 .unbuffered_reader = corresponding_lines.file.deprecatedReader(),
1110 };1106 };
1111 errdefer corresponding_lines.deinit();1107 errdefer corresponding_lines.deinit();
11121108
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+17-13
...@@ -22,14 +22,14 @@ pub fn main() !void {...@@ -22,14 +22,14 @@ pub fn main() !void {
22 defer arena_state.deinit();22 defer arena_state.deinit();
23 const arena = arena_state.allocator();23 const arena = arena_state.allocator();
2424
25 const stderr = std.io.getStdErr();25 const stderr = std.fs.File.stderr();
26 const stderr_config = std.io.tty.detectConfig(stderr);26 const stderr_config = std.io.tty.detectConfig(stderr);
2727
28 const args = try std.process.argsAlloc(allocator);28 const args = try std.process.argsAlloc(allocator);
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(std.debug.lockStderrWriter(&.{}), 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];
...@@ -44,7 +44,7 @@ pub fn main() !void {...@@ -44,7 +44,7 @@ pub fn main() !void {
44 var error_handler: ErrorHandler = switch (zig_integration) {44 var error_handler: ErrorHandler = switch (zig_integration) {
45 true => .{45 true => .{
46 .server = .{46 .server = .{
47 .out = std.io.getStdOut(),47 .out = std.fs.File.stdout(),
48 .in = undefined, // won't be receiving messages48 .in = undefined, // won't be receiving messages
49 .receive_fifo = undefined, // won't be receiving messages49 .receive_fifo = undefined, // won't be receiving messages
50 },50 },
...@@ -81,15 +81,15 @@ pub fn main() !void {...@@ -81,15 +81,15 @@ pub fn main() !void {
81 defer options.deinit();81 defer options.deinit();
8282
83 if (options.print_help_and_exit) {83 if (options.print_help_and_exit) {
84 const stdout = std.io.getStdOut();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.io.getStdOut().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 => {
...@@ -343,7 +343,7 @@ pub fn main() !void {...@@ -343,7 +343,7 @@ pub fn main() !void {
343 switch (err) {343 switch (err) {
344 error.DuplicateResource => {344 error.DuplicateResource => {
345 const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];345 const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
346 try error_handler.emitMessage(allocator, .err, "duplicate resource [id: {}, type: {}, language: {}]", .{346 try error_handler.emitMessage(allocator, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
347 duplicate_resource.name_value,347 duplicate_resource.name_value,
348 fmtResourceType(duplicate_resource.type_value),348 fmtResourceType(duplicate_resource.type_value),
349 duplicate_resource.language,349 duplicate_resource.language,
...@@ -352,7 +352,7 @@ pub fn main() !void {...@@ -352,7 +352,7 @@ pub fn main() !void {
352 error.ResourceDataTooLong => {352 error.ResourceDataTooLong => {
353 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];353 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
354 try error_handler.emitMessage(allocator, .err, "resource has a data length that is too large to be written into a coff section", .{});354 try error_handler.emitMessage(allocator, .err, "resource has a data length that is too large to be written into a coff section", .{});
355 try error_handler.emitMessage(allocator, .note, "the resource with the invalid size is [id: {}, type: {}, language: {}]", .{355 try error_handler.emitMessage(allocator, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
356 overflow_resource.name_value,356 overflow_resource.name_value,
357 fmtResourceType(overflow_resource.type_value),357 fmtResourceType(overflow_resource.type_value),
358 overflow_resource.language,358 overflow_resource.language,
...@@ -361,7 +361,7 @@ pub fn main() !void {...@@ -361,7 +361,7 @@ pub fn main() !void {
361 error.TotalResourceDataTooLong => {361 error.TotalResourceDataTooLong => {
362 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];362 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
363 try error_handler.emitMessage(allocator, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});363 try error_handler.emitMessage(allocator, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
364 try error_handler.emitMessage(allocator, .note, "size overflow occurred when attempting to write this resource: [id: {}, type: {}, language: {}]", .{364 try error_handler.emitMessage(allocator, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
365 overflow_resource.name_value,365 overflow_resource.name_value,
366 fmtResourceType(overflow_resource.type_value),366 fmtResourceType(overflow_resource.type_value),
367 overflow_resource.language,367 overflow_resource.language,
...@@ -471,7 +471,7 @@ const IoStream = struct {...@@ -471,7 +471,7 @@ const IoStream = struct {
471 allocator: std.mem.Allocator,471 allocator: std.mem.Allocator,
472 };472 };
473 pub const WriteError = std.mem.Allocator.Error || std.fs.File.WriteError;473 pub const WriteError = std.mem.Allocator.Error || std.fs.File.WriteError;
474 pub const Writer = std.io.Writer(WriterContext, WriteError, write);474 pub const Writer = std.io.GenericWriter(WriterContext, WriteError, write);
475475
476 pub fn write(ctx: WriterContext, bytes: []const u8) WriteError!usize {476 pub fn write(ctx: WriterContext, bytes: []const u8) WriteError!usize {
477 switch (ctx.self.*) {477 switch (ctx.self.*) {
...@@ -645,7 +645,9 @@ const ErrorHandler = union(enum) {...@@ -645,7 +645,9 @@ 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.io.getStdErr().writer(), self.tty, .err, "{s}\n", .{fail_msg});648 const stderr = std.debug.lockStderrWriter(&.{});
649 defer std.debug.unlockStderrWriter();
650 try renderErrorMessage(stderr, self.tty, .err, "{s}\n", .{fail_msg});
649 aro.Diagnostics.render(comp, self.tty);651 aro.Diagnostics.render(comp, self.tty);
650 },652 },
651 }653 }
...@@ -690,7 +692,9 @@ const ErrorHandler = union(enum) {...@@ -690,7 +692,9 @@ const ErrorHandler = union(enum) {
690 try server.serveErrorBundle(error_bundle);692 try server.serveErrorBundle(error_bundle);
691 },693 },
692 .tty => {694 .tty => {
693 try renderErrorMessage(std.io.getStdErr().writer(), self.tty, msg_type, format, args);695 const stderr = std.debug.lockStderrWriter(&.{});
696 defer std.debug.unlockStderrWriter();
697 try renderErrorMessage(stderr, self.tty, msg_type, format, args);
694 },698 },
695 }699 }
696 }700 }
lib/compiler/resinator/res.zig+11-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,7 @@ pub const Language = packed struct(u16) {...@@ -163,14 +164,7 @@ 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) std.io.Writer.Error!void {
167 language: Language,
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();168 const language_id = language.asInt();
175 const language_name = language_name: {169 const language_name = language_name: {
176 if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {170 if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {
...@@ -181,7 +175,7 @@ pub const Language = packed struct(u16) {...@@ -181,7 +175,7 @@ pub const Language = packed struct(u16) {
181 }175 }
182 break :language_name "<UNKNOWN>";176 break :language_name "<UNKNOWN>";
183 };177 };
184 try out_stream.print("{s} (0x{X})", .{ language_name, language_id });178 try w.print("{s} (0x{X})", .{ language_name, language_id });
185 }179 }
186};180};
187181
...@@ -445,47 +439,33 @@ pub const NameOrOrdinal = union(enum) {...@@ -445,47 +439,33 @@ pub const NameOrOrdinal = union(enum) {
445 }439 }
446 }440 }
447441
448 pub fn format(442 pub fn format(self: NameOrOrdinal, w: *std.io.Writer) !void {
449 self: NameOrOrdinal,
450 comptime fmt: []const u8,
451 options: std.fmt.FormatOptions,
452 out_stream: anytype,
453 ) !void {
454 _ = fmt;
455 _ = options;
456 switch (self) {443 switch (self) {
457 .name => |name| {444 .name => |name| {
458 try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});445 try w.print("{f}", .{std.unicode.fmtUtf16Le(name)});
459 },446 },
460 .ordinal => |ordinal| {447 .ordinal => |ordinal| {
461 try out_stream.print("{d}", .{ordinal});448 try w.print("{d}", .{ordinal});
462 },449 },
463 }450 }
464 }451 }
465452
466 fn formatResourceType(453 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) {454 switch (self) {
475 .name => |name| {455 .name => |name| {
476 try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});456 try w.print("{f}", .{std.unicode.fmtUtf16Le(name)});
477 },457 },
478 .ordinal => |ordinal| {458 .ordinal => |ordinal| {
479 if (std.enums.tagName(RT, @enumFromInt(ordinal))) |predefined_type_name| {459 if (std.enums.tagName(RT, @enumFromInt(ordinal))) |predefined_type_name| {
480 try out_stream.print("{s}", .{predefined_type_name});460 try w.print("{s}", .{predefined_type_name});
481 } else {461 } else {
482 try out_stream.print("{d}", .{ordinal});462 try w.print("{d}", .{ordinal});
483 }463 }
484 },464 },
485 }465 }
486 }466 }
487467
488 pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(formatResourceType) {468 pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(NameOrOrdinal, formatResourceType) {
489 return .{ .data = type_value };469 return .{ .data = type_value };
490 }470 }
491};471};
lib/compiler/resinator/utils.zig+1-1
...@@ -86,7 +86,7 @@ pub const ErrorMessageType = enum { err, warning, note };...@@ -86,7 +86,7 @@ pub const ErrorMessageType = enum { err, warning, note };
8686
87/// Used for generic colored errors/warnings/notes, more context-specific error messages87/// Used for generic colored errors/warnings/notes, more context-specific error messages
88/// are handled elsewhere.88/// are handled elsewhere.
89pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {89pub fn renderErrorMessage(writer: *std.io.Writer, config: std.io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {
90 switch (msg_type) {90 switch (msg_type) {
91 .err => {91 .err => {
92 try config.setColor(writer, .bold);92 try config.setColor(writer, .bold);
lib/compiler/std-docs.zig+2-2
...@@ -7,7 +7,7 @@ const assert = std.debug.assert;...@@ -7,7 +7,7 @@ const assert = std.debug.assert;
7const Cache = std.Build.Cache;7const Cache = std.Build.Cache;
88
9fn usage() noreturn {9fn usage() noreturn {
10 io.getStdOut().writeAll(10 std.fs.File.stdout().writeAll(
11 \\Usage: zig std [options]11 \\Usage: zig std [options]
12 \\12 \\
13 \\Options:13 \\Options:
...@@ -63,7 +63,7 @@ pub fn main() !void {...@@ -63,7 +63,7 @@ pub fn main() !void {
63 var http_server = try address.listen(.{});63 var http_server = try address.listen(.{});
64 const port = http_server.listen_address.in.getPort();64 const port = http_server.listen_address.in.getPort();
65 const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port});65 const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port});
66 std.io.getStdOut().writeAll(url_with_newline) catch {};66 std.fs.File.stdout().writeAll(url_with_newline) catch {};
67 if (should_open_browser) {67 if (should_open_browser) {
68 openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| {68 openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| {
69 std.log.err("unable to open browser: {s}", .{@errorName(err)});69 std.log.err("unable to open browser: {s}", .{@errorName(err)});
lib/compiler/test_runner.zig+5-5
...@@ -69,8 +69,8 @@ fn mainServer() !void {...@@ -69,8 +69,8 @@ fn mainServer() !void {
69 @disableInstrumentation();69 @disableInstrumentation();
70 var server = try std.zig.Server.init(.{70 var server = try std.zig.Server.init(.{
71 .gpa = fba.allocator(),71 .gpa = fba.allocator(),
72 .in = std.io.getStdIn(),72 .in = .stdin(),
73 .out = std.io.getStdOut(),73 .out = .stdout(),
74 .zig_version = builtin.zig_version_string,74 .zig_version = builtin.zig_version_string,
75 });75 });
76 defer server.deinit();76 defer server.deinit();
...@@ -191,7 +191,7 @@ fn mainTerminal() void {...@@ -191,7 +191,7 @@ fn mainTerminal() void {
191 .root_name = "Test",191 .root_name = "Test",
192 .estimated_total_items = test_fn_list.len,192 .estimated_total_items = test_fn_list.len,
193 });193 });
194 const have_tty = std.io.getStdErr().isTty();194 const have_tty = std.fs.File.stderr().isTty();
195195
196 var async_frame_buffer: []align(builtin.target.stackAlignment()) u8 = undefined;196 var async_frame_buffer: []align(builtin.target.stackAlignment()) u8 = undefined;
197 // TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly197 // TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly
...@@ -301,7 +301,7 @@ pub fn mainSimple() anyerror!void {...@@ -301,7 +301,7 @@ pub fn mainSimple() anyerror!void {
301 var failed: u64 = 0;301 var failed: u64 = 0;
302302
303 // we don't want to bring in File and Writer if the backend doesn't support it303 // we don't want to bring in File and Writer if the backend doesn't support it
304 const stderr = if (comptime enable_print) std.io.getStdErr() else {};304 const stderr = if (comptime enable_print) std.fs.File.stderr() else {};
305305
306 for (builtin.test_functions) |test_fn| {306 for (builtin.test_functions) |test_fn| {
307 if (test_fn.func()) |_| {307 if (test_fn.func()) |_| {
...@@ -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/Walk.zig+1-1
...@@ -440,7 +440,7 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {...@@ -440,7 +440,7 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {
440 const err_loc = std.zig.findLineColumn(ast.source, err_offset);440 const err_loc = std.zig.findLineColumn(ast.source, err_offset);
441 rendered_err.clearRetainingCapacity();441 rendered_err.clearRetainingCapacity();
442 try ast.renderError(err, rendered_err.writer(gpa));442 try ast.renderError(err, rendered_err.writer(gpa));
443 log.err("{s}:{}:{}: {s}", .{ file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.items });443 log.err("{s}:{d}:{d}: {s}", .{ file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.items });
444 }444 }
445 return Ast.parse(gpa, "", .zig);445 return Ast.parse(gpa, "", .zig);
446 }446 }
lib/docs/wasm/main.zig+2-2
...@@ -717,9 +717,9 @@ fn render_docs(...@@ -717,9 +717,9 @@ fn render_docs(
717 try writer.writeAll("<a href=\"#");717 try writer.writeAll("<a href=\"#");
718 _ = missing_feature_url_escape;718 _ = missing_feature_url_escape;
719 try writer.writeAll(g.link_buffer.items);719 try writer.writeAll(g.link_buffer.items);
720 try writer.print("\">{}</a>", .{markdown.fmtHtml(content)});720 try writer.print("\">{f}</a>", .{markdown.fmtHtml(content)});
721 } else {721 } else {
722 try writer.print("{}", .{markdown.fmtHtml(content)});722 try writer.print("{f}", .{markdown.fmtHtml(content)});
723 }723 }
724724
725 try writer.writeAll("</code>");725 try writer.writeAll("</code>");
lib/docs/wasm/markdown.zig+2-2
...@@ -145,7 +145,7 @@ fn mainImpl() !void {...@@ -145,7 +145,7 @@ fn mainImpl() !void {
145 var parser = try Parser.init(gpa);145 var parser = try Parser.init(gpa);
146 defer parser.deinit();146 defer parser.deinit();
147147
148 var stdin_buf = std.io.bufferedReader(std.io.getStdIn().reader());148 var stdin_buf = std.io.bufferedReader(std.fs.File.stdin().deprecatedReader());
149 var line_buf = std.ArrayList(u8).init(gpa);149 var line_buf = std.ArrayList(u8).init(gpa);
150 defer line_buf.deinit();150 defer line_buf.deinit();
151 while (stdin_buf.reader().streamUntilDelimiter(line_buf.writer(), '\n', null)) {151 while (stdin_buf.reader().streamUntilDelimiter(line_buf.writer(), '\n', null)) {
...@@ -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.io.getStdOut().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+13-19
...@@ -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///
...@@ -41,7 +42,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {...@@ -41,7 +42,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
41 if (start == 1) {42 if (start == 1) {
42 try writer.writeAll("<ol>\n");43 try writer.writeAll("<ol>\n");
43 } else {44 } else {
44 try writer.print("<ol start=\"{}\">\n", .{start});45 try writer.print("<ol start=\"{d}\">\n", .{start});
45 }46 }
46 } else {47 } else {
47 try writer.writeAll("<ul>\n");48 try writer.writeAll("<ul>\n");
...@@ -105,15 +106,15 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {...@@ -105,15 +106,15 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
105 }106 }
106 },107 },
107 .heading => {108 .heading => {
108 try writer.print("<h{}>", .{data.heading.level});109 try writer.print("<h{d}>", .{data.heading.level});
109 for (doc.extraChildren(data.heading.children)) |child| {110 for (doc.extraChildren(data.heading.children)) |child| {
110 try r.renderFn(r, doc, child, writer);111 try r.renderFn(r, doc, child, writer);
111 }112 }
112 try writer.print("</h{}>\n", .{data.heading.level});113 try writer.print("</h{d}>\n", .{data.heading.level});
113 },114 },
114 .code_block => {115 .code_block => {
115 const content = doc.string(data.code_block.content);116 const content = doc.string(data.code_block.content);
116 try writer.print("<pre><code>{}</code></pre>\n", .{fmtHtml(content)});117 try writer.print("<pre><code>{f}</code></pre>\n", .{fmtHtml(content)});
117 },118 },
118 .blockquote => {119 .blockquote => {
119 try writer.writeAll("<blockquote>\n");120 try writer.writeAll("<blockquote>\n");
...@@ -134,7 +135,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {...@@ -134,7 +135,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
134 },135 },
135 .link => {136 .link => {
136 const target = doc.string(data.link.target);137 const target = doc.string(data.link.target);
137 try writer.print("<a href=\"{}\">", .{fmtHtml(target)});138 try writer.print("<a href=\"{f}\">", .{fmtHtml(target)});
138 for (doc.extraChildren(data.link.children)) |child| {139 for (doc.extraChildren(data.link.children)) |child| {
139 try r.renderFn(r, doc, child, writer);140 try r.renderFn(r, doc, child, writer);
140 }141 }
...@@ -142,11 +143,11 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {...@@ -142,11 +143,11 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
142 },143 },
143 .autolink => {144 .autolink => {
144 const target = doc.string(data.text.content);145 const target = doc.string(data.text.content);
145 try writer.print("<a href=\"{0}\">{0}</a>", .{fmtHtml(target)});146 try writer.print("<a href=\"{0f}\">{0f}</a>", .{fmtHtml(target)});
146 },147 },
147 .image => {148 .image => {
148 const target = doc.string(data.link.target);149 const target = doc.string(data.link.target);
149 try writer.print("<img src=\"{}\" alt=\"", .{fmtHtml(target)});150 try writer.print("<img src=\"{f}\" alt=\"", .{fmtHtml(target)});
150 for (doc.extraChildren(data.link.children)) |child| {151 for (doc.extraChildren(data.link.children)) |child| {
151 try renderInlineNodeText(doc, child, writer);152 try renderInlineNodeText(doc, child, writer);
152 }153 }
...@@ -168,11 +169,11 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {...@@ -168,11 +169,11 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
168 },169 },
169 .code_span => {170 .code_span => {
170 const content = doc.string(data.text.content);171 const content = doc.string(data.text.content);
171 try writer.print("<code>{}</code>", .{fmtHtml(content)});172 try writer.print("<code>{f}</code>", .{fmtHtml(content)});
172 },173 },
173 .text => {174 .text => {
174 const content = doc.string(data.text.content);175 const content = doc.string(data.text.content);
175 try writer.print("{}", .{fmtHtml(content)});176 try writer.print("{f}", .{fmtHtml(content)});
176 },177 },
177 .line_break => {178 .line_break => {
178 try writer.writeAll("<br />\n");179 try writer.writeAll("<br />\n");
...@@ -221,7 +222,7 @@ pub fn renderInlineNodeText(...@@ -221,7 +222,7 @@ pub fn renderInlineNodeText(
221 },222 },
222 .autolink, .code_span, .text => {223 .autolink, .code_span, .text => {
223 const content = doc.string(data.text.content);224 const content = doc.string(data.text.content);
224 try writer.print("{}", .{fmtHtml(content)});225 try writer.print("{f}", .{fmtHtml(content)});
225 },226 },
226 .line_break => {227 .line_break => {
227 try writer.writeAll("\n");228 try writer.writeAll("\n");
...@@ -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/fuzzer.zig+12-9
...@@ -9,7 +9,8 @@ pub const std_options = std.Options{...@@ -9,7 +9,8 @@ pub const std_options = std.Options{
9 .logFn = logOverride,9 .logFn = logOverride,
10};10};
1111
12var log_file: ?std.fs.File = null;12var log_file_buffer: [256]u8 = undefined;
13var log_file_writer: ?std.fs.File.Writer = null;
1314
14fn logOverride(15fn logOverride(
15 comptime level: std.log.Level,16 comptime level: std.log.Level,
...@@ -17,15 +18,17 @@ fn logOverride(...@@ -17,15 +18,17 @@ fn logOverride(
17 comptime format: []const u8,18 comptime format: []const u8,
18 args: anytype,19 args: anytype,
19) void {20) void {
20 const f = if (log_file) |f| f else f: {21 const fw = if (log_file_writer) |*f| f else f: {
21 const f = fuzzer.cache_dir.createFile("tmp/libfuzzer.log", .{}) catch22 const f = fuzzer.cache_dir.createFile("tmp/libfuzzer.log", .{}) catch
22 @panic("failed to open fuzzer log file");23 @panic("failed to open fuzzer log file");
23 log_file = f;24 log_file_writer = f.writer(&log_file_buffer);
24 break :f f;25 break :f &log_file_writer.?;
25 };26 };
26 const prefix1 = comptime level.asText();27 const prefix1 = comptime level.asText();
27 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";28 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
28 f.writer().print(prefix1 ++ prefix2 ++ format ++ "\n", args) catch @panic("failed to write to fuzzer log");29 fw.interface.print(prefix1 ++ prefix2 ++ format ++ "\n", args) catch
30 @panic("failed to write to fuzzer log");
31 fw.interface.flush() catch @panic("failed to flush fuzzer log");
29}32}
3033
31/// Helps determine run uniqueness in the face of recursion.34/// Helps determine run uniqueness in the face of recursion.
...@@ -226,18 +229,18 @@ const Fuzzer = struct {...@@ -226,18 +229,18 @@ const Fuzzer = struct {
226 .read = true,229 .read = true,
227 }) catch |e| switch (e) {230 }) catch |e| switch (e) {
228 error.PathAlreadyExists => continue,231 error.PathAlreadyExists => continue,
229 else => fatal("unable to create '{}{d}: {s}", .{ f.corpus_directory, i, @errorName(err) }),232 else => fatal("unable to create '{f}{d}: {s}", .{ f.corpus_directory, i, @errorName(err) }),
230 };233 };
231 errdefer input_file.close();234 errdefer input_file.close();
232 // Initialize the mmap for the current input.235 // Initialize the mmap for the current input.
233 f.input = MemoryMappedList.create(input_file, 0, std.heap.page_size_max) catch |e| {236 f.input = MemoryMappedList.create(input_file, 0, std.heap.page_size_max) catch |e| {
234 fatal("unable to init memory map for input at '{}{d}': {s}", .{237 fatal("unable to init memory map for input at '{f}{d}': {s}", .{
235 f.corpus_directory, i, @errorName(e),238 f.corpus_directory, i, @errorName(e),
236 });239 });
237 };240 };
238 break;241 break;
239 },242 },
240 else => fatal("unable to read '{}{d}': {s}", .{ f.corpus_directory, i, @errorName(err) }),243 else => fatal("unable to read '{f}{d}': {s}", .{ f.corpus_directory, i, @errorName(err) }),
241 };244 };
242 errdefer gpa.free(input);245 errdefer gpa.free(input);
243 f.corpus.append(gpa, .{246 f.corpus.append(gpa, .{
...@@ -263,7 +266,7 @@ const Fuzzer = struct {...@@ -263,7 +266,7 @@ const Fuzzer = struct {
263 const sub_path = try std.fmt.allocPrint(gpa, "f/{s}", .{f.unit_test_name});266 const sub_path = try std.fmt.allocPrint(gpa, "f/{s}", .{f.unit_test_name});
264 f.corpus_directory = .{267 f.corpus_directory = .{
265 .handle = f.cache_dir.makeOpenPath(sub_path, .{}) catch |err|268 .handle = f.cache_dir.makeOpenPath(sub_path, .{}) catch |err|
266 fatal("unable to open corpus directory 'f/{s}': {s}", .{ sub_path, @errorName(err) }),269 fatal("unable to open corpus directory 'f/{s}': {t}", .{ sub_path, err }),
267 .path = sub_path,270 .path = sub_path,
268 };271 };
269 initNextInput(f);272 initNextInput(f);
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.io.getStdOut().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+33-43
...@@ -284,7 +284,7 @@ pub fn create(...@@ -284,7 +284,7 @@ pub fn create(
284 .h_dir = undefined,284 .h_dir = undefined,
285 .dest_dir = graph.env_map.get("DESTDIR"),285 .dest_dir = graph.env_map.get("DESTDIR"),
286 .install_tls = .{286 .install_tls = .{
287 .step = Step.init(.{287 .step = .init(.{
288 .id = TopLevelStep.base_id,288 .id = TopLevelStep.base_id,
289 .name = "install",289 .name = "install",
290 .owner = b,290 .owner = b,
...@@ -292,7 +292,7 @@ pub fn create(...@@ -292,7 +292,7 @@ pub fn create(
292 .description = "Copy build artifacts to prefix path",292 .description = "Copy build artifacts to prefix path",
293 },293 },
294 .uninstall_tls = .{294 .uninstall_tls = .{
295 .step = Step.init(.{295 .step = .init(.{
296 .id = TopLevelStep.base_id,296 .id = TopLevelStep.base_id,
297 .name = "uninstall",297 .name = "uninstall",
298 .owner = b,298 .owner = b,
...@@ -342,7 +342,7 @@ fn createChildOnly(...@@ -342,7 +342,7 @@ fn createChildOnly(
342 .graph = parent.graph,342 .graph = parent.graph,
343 .allocator = allocator,343 .allocator = allocator,
344 .install_tls = .{344 .install_tls = .{
345 .step = Step.init(.{345 .step = .init(.{
346 .id = TopLevelStep.base_id,346 .id = TopLevelStep.base_id,
347 .name = "install",347 .name = "install",
348 .owner = child,348 .owner = child,
...@@ -350,7 +350,7 @@ fn createChildOnly(...@@ -350,7 +350,7 @@ fn createChildOnly(
350 .description = "Copy build artifacts to prefix path",350 .description = "Copy build artifacts to prefix path",
351 },351 },
352 .uninstall_tls = .{352 .uninstall_tls = .{
353 .step = Step.init(.{353 .step = .init(.{
354 .id = TopLevelStep.base_id,354 .id = TopLevelStep.base_id,
355 .name = "uninstall",355 .name = "uninstall",
356 .owner = child,356 .owner = child,
...@@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1525pub fn step(b: *Build, name: []const u8, description: []const u8) *Step {1525pub fn step(b: *Build, name: []const u8, description: []const u8) *Step {
1526 const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM");1526 const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM");
1527 step_info.* = .{1527 step_info.* = .{
1528 .step = Step.init(.{1528 .step = .init(.{
1529 .id = TopLevelStep.base_id,1529 .id = TopLevelStep.base_id,
1530 .name = name,1530 .name = name,
1531 .owner = b,1531 .owner = b,
...@@ -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 }
...@@ -1824,13 +1824,13 @@ pub fn validateUserInputDidItFail(b: *Build) bool {...@@ -1824,13 +1824,13 @@ pub fn validateUserInputDidItFail(b: *Build) bool {
1824 return b.invalid_user_input;1824 return b.invalid_user_input;
1825}1825}
18261826
1827fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 {1827fn allocPrintCmd(gpa: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 {
1828 var buf = ArrayList(u8).init(ally);1828 var buf: std.ArrayListUnmanaged(u8) = .empty;
1829 if (opt_cwd) |cwd| try buf.writer().print("cd {s} && ", .{cwd});1829 if (opt_cwd) |cwd| try buf.print(gpa, "cd {s} && ", .{cwd});
1830 for (argv) |arg| {1830 for (argv) |arg| {
1831 try buf.writer().print("{s} ", .{arg});1831 try buf.print(gpa, "{s} ", .{arg});
1832 }1832 }
1833 return buf.toOwnedSlice();1833 return buf.toOwnedSlice(gpa);
1834}1834}
18351835
1836fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void {1836fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void {
...@@ -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);
...@@ -2466,10 +2466,9 @@ pub const GeneratedFile = struct {...@@ -2466,10 +2466,9 @@ pub const GeneratedFile = struct {
24662466
2467 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {2467 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {
2468 return gen.path orelse {2468 return gen.path orelse {
2469 std.debug.lockStdErr();2469 const w = debug.lockStderrWriter(&.{});
2470 const stderr = std.io.getStdErr();2470 dumpBadGetPathHelp(gen.step, w, .detect(.stderr()), src_builder, asking_step) catch {};
2471 dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};2471 debug.unlockStderrWriter();
2472 std.debug.unlockStdErr();
2473 @panic("misconfigured build script");2472 @panic("misconfigured build script");
2474 };2473 };
2475 }2474 }
...@@ -2676,10 +2675,9 @@ pub const LazyPath = union(enum) {...@@ -2676,10 +2675,9 @@ pub const LazyPath = union(enum) {
2676 var file_path: Cache.Path = .{2675 var file_path: Cache.Path = .{
2677 .root_dir = Cache.Directory.cwd(),2676 .root_dir = Cache.Directory.cwd(),
2678 .sub_path = gen.file.path orelse {2677 .sub_path = gen.file.path orelse {
2679 std.debug.lockStdErr();2678 const w = debug.lockStderrWriter(&.{});
2680 const stderr = std.io.getStdErr();2679 dumpBadGetPathHelp(gen.file.step, w, .detect(.stderr()), src_builder, asking_step) catch {};
2681 dumpBadGetPathHelp(gen.file.step, stderr, src_builder, asking_step) catch {};2680 debug.unlockStderrWriter();
2682 std.debug.unlockStdErr();
2683 @panic("misconfigured build script");2681 @panic("misconfigured build script");
2684 },2682 },
2685 };2683 };
...@@ -2766,44 +2764,42 @@ fn dumpBadDirnameHelp(...@@ -2766,44 +2764,42 @@ fn dumpBadDirnameHelp(
2766 comptime msg: []const u8,2764 comptime msg: []const u8,
2767 args: anytype,2765 args: anytype,
2768) anyerror!void {2766) anyerror!void {
2769 debug.lockStdErr();2767 const w = debug.lockStderrWriter(&.{});
2770 defer debug.unlockStdErr();2768 defer debug.unlockStderrWriter();
27712769
2772 const stderr = io.getStdErr();
2773 const w = stderr.writer();
2774 try w.print(msg, args);2770 try w.print(msg, args);
27752771
2776 const tty_config = std.io.tty.detectConfig(stderr);2772 const tty_config = std.io.tty.detectConfig(.stderr());
27772773
2778 if (fail_step) |s| {2774 if (fail_step) |s| {
2779 tty_config.setColor(w, .red) catch {};2775 tty_config.setColor(w, .red) catch {};
2780 try stderr.writeAll(" The step was created by this stack trace:\n");2776 try w.writeAll(" The step was created by this stack trace:\n");
2781 tty_config.setColor(w, .reset) catch {};2777 tty_config.setColor(w, .reset) catch {};
27822778
2783 s.dump(stderr);2779 s.dump(w, tty_config);
2784 }2780 }
27852781
2786 if (asking_step) |as| {2782 if (asking_step) |as| {
2787 tty_config.setColor(w, .red) catch {};2783 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});2784 try w.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 {};2785 tty_config.setColor(w, .reset) catch {};
27902786
2791 as.dump(stderr);2787 as.dump(w, tty_config);
2792 }2788 }
27932789
2794 tty_config.setColor(w, .red) catch {};2790 tty_config.setColor(w, .red) catch {};
2795 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");2791 try w.writeAll(" Hope that helps. Proceeding to panic.\n");
2796 tty_config.setColor(w, .reset) catch {};2792 tty_config.setColor(w, .reset) catch {};
2797}2793}
27982794
2799/// In this function the stderr mutex has already been locked.2795/// In this function the stderr mutex has already been locked.
2800pub fn dumpBadGetPathHelp(2796pub fn dumpBadGetPathHelp(
2801 s: *Step,2797 s: *Step,
2802 stderr: fs.File,2798 w: *std.io.Writer,
2799 tty_config: std.io.tty.Config,
2803 src_builder: *Build,2800 src_builder: *Build,
2804 asking_step: ?*Step,2801 asking_step: ?*Step,
2805) anyerror!void {2802) anyerror!void {
2806 const w = stderr.writer();
2807 try w.print(2803 try w.print(
2808 \\getPath() was called on a GeneratedFile that wasn't built yet.2804 \\getPath() was called on a GeneratedFile that wasn't built yet.
2809 \\ source package path: {s}2805 \\ source package path: {s}
...@@ -2814,21 +2810,20 @@ pub fn dumpBadGetPathHelp(...@@ -2814,21 +2810,20 @@ pub fn dumpBadGetPathHelp(
2814 s.name,2810 s.name,
2815 });2811 });
28162812
2817 const tty_config = std.io.tty.detectConfig(stderr);
2818 tty_config.setColor(w, .red) catch {};2813 tty_config.setColor(w, .red) catch {};
2819 try stderr.writeAll(" The step was created by this stack trace:\n");2814 try w.writeAll(" The step was created by this stack trace:\n");
2820 tty_config.setColor(w, .reset) catch {};2815 tty_config.setColor(w, .reset) catch {};
28212816
2822 s.dump(stderr);2817 s.dump(w, tty_config);
2823 if (asking_step) |as| {2818 if (asking_step) |as| {
2824 tty_config.setColor(w, .red) catch {};2819 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});2820 try w.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 {};2821 tty_config.setColor(w, .reset) catch {};
28272822
2828 as.dump(stderr);2823 as.dump(w, tty_config);
2829 }2824 }
2830 tty_config.setColor(w, .red) catch {};2825 tty_config.setColor(w, .red) catch {};
2831 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");2826 try w.writeAll(" Hope that helps. Proceeding to panic.\n");
2832 tty_config.setColor(w, .reset) catch {};2827 tty_config.setColor(w, .reset) catch {};
2833}2828}
28342829
...@@ -2866,11 +2861,6 @@ pub fn makeTempPath(b: *Build) []const u8 {...@@ -2866,11 +2861,6 @@ pub fn makeTempPath(b: *Build) []const u8 {
2866 return result_path;2861 return result_path;
2867}2862}
28682863
2869/// Deprecated; use `std.fmt.hex` instead.
2870pub fn hex64(x: u64) [16]u8 {
2871 return std.fmt.hex(x);
2872}
2873
2874/// A pair of target query and fully resolved target.2864/// A pair of target query and fully resolved target.
2875/// This type is generally required by build system API that need to be given a2865/// This type is generally required by build system API that need to be given a
2876/// target. The query is kept because the Zig toolchain needs to know which parts2866/// target. The query is kept because the Zig toolchain needs to know which parts
lib/std/Build/Cache.zig+55-61
...@@ -2,6 +2,18 @@...@@ -2,6 +2,18 @@
2//! This is not a general-purpose cache. It is designed to be fast and simple,2//! This is not a general-purpose cache. It is designed to be fast and simple,
3//! not to withstand attacks using specially-crafted input.3//! not to withstand attacks using specially-crafted input.
44
5const Cache = @This();
6const std = @import("std");
7const builtin = @import("builtin");
8const crypto = std.crypto;
9const fs = std.fs;
10const assert = std.debug.assert;
11const testing = std.testing;
12const mem = std.mem;
13const fmt = std.fmt;
14const Allocator = std.mem.Allocator;
15const log = std.log.scoped(.cache);
16
5gpa: Allocator,17gpa: Allocator,
6manifest_dir: fs.Dir,18manifest_dir: fs.Dir,
7hash: HashHelper = .{},19hash: HashHelper = .{},
...@@ -21,18 +33,6 @@ pub const Path = @import("Cache/Path.zig");...@@ -21,18 +33,6 @@ pub const Path = @import("Cache/Path.zig");
21pub const Directory = @import("Cache/Directory.zig");33pub const Directory = @import("Cache/Directory.zig");
22pub const DepTokenizer = @import("Cache/DepTokenizer.zig");34pub const DepTokenizer = @import("Cache/DepTokenizer.zig");
2335
24const Cache = @This();
25const std = @import("std");
26const builtin = @import("builtin");
27const crypto = std.crypto;
28const fs = std.fs;
29const assert = std.debug.assert;
30const testing = std.testing;
31const mem = std.mem;
32const fmt = std.fmt;
33const Allocator = std.mem.Allocator;
34const log = std.log.scoped(.cache);
35
36pub fn addPrefix(cache: *Cache, directory: Directory) void {36pub fn addPrefix(cache: *Cache, directory: Directory) void {
37 cache.prefixes_buffer[cache.prefixes_len] = directory;37 cache.prefixes_buffer[cache.prefixes_len] = directory;
38 cache.prefixes_len += 1;38 cache.prefixes_len += 1;
...@@ -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,12 @@ pub const Manifest = struct {...@@ -1127,24 +1118,12 @@ 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 var buffer: [4000]u8 = undefined;
1131 defer contents.deinit();1122 var fw = manifest_file.writer(&buffer);
11321123 writeDirtyManifestToStream(self, &fw) catch |err| switch (err) {
1133 const writer = contents.writer();1124 error.WriteFailed => return fw.err.?,
1134 try writer.writeAll(manifest_header ++ "\n");1125 else => |e| return e,
1135 for (self.files.keys()) |file| {1126 };
1136 try writer.print("{d} {d} {d} {} {d} {s}\n", .{
1137 file.stat.size,
1138 file.stat.inode,
1139 file.stat.mtime,
1140 fmt.fmtSliceHexLower(&file.bin_digest),
1141 file.prefixed_path.prefix,
1142 file.prefixed_path.sub_path,
1143 });
1144 }
1145
1146 try manifest_file.setEndPos(contents.items.len);
1147 try manifest_file.pwriteAll(contents.items, 0);
1148 }1127 }
11491128
1150 if (self.want_shared_lock) {1129 if (self.want_shared_lock) {
...@@ -1152,6 +1131,21 @@ pub const Manifest = struct {...@@ -1152,6 +1131,21 @@ pub const Manifest = struct {
1152 }1131 }
1153 }1132 }
11541133
1134 fn writeDirtyManifestToStream(self: *Manifest, fw: *fs.File.Writer) !void {
1135 try fw.interface.writeAll(manifest_header ++ "\n");
1136 for (self.files.keys()) |file| {
1137 try fw.interface.print("{d} {d} {d} {x} {d} {s}\n", .{
1138 file.stat.size,
1139 file.stat.inode,
1140 file.stat.mtime,
1141 &file.bin_digest,
1142 file.prefixed_path.prefix,
1143 file.prefixed_path.sub_path,
1144 });
1145 }
1146 try fw.end();
1147 }
1148
1155 fn downgradeToSharedLock(self: *Manifest) !void {1149 fn downgradeToSharedLock(self: *Manifest) !void {
1156 if (!self.have_exclusive_lock) return;1150 if (!self.have_exclusive_lock) return;
11571151
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.io.getStdErr().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+2-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,7 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {...@@ -55,14 +56,7 @@ 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) std.io.Writer.Error!void {
59 self: Directory,
60 comptime fmt_string: []const u8,
61 options: fmt.FormatOptions,
62 writer: anytype,
63) !void {
64 _ = options;
65 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);
66 if (self.path) |p| {60 if (self.path) |p| {
67 try writer.writeAll(p);61 try writer.writeAll(p);
68 try writer.writeAll(fs.path.sep_str);62 try writer.writeAll(fs.path.sep_str);
lib/std/Build/Cache/Path.zig+39-34
...@@ -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,42 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {...@@ -133,38 +140,42 @@ 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 fmtEscapeString(path: Path) std.fmt.Formatter(Path, formatEscapeString) {
144 self: Path,151 return .{ .data = path };
145 comptime fmt_string: []const u8,152}
146 options: std.fmt.FormatOptions,153
147 writer: anytype,154pub fn formatEscapeString(path: Path, writer: *std.io.Writer) std.io.Writer.Error!void {
148) !void {155 if (path.root_dir.path) |p| {
149 if (fmt_string.len == 1) {156 try std.zig.stringEscape(p, writer);
150 // Quote-escape the string.157 if (path.sub_path.len > 0) try std.zig.stringEscape(fs.path.sep_str, writer);
151 const stringEscape = std.zig.stringEscape;
152 const f = switch (fmt_string[0]) {
153 'q' => "",
154 '\'' => "\'",
155 else => @compileError("unsupported format string: " ++ fmt_string),
156 };
157 if (self.root_dir.path) |p| {
158 try stringEscape(p, f, options, writer);
159 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, f, options, writer);
160 }
161 if (self.sub_path.len > 0) {
162 try stringEscape(self.sub_path, f, options, writer);
163 }
164 return;
165 }158 }
166 if (fmt_string.len > 0)159 if (path.sub_path.len > 0) {
167 std.fmt.invalidFmtError(fmt_string, self);160 try std.zig.stringEscape(path.sub_path, writer);
161 }
162}
163
164pub fn fmtEscapeChar(path: Path) std.fmt.Formatter(Path, formatEscapeChar) {
165 return .{ .data = path };
166}
167
168pub fn formatEscapeChar(path: Path, writer: *std.io.Writer) std.io.Writer.Error!void {
169 if (path.root_dir.path) |p| {
170 try std.zig.charEscape(p, writer);
171 if (path.sub_path.len > 0) try std.zig.charEscape(fs.path.sep_str, writer);
172 }
173 if (path.sub_path.len > 0) {
174 try std.zig.charEscape(path.sub_path, writer);
175 }
176}
177
178pub fn format(self: Path, writer: *std.io.Writer) std.io.Writer.Error!void {
168 if (std.fs.path.isAbsolute(self.sub_path)) {179 if (std.fs.path.isAbsolute(self.sub_path)) {
169 try writer.writeAll(self.sub_path);180 try writer.writeAll(self.sub_path);
170 return;181 return;
...@@ -223,9 +234,3 @@ pub const TableAdapter = struct {...@@ -223,9 +234,3 @@ pub const TableAdapter = struct {
223 return a.eql(b);234 return a.eql(b);
224 }235 }
225};236};
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.zig+8-8
...@@ -112,7 +112,6 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog...@@ -112,7 +112,6 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog
112112
113fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void {113fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void {
114 const gpa = run.step.owner.allocator;114 const gpa = run.step.owner.allocator;
115 const stderr = std.io.getStdErr();
116115
117 const compile = run.producer.?;116 const compile = run.producer.?;
118 const prog_node = parent_prog_node.start(compile.step.name, 0);117 const prog_node = parent_prog_node.start(compile.step.name, 0);
...@@ -125,9 +124,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par...@@ -125,9 +124,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par
125 const show_stderr = compile.step.result_stderr.len > 0;124 const show_stderr = compile.step.result_stderr.len > 0;
126125
127 if (show_error_msgs or show_compile_errors or show_stderr) {126 if (show_error_msgs or show_compile_errors or show_stderr) {
128 std.debug.lockStdErr();127 var buf: [256]u8 = undefined;
129 defer std.debug.unlockStdErr();128 const w = std.debug.lockStderrWriter(&buf);
130 build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, stderr, false) catch {};129 defer std.debug.unlockStderrWriter();
130 build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, false) catch {};
131 }131 }
132132
133 const rebuilt_bin_path = result catch |err| switch (err) {133 const rebuilt_bin_path = result catch |err| switch (err) {
...@@ -152,10 +152,10 @@ fn fuzzWorkerRun(...@@ -152,10 +152,10 @@ fn fuzzWorkerRun(
152152
153 run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) {153 run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) {
154 error.MakeFailed => {154 error.MakeFailed => {
155 const stderr = std.io.getStdErr();155 var buf: [256]u8 = undefined;
156 std.debug.lockStdErr();156 const w = std.debug.lockStderrWriter(&buf);
157 defer std.debug.unlockStdErr();157 defer std.debug.unlockStderrWriter();
158 build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, stderr, false) catch {};158 build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, w, false) catch {};
159 return;159 return;
160 },160 },
161 else => {161 else => {
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+4-6
...@@ -286,9 +286,7 @@ pub fn cast(step: *Step, comptime T: type) ?*T {...@@ -286,9 +286,7 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
286}286}
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, w: *std.io.Writer, tty_config: std.io.tty.Config) void {
290 const w = file.writer();
291 const tty_config = std.io.tty.detectConfig(file);
292 const debug_info = std.debug.getSelfDebugInfo() catch |err| {290 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
293 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{291 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
294 @errorName(err),292 @errorName(err),
...@@ -482,9 +480,9 @@ pub fn evalZigProcess(...@@ -482,9 +480,9 @@ pub fn evalZigProcess(
482pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {480pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
483 const b = s.owner;481 const b = s.owner;
484 const src_path = src_lazy_path.getPath3(b, s);482 const src_path = src_lazy_path.getPath3(b, s);
485 try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{}", .{src_path}), dest_path });483 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| {484 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}", .{485 return s.fail("unable to update file from '{f}' to '{s}': {s}", .{
488 src_path, dest_path, @errorName(err),486 src_path, dest_path, @errorName(err),
489 });487 });
490 };488 };
...@@ -821,7 +819,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac...@@ -821,7 +819,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac
821 switch (err) {819 switch (err) {
822 error.CacheCheckFailed => switch (man.diagnostic) {820 error.CacheCheckFailed => switch (man.diagnostic) {
823 .none => unreachable,821 .none => unreachable,
824 .manifest_create, .manifest_read, .manifest_lock, .manifest_seek => |e| return s.fail("failed to check cache: {s} {s}", .{822 .manifest_create, .manifest_read, .manifest_lock => |e| return s.fail("failed to check cache: {s} {s}", .{
825 @tagName(man.diagnostic), @errorName(e),823 @tagName(man.diagnostic), @errorName(e),
826 }),824 }),
827 .file_open, .file_stat, .file_read, .file_hash => |op| {825 .file_open, .file_stat, .file_read, .file_hash => |op| {
lib/std/Build/Step/CheckObject.zig+36-61
...@@ -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,7 +29,7 @@ pub fn create(...@@ -28,7 +29,7 @@ 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,
...@@ -80,7 +81,7 @@ const Action = struct {...@@ -80,7 +81,7 @@ const Action = struct {
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
...@@ -229,18 +230,11 @@ const ComputeCompareExpected = struct {...@@ -229,18 +230,11 @@ const ComputeCompareExpected = struct {
229 literal: u64,230 literal: u64,
230 },231 },
231232
232 pub fn format(233 pub fn format(value: ComputeCompareExpected, w: *Writer) Writer.Error!void {
233 value: @This(),234 try w.print("{t} ", .{value.op});
234 comptime fmt: []const u8,
235 options: std.fmt.FormatOptions,
236 writer: anytype,
237 ) !void {
238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
239 _ = options;
240 try writer.print("{s} ", .{@tagName(value.op)});
241 switch (value.value) {235 switch (value.value) {
242 .variable => |name| try writer.writeAll(name),236 .variable => |name| try w.writeAll(name),
243 .literal => |x| try writer.print("{x}", .{x}),237 .literal => |x| try w.print("{x}", .{x}),
244 }238 }
245 }239 }
246};240};
...@@ -565,9 +559,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -565,9 +559,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
565 null,559 null,
566 .of(u64),560 .of(u64),
567 null,561 null,
568 ) catch |err| return step.fail("unable to read '{'}': {s}", .{ src_path, @errorName(err) });562 ) catch |err| return step.fail("unable to read '{f}': {s}", .{
563 std.fmt.alt(src_path, .formatEscapeChar), @errorName(err),
564 });
569565
570 var vars = std.StringHashMap(u64).init(gpa);566 var vars: std.StringHashMap(u64) = .init(gpa);
571 for (check_object.checks.items) |chk| {567 for (check_object.checks.items) |chk| {
572 if (chk.kind == .compute_compare) {568 if (chk.kind == .compute_compare) {
573 assert(chk.actions.items.len == 1);569 assert(chk.actions.items.len == 1);
...@@ -581,7 +577,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -581,7 +577,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
581 return step.fail(577 return step.fail(
582 \\578 \\
583 \\========= comparison failed for action: ===========579 \\========= comparison failed for action: ===========
584 \\{s} {}580 \\{s} {f}
585 \\===================================================581 \\===================================================
586 , .{ act.phrase.resolve(b, step), act.expected.? });582 , .{ act.phrase.resolve(b, step), act.expected.? });
587 }583 }
...@@ -600,7 +596,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -600,7 +596,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
600 // we either format message string with escaped codes, or not to aid debugging596 // we either format message string with escaped codes, or not to aid debugging
601 // the failed test.597 // the failed test.
602 const fmtMessageString = struct {598 const fmtMessageString = struct {
603 fn fmtMessageString(kind: Check.Kind, msg: []const u8) std.fmt.Formatter(formatMessageString) {599 fn fmtMessageString(kind: Check.Kind, msg: []const u8) std.fmt.Formatter(Ctx, formatMessageString) {
604 return .{ .data = .{600 return .{ .data = .{
605 .kind = kind,601 .kind = kind,
606 .msg = msg,602 .msg = msg,
...@@ -612,17 +608,10 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -612,17 +608,10 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
612 msg: []const u8,608 msg: []const u8,
613 };609 };
614610
615 fn formatMessageString(611 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) {612 switch (ctx.kind) {
624 .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),613 .dump_section => try w.print("{f}", .{std.ascii.hexEscape(ctx.msg, .lower)}),
625 else => try writer.writeAll(ctx.msg),614 else => try w.writeAll(ctx.msg),
626 }615 }
627 }616 }
628 }.fmtMessageString;617 }.fmtMessageString;
...@@ -637,11 +626,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -637,11 +626,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
637 return step.fail(626 return step.fail(
638 \\627 \\
639 \\========= expected to find: ==========================628 \\========= expected to find: ==========================
640 \\{s}629 \\{f}
641 \\========= but parsed file does not contain it: =======630 \\========= but parsed file does not contain it: =======
642 \\{s}631 \\{f}
643 \\========= file path: =================================632 \\========= file path: =================================
644 \\{}633 \\{f}
645 , .{634 , .{
646 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),635 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
647 fmtMessageString(chk.kind, output),636 fmtMessageString(chk.kind, output),
...@@ -657,11 +646,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -657,11 +646,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
657 return step.fail(646 return step.fail(
658 \\647 \\
659 \\========= expected to find: ==========================648 \\========= expected to find: ==========================
660 \\*{s}*649 \\*{f}*
661 \\========= but parsed file does not contain it: =======650 \\========= but parsed file does not contain it: =======
662 \\{s}651 \\{f}
663 \\========= file path: =================================652 \\========= file path: =================================
664 \\{}653 \\{f}
665 , .{654 , .{
666 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),655 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
667 fmtMessageString(chk.kind, output),656 fmtMessageString(chk.kind, output),
...@@ -676,11 +665,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -676,11 +665,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
676 return step.fail(665 return step.fail(
677 \\666 \\
678 \\========= expected not to find: ===================667 \\========= expected not to find: ===================
679 \\{s}668 \\{f}
680 \\========= but parsed file does contain it: ========669 \\========= but parsed file does contain it: ========
681 \\{s}670 \\{f}
682 \\========= file path: ==============================671 \\========= file path: ==============================
683 \\{}672 \\{f}
684 , .{673 , .{
685 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),674 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
686 fmtMessageString(chk.kind, output),675 fmtMessageString(chk.kind, output),
...@@ -696,13 +685,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -696,13 +685,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
696 return step.fail(685 return step.fail(
697 \\686 \\
698 \\========= expected to find and extract: ==============687 \\========= expected to find and extract: ==============
699 \\{s}688 \\{f}
700 \\========= but parsed file does not contain it: =======689 \\========= but parsed file does not contain it: =======
701 \\{s}690 \\{f}
702 \\========= file path: ==============================691 \\========= file path: ==============================
703 \\{}692 \\{f}
704 , .{693 , .{
705 act.phrase.resolve(b, step),694 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
706 fmtMessageString(chk.kind, output),695 fmtMessageString(chk.kind, output),
707 src_path,696 src_path,
708 });697 });
...@@ -963,7 +952,7 @@ const MachODumper = struct {...@@ -963,7 +952,7 @@ const MachODumper = struct {
963 .UUID => {952 .UUID => {
964 const uuid = lc.cast(macho.uuid_command).?;953 const uuid = lc.cast(macho.uuid_command).?;
965 try writer.writeByte('\n');954 try writer.writeByte('\n');
966 try writer.print("uuid {x}", .{std.fmt.fmtSliceHexLower(&uuid.uuid)});955 try writer.print("uuid {x}", .{&uuid.uuid});
967 },956 },
968957
969 .DATA_IN_CODE,958 .DATA_IN_CODE,
...@@ -2012,7 +2001,7 @@ const ElfDumper = struct {...@@ -2012,7 +2001,7 @@ const ElfDumper = struct {
20122001
2013 for (ctx.phdrs, 0..) |phdr, phndx| {2002 for (ctx.phdrs, 0..) |phdr, phndx| {
2014 try writer.print("phdr {d}\n", .{phndx});2003 try writer.print("phdr {d}\n", .{phndx});
2015 try writer.print("type {s}\n", .{fmtPhType(phdr.p_type)});2004 try writer.print("type {f}\n", .{fmtPhType(phdr.p_type)});
2016 try writer.print("vaddr {x}\n", .{phdr.p_vaddr});2005 try writer.print("vaddr {x}\n", .{phdr.p_vaddr});
2017 try writer.print("paddr {x}\n", .{phdr.p_paddr});2006 try writer.print("paddr {x}\n", .{phdr.p_paddr});
2018 try writer.print("offset {x}\n", .{phdr.p_offset});2007 try writer.print("offset {x}\n", .{phdr.p_offset});
...@@ -2052,7 +2041,7 @@ const ElfDumper = struct {...@@ -2052,7 +2041,7 @@ const ElfDumper = struct {
2052 for (ctx.shdrs, 0..) |shdr, shndx| {2041 for (ctx.shdrs, 0..) |shdr, shndx| {
2053 try writer.print("shdr {d}\n", .{shndx});2042 try writer.print("shdr {d}\n", .{shndx});
2054 try writer.print("name {s}\n", .{ctx.getSectionName(shndx)});2043 try writer.print("name {s}\n", .{ctx.getSectionName(shndx)});
2055 try writer.print("type {s}\n", .{fmtShType(shdr.sh_type)});2044 try writer.print("type {f}\n", .{fmtShType(shdr.sh_type)});
2056 try writer.print("addr {x}\n", .{shdr.sh_addr});2045 try writer.print("addr {x}\n", .{shdr.sh_addr});
2057 try writer.print("offset {x}\n", .{shdr.sh_offset});2046 try writer.print("offset {x}\n", .{shdr.sh_offset});
2058 try writer.print("size {x}\n", .{shdr.sh_size});2047 try writer.print("size {x}\n", .{shdr.sh_size});
...@@ -2325,18 +2314,11 @@ const ElfDumper = struct {...@@ -2325,18 +2314,11 @@ const ElfDumper = struct {
2325 return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0);2314 return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0);
2326 }2315 }
23272316
2328 fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) {2317 fn fmtShType(sh_type: u32) std.fmt.Formatter(u32, formatShType) {
2329 return .{ .data = sh_type };2318 return .{ .data = sh_type };
2330 }2319 }
23312320
2332 fn formatShType(2321 fn formatShType(sh_type: u32, writer: *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) {2322 const name = switch (sh_type) {
2341 elf.SHT_NULL => "NULL",2323 elf.SHT_NULL => "NULL",
2342 elf.SHT_PROGBITS => "PROGBITS",2324 elf.SHT_PROGBITS => "PROGBITS",
...@@ -2372,18 +2354,11 @@ const ElfDumper = struct {...@@ -2372,18 +2354,11 @@ const ElfDumper = struct {
2372 try writer.writeAll(name);2354 try writer.writeAll(name);
2373 }2355 }
23742356
2375 fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) {2357 fn fmtPhType(ph_type: u32) std.fmt.Formatter(u32, formatPhType) {
2376 return .{ .data = ph_type };2358 return .{ .data = ph_type };
2377 }2359 }
23782360
2379 fn formatPhType(2361 fn formatPhType(ph_type: u32, writer: *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) {2362 const p_type = switch (ph_type) {
2388 elf.PT_NULL => "NULL",2363 elf.PT_NULL => "NULL",
2389 elf.PT_LOAD => "LOAD",2364 elf.PT_LOAD => "LOAD",
lib/std/Build/Step/Compile.zig+36-44
...@@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
409 .linkage = options.linkage,409 .linkage = options.linkage,
410 .kind = options.kind,410 .kind = options.kind,
411 .name = name,411 .name = name,
412 .step = Step.init(.{412 .step = .init(.{
413 .id = base_id,413 .id = base_id,
414 .name = step_name,414 .name = step_name,
415 .owner = owner,415 .owner = owner,
...@@ -1017,20 +1017,16 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking...@@ -1017,20 +1017,16 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking
1017 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);1017 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
10181018
1019 const generated_file = maybe_path orelse {1019 const generated_file = maybe_path orelse {
1020 std.debug.lockStdErr();1020 const w = std.debug.lockStderrWriter(&.{});
1021 const stderr = std.io.getStdErr();1021 std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {};
10221022 std.debug.unlockStderrWriter();
1023 std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {};
1024
1025 @panic("missing emit option for " ++ tag_name);1023 @panic("missing emit option for " ++ tag_name);
1026 };1024 };
10271025
1028 const path = generated_file.path orelse {1026 const path = generated_file.path orelse {
1029 std.debug.lockStdErr();1027 const w = std.debug.lockStderrWriter(&.{});
1030 const stderr = std.io.getStdErr();1028 std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {};
10311029 std.debug.unlockStderrWriter();
1032 std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {};
1033
1034 @panic(tag_name ++ " is null. Is there a missing step dependency?");1030 @panic(tag_name ++ " is null. Is there a missing step dependency?");
1035 };1031 };
10361032
...@@ -1542,7 +1538,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1542,7 +1538,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {1538 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
1543 if (compile.version) |version| {1539 if (compile.version) |version| {
1544 try zig_args.append("--version");1540 try zig_args.append("--version");
1545 try zig_args.append(b.fmt("{}", .{version}));1541 try zig_args.append(b.fmt("{f}", .{version}));
1546 }1542 }
15471543
1548 if (compile.rootModuleTarget().os.tag.isDarwin()) {1544 if (compile.rootModuleTarget().os.tag.isDarwin()) {
...@@ -1696,9 +1692,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1696,9 +1692,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
16961692
1697 if (compile.build_id orelse b.build_id) |build_id| {1693 if (compile.build_id orelse b.build_id) |build_id| {
1698 try zig_args.append(switch (build_id) {1694 try zig_args.append(switch (build_id) {
1699 .hexstring => |hs| b.fmt("--build-id=0x{s}", .{1695 .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)}),1696 .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
1703 });1697 });
1704 }1698 }
...@@ -1706,7 +1700,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1706,7 +1700,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1706 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|1700 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
1707 dir.getPath2(b, step)1701 dir.getPath2(b, step)
1708 else if (b.graph.zig_lib_directory.path) |_|1702 else if (b.graph.zig_lib_directory.path) |_|
1709 b.fmt("{}", .{b.graph.zig_lib_directory})1703 b.fmt("{f}", .{b.graph.zig_lib_directory})
1710 else1704 else
1711 null;1705 null;
17121706
...@@ -1746,8 +1740,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1746,8 +1740,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1746 }1740 }
17471741
1748 if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{1742 if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{
1749 "--error-limit",1743 "--error-limit", b.fmt("{d}", .{err_limit}),
1750 b.fmt("{}", .{err_limit}),
1751 });1744 });
17521745
1753 try addFlag(&zig_args, "incremental", b.graph.incremental);1746 try addFlag(&zig_args, "incremental", b.graph.incremental);
...@@ -1771,12 +1764,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1771,12 +1764,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1771 for (arg, 0..) |c, arg_idx| {1764 for (arg, 0..) |c, arg_idx| {
1772 if (c == '\\' or c == '"') {1765 if (c == '\\' or c == '"') {
1773 // Slow path for arguments that need to be escaped. We'll need to allocate and copy1766 // Slow path for arguments that need to be escaped. We'll need to allocate and copy
1774 var escaped = try ArrayList(u8).initCapacity(arena, arg.len + 1);1767 var escaped: std.ArrayListUnmanaged(u8) = .empty;
1775 const writer = escaped.writer();1768 try escaped.ensureTotalCapacityPrecise(arena, arg.len + 1);
1776 try writer.writeAll(arg[0..arg_idx]);1769 try escaped.appendSlice(arena, arg[0..arg_idx]);
1777 for (arg[arg_idx..]) |to_escape| {1770 for (arg[arg_idx..]) |to_escape| {
1778 if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\');1771 if (to_escape == '\\' or to_escape == '"') try escaped.append(arena, '\\');
1779 try writer.writeByte(to_escape);1772 try escaped.append(arena, to_escape);
1780 }1773 }
1781 escaped_args.appendAssumeCapacity(escaped.items);1774 escaped_args.appendAssumeCapacity(escaped.items);
1782 continue :arg_blk;1775 continue :arg_blk;
...@@ -1793,11 +1786,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1793,11 +1786,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1793 var args_hash: [Sha256.digest_length]u8 = undefined;1786 var args_hash: [Sha256.digest_length]u8 = undefined;
1794 Sha256.hash(args, &args_hash, .{});1787 Sha256.hash(args, &args_hash, .{});
1795 var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;1788 var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;
1796 _ = try std.fmt.bufPrint(1789 _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});
1797 &args_hex_hash,
1798 "{s}",
1799 .{std.fmt.fmtSliceHexLower(&args_hash)},
1800 );
18011790
1802 const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;1791 const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;
1803 try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });1792 try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });
...@@ -1836,7 +1825,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -1836,7 +1825,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
1836 // Update generated files1825 // Update generated files
1837 if (maybe_output_dir) |output_dir| {1826 if (maybe_output_dir) |output_dir| {
1838 if (compile.emit_directory) |lp| {1827 if (compile.emit_directory) |lp| {
1839 lp.path = b.fmt("{}", .{output_dir});1828 lp.path = b.fmt("{f}", .{output_dir});
1840 }1829 }
18411830
1842 // zig fmt: off1831 // zig fmt: off
...@@ -1970,20 +1959,23 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool)...@@ -1970,20 +1959,23 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool)
1970fn checkCompileErrors(compile: *Compile) !void {1959fn checkCompileErrors(compile: *Compile) !void {
1971 // Clear this field so that it does not get printed by the build runner.1960 // Clear this field so that it does not get printed by the build runner.
1972 const actual_eb = compile.step.result_error_bundle;1961 const actual_eb = compile.step.result_error_bundle;
1973 compile.step.result_error_bundle = std.zig.ErrorBundle.empty;1962 compile.step.result_error_bundle = .empty;
19741963
1975 const arena = compile.step.owner.allocator;1964 const arena = compile.step.owner.allocator;
19761965
1977 var actual_errors_list = std.ArrayList(u8).init(arena);1966 const actual_errors = ae: {
1978 try actual_eb.renderToWriter(.{1967 var aw: std.io.Writer.Allocating = .init(arena);
1979 .ttyconf = .no_color,1968 defer aw.deinit();
1980 .include_reference_trace = false,1969 try actual_eb.renderToWriter(.{
1981 .include_source_line = false,1970 .ttyconf = .no_color,
1982 }, actual_errors_list.writer());1971 .include_reference_trace = false,
1983 const actual_errors = try actual_errors_list.toOwnedSlice();1972 .include_source_line = false,
1973 }, &aw.writer);
1974 break :ae try aw.toOwnedSlice();
1975 };
19841976
1985 // Render the expected lines into a string that we can compare verbatim.1977 // Render the expected lines into a string that we can compare verbatim.
1986 var expected_generated = std.ArrayList(u8).init(arena);1978 var expected_generated: std.ArrayListUnmanaged(u8) = .empty;
1987 const expect_errors = compile.expect_errors.?;1979 const expect_errors = compile.expect_errors.?;
19881980
1989 var actual_line_it = mem.splitScalar(u8, actual_errors, '\n');1981 var actual_line_it = mem.splitScalar(u8, actual_errors, '\n');
...@@ -2042,17 +2034,17 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -2042,17 +2034,17 @@ fn checkCompileErrors(compile: *Compile) !void {
2042 .exact => |expect_lines| {2034 .exact => |expect_lines| {
2043 for (expect_lines) |expect_line| {2035 for (expect_lines) |expect_line| {
2044 const actual_line = actual_line_it.next() orelse {2036 const actual_line = actual_line_it.next() orelse {
2045 try expected_generated.appendSlice(expect_line);2037 try expected_generated.appendSlice(arena, expect_line);
2046 try expected_generated.append('\n');2038 try expected_generated.append(arena, '\n');
2047 continue;2039 continue;
2048 };2040 };
2049 if (matchCompileError(actual_line, expect_line)) {2041 if (matchCompileError(actual_line, expect_line)) {
2050 try expected_generated.appendSlice(actual_line);2042 try expected_generated.appendSlice(arena, actual_line);
2051 try expected_generated.append('\n');2043 try expected_generated.append(arena, '\n');
2052 continue;2044 continue;
2053 }2045 }
2054 try expected_generated.appendSlice(expect_line);2046 try expected_generated.appendSlice(arena, expect_line);
2055 try expected_generated.append('\n');2047 try expected_generated.append(arena, '\n');
2056 }2048 }
20572049
2058 if (mem.eql(u8, expected_generated.items, actual_errors)) return;2050 if (mem.eql(u8, expected_generated.items, actual_errors)) return;
lib/std/Build/Step/ConfigHeader.zig+92-140
...@@ -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.writer;
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.writer;
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 aw: std.io.Writer.Allocating = .init(allocator);
805 defer output.deinit();757 defer aw.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(&aw.writer, 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, aw.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+148-113
...@@ -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
...@@ -381,7 +415,8 @@ pub fn addOptionPath(...@@ -381,7 +415,8 @@ pub fn addOptionPath(
381 name: []const u8,415 name: []const u8,
382 path: LazyPath,416 path: LazyPath,
383) void {417) void {
384 options.args.append(.{418 const arena = options.step.owner.allocator;
419 options.args.append(arena, .{
385 .name = options.step.owner.dupe(name),420 .name = options.step.owner.dupe(name),
386 .path = path.dupe(options.step.owner),421 .path = path.dupe(options.step.owner),
387 }) catch @panic("OOM");422 }) catch @panic("OOM");
...@@ -440,7 +475,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -440,7 +475,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
440 error.FileNotFound => {475 error.FileNotFound => {
441 const sub_dirname = fs.path.dirname(sub_path).?;476 const sub_dirname = fs.path.dirname(sub_path).?;
442 b.cache_root.handle.makePath(sub_dirname) catch |e| {477 b.cache_root.handle.makePath(sub_dirname) catch |e| {
443 return step.fail("unable to make path '{}{s}': {s}", .{478 return step.fail("unable to make path '{f}{s}': {s}", .{
444 b.cache_root, sub_dirname, @errorName(e),479 b.cache_root, sub_dirname, @errorName(e),
445 });480 });
446 };481 };
...@@ -452,13 +487,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -452,13 +487,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
452 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;487 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
453488
454 b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {489 b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {
455 return step.fail("unable to make temporary directory '{}{s}': {s}", .{490 return step.fail("unable to make temporary directory '{f}{s}': {s}", .{
456 b.cache_root, tmp_sub_path_dirname, @errorName(err),491 b.cache_root, tmp_sub_path_dirname, @errorName(err),
457 });492 });
458 };493 };
459494
460 b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {495 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}", .{496 return step.fail("unable to write options to '{f}{s}': {s}", .{
462 b.cache_root, tmp_sub_path, @errorName(err),497 b.cache_root, tmp_sub_path, @errorName(err),
463 });498 });
464 };499 };
...@@ -467,7 +502,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -467,7 +502,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
467 error.PathAlreadyExists => {502 error.PathAlreadyExists => {
468 // Other process beat us to it. Clean up the temp file.503 // Other process beat us to it. Clean up the temp file.
469 b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {504 b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {
470 try step.addError("warning: unable to delete temp file '{}{s}': {s}", .{505 try step.addError("warning: unable to delete temp file '{f}{s}': {s}", .{
471 b.cache_root, tmp_sub_path, @errorName(e),506 b.cache_root, tmp_sub_path, @errorName(e),
472 });507 });
473 };508 };
...@@ -475,7 +510,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -475,7 +510,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
475 return;510 return;
476 },511 },
477 else => {512 else => {
478 return step.fail("unable to rename options from '{}{s}' to '{}{s}': {s}", .{513 return step.fail("unable to rename options from '{f}{s}' to '{f}{s}': {s}", .{
479 b.cache_root, tmp_sub_path,514 b.cache_root, tmp_sub_path,
480 b.cache_root, sub_path,515 b.cache_root, sub_path,
481 @errorName(err),516 @errorName(err),
...@@ -483,7 +518,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -483,7 +518,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
483 },518 },
484 };519 };
485 },520 },
486 else => |e| return step.fail("unable to access options file '{}{s}': {s}", .{521 else => |e| return step.fail("unable to access options file '{f}{s}': {s}", .{
487 b.cache_root, sub_path, @errorName(e),522 b.cache_root, sub_path, @errorName(e),
488 }),523 }),
489 }524 }
...@@ -643,5 +678,5 @@ test Options {...@@ -643,5 +678,5 @@ test Options {
643 \\678 \\
644 , options.contents.items);679 , options.contents.items);
645680
646 _ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(0), .zig);681 _ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(arena.allocator(), 0), .zig);
647}682}
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+32-1
...@@ -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()
...@@ -451,7 +452,7 @@ pub fn start(options: Options) Node {...@@ -451,7 +452,7 @@ pub fn start(options: Options) Node {
451 if (options.disable_printing) {452 if (options.disable_printing) {
452 return Node.none;453 return Node.none;
453 }454 }
454 const stderr = std.io.getStdErr();455 const stderr: std.fs.File = .stderr();
455 global_progress.terminal = stderr;456 global_progress.terminal = stderr;
456 if (stderr.getOrEnableAnsiEscapeSupport()) {457 if (stderr.getOrEnableAnsiEscapeSupport()) {
457 global_progress.terminal_mode = .ansi_escape_codes;458 global_progress.terminal_mode = .ansi_escape_codes;
...@@ -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.io.getStdOut().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-14
...@@ -150,17 +150,10 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {...@@ -150,17 +150,10 @@ 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) std.io.Writer.Error!void {
154 self: Version,154 try w.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
155 comptime fmt: []const u8,155 if (self.pre) |pre| try w.print("-{s}", .{pre});
156 options: std.fmt.FormatOptions,156 if (self.build) |build| try w.print("+{s}", .{build});
157 out_stream: anytype,
158) !void {
159 _ = options;
160 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
161 try std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
162 if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});
163 if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});
164}157}
165158
166const expect = std.testing.expect;159const expect = std.testing.expect;
...@@ -202,7 +195,7 @@ test format {...@@ -202,7 +195,7 @@ test format {
202 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",195 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",
203 "5.4.0-1018-raspi",196 "5.4.0-1018-raspi",
204 "5.7.123",197 "5.7.123",
205 }) |valid| try std.testing.expectFmt(valid, "{}", .{try parse(valid)});198 }) |valid| try std.testing.expectFmt(valid, "{f}", .{try parse(valid)});
206199
207 // Invalid version strings should be rejected.200 // Invalid version strings should be rejected.
208 for ([_][]const u8{201 for ([_][]const u8{
...@@ -269,12 +262,12 @@ test format {...@@ -269,12 +262,12 @@ test format {
269 // Valid version string that may overflow.262 // Valid version string that may overflow.
270 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";263 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";
271 if (parse(big_valid)) |ver| {264 if (parse(big_valid)) |ver| {
272 try std.testing.expectFmt(big_valid, "{}", .{ver});265 try std.testing.expectFmt(big_valid, "{f}", .{ver});
273 } else |err| try expect(err == error.Overflow);266 } else |err| try expect(err == error.Overflow);
274267
275 // Invalid version string that may overflow.268 // Invalid version string that may overflow.
276 const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";269 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 |_| {}270 if (parse(big_invalid)) |ver| std.debug.panic("expected error, found {f}", .{ver}) else |_| {}
278}271}
279272
280test "precedence" {273test "precedence" {
lib/std/Target.zig+7-23
...@@ -301,29 +301,13 @@ pub const Os = struct {...@@ -301,29 +301,13 @@ 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(wv: WindowsVersion, w: *std.io.Writer) std.io.Writer.Error!void {
305 ver: WindowsVersion,305 if (std.enums.tagName(WindowsVersion, wv)) |name| {
306 comptime fmt_str: []const u8,306 var vecs: [2][]const u8 = .{ ".", name };
307 _: std.fmt.FormatOptions,307 return w.writeVecAll(&vecs);
308 writer: anytype,308 } else {
309 ) @TypeOf(writer).Error!void {309 return w.print("@enumFromInt(0x{X:0>8})", .{wv});
310 const maybe_name = std.enums.tagName(WindowsVersion, ver);310 }
311 if (comptime std.mem.eql(u8, fmt_str, "s")) {
312 if (maybe_name) |name|
313 try writer.print(".{s}", .{name})
314 else
315 try writer.print(".{d}", .{@intFromEnum(ver)});
316 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {
317 if (maybe_name) |name|
318 try writer.print(".{s}", .{name})
319 else
320 try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
321 } else if (fmt_str.len == 0) {
322 if (maybe_name) |name|
323 try writer.print("WindowsVersion.{s}", .{name})
324 else
325 try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
326 } else std.fmt.invalidFmtError(fmt_str, ver);
327 }311 }
328 };312 };
329313
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+153-129
...@@ -1,6 +1,10 @@...@@ -1,6 +1,10 @@
1//! Uniform Resource Identifier (URI) parsing roughly adhering to <https://tools.ietf.org/html/rfc3986>.1//! Uniform Resource Identifier (URI) parsing roughly adhering to <https://tools.ietf.org/html/rfc3986>.
2//! Does not do perfect grammar and character class checking, but should be robust against URIs in the wild.2//! Does not do perfect grammar and character class checking, but should be robust against URIs in the wild.
33
4const std = @import("std.zig");
5const testing = std.testing;
6const Uri = @This();
7
4scheme: []const u8,8scheme: []const u8,
5user: ?Component = null,9user: ?Component = null,
6password: ?Component = null,10password: ?Component = null,
...@@ -34,27 +38,15 @@ pub const Component = union(enum) {...@@ -34,27 +38,15 @@ pub const Component = union(enum) {
34 return switch (component) {38 return switch (component) {
35 .raw => |raw| raw,39 .raw => |raw| raw,
36 .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|40 .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|
37 try std.fmt.allocPrint(arena, "{raw}", .{component})41 try std.fmt.allocPrint(arena, "{f}", .{std.fmt.alt(component, .formatRaw)})
38 else42 else
39 percent_encoded,43 percent_encoded,
40 };44 };
41 }45 }
4246
43 pub fn format(47 pub fn formatRaw(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
44 component: Component,48 switch (component) {
45 comptime fmt_str: []const u8,49 .raw => |raw| try w.writeAll(raw),
46 _: std.fmt.FormatOptions,
47 writer: anytype,
48 ) @TypeOf(writer).Error!void {
49 if (fmt_str.len == 0) {
50 try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{
51 @tagName(component),
52 std.zig.fmtEscapes(switch (component) {
53 .raw, .percent_encoded => |string| string,
54 }),
55 });
56 } else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) {
57 .raw => |raw| try writer.writeAll(raw),
58 .percent_encoded => |percent_encoded| {50 .percent_encoded => |percent_encoded| {
59 var start: usize = 0;51 var start: usize = 0;
60 var index: usize = 0;52 var index: usize = 0;
...@@ -63,51 +55,75 @@ pub const Component = union(enum) {...@@ -63,51 +55,75 @@ pub const Component = union(enum) {
63 if (percent_encoded.len - index < 2) continue;55 if (percent_encoded.len - index < 2) continue;
64 const percent_encoded_char =56 const percent_encoded_char =
65 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;57 std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
66 try writer.print("{s}{c}", .{58 try w.print("{s}{c}", .{
67 percent_encoded[start..percent],59 percent_encoded[start..percent],
68 percent_encoded_char,60 percent_encoded_char,
69 });61 });
70 start = percent + 3;62 start = percent + 3;
71 index = percent + 3;63 index = percent + 3;
72 }64 }
73 try writer.writeAll(percent_encoded[start..]);65 try w.writeAll(percent_encoded[start..]);
74 },66 },
75 } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {67 }
76 .raw => |raw| try percentEncode(writer, raw, isUnreserved),68 }
77 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),69
78 } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {70 pub fn formatEscaped(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
79 .raw => |raw| try percentEncode(writer, raw, isUserChar),71 switch (component) {
80 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),72 .raw => |raw| try percentEncode(w, raw, isUnreserved),
81 } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {73 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
82 .raw => |raw| try percentEncode(writer, raw, isPasswordChar),74 }
83 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),75 }
84 } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {76
85 .raw => |raw| try percentEncode(writer, raw, isHostChar),77 pub fn formatUser(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
86 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),78 switch (component) {
87 } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {79 .raw => |raw| try percentEncode(w, raw, isUserChar),
88 .raw => |raw| try percentEncode(writer, raw, isPathChar),80 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
89 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),81 }
90 } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {82 }
91 .raw => |raw| try percentEncode(writer, raw, isQueryChar),83
92 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),84 pub fn formatPassword(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
93 } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {85 switch (component) {
94 .raw => |raw| try percentEncode(writer, raw, isFragmentChar),86 .raw => |raw| try percentEncode(w, raw, isPasswordChar),
95 .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),87 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
96 } else @compileError("invalid format string '" ++ fmt_str ++ "'");88 }
97 }89 }
9890
99 pub fn percentEncode(91 pub fn formatHost(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
100 writer: anytype,92 switch (component) {
101 raw: []const u8,93 .raw => |raw| try percentEncode(w, raw, isHostChar),
102 comptime isValidChar: fn (u8) bool,94 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
103 ) @TypeOf(writer).Error!void {95 }
96 }
97
98 pub fn formatPath(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
99 switch (component) {
100 .raw => |raw| try percentEncode(w, raw, isPathChar),
101 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
102 }
103 }
104
105 pub fn formatQuery(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
106 switch (component) {
107 .raw => |raw| try percentEncode(w, raw, isQueryChar),
108 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
109 }
110 }
111
112 pub fn formatFragment(component: Component, w: *std.io.Writer) std.io.Writer.Error!void {
113 switch (component) {
114 .raw => |raw| try percentEncode(w, raw, isFragmentChar),
115 .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
116 }
117 }
118
119 pub fn percentEncode(w: *std.io.Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) std.io.Writer.Error!void {
104 var start: usize = 0;120 var start: usize = 0;
105 for (raw, 0..) |char, index| {121 for (raw, 0..) |char, index| {
106 if (isValidChar(char)) continue;122 if (isValidChar(char)) continue;
107 try writer.print("{s}%{X:0>2}", .{ raw[start..index], char });123 try w.print("{s}%{X:0>2}", .{ raw[start..index], char });
108 start = index + 1;124 start = index + 1;
109 }125 }
110 try writer.writeAll(raw[start..]);126 try w.writeAll(raw[start..]);
111 }127 }
112};128};
113129
...@@ -224,91 +240,91 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {...@@ -224,91 +240,91 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
224 return uri;240 return uri;
225}241}
226242
227pub const WriteToStreamOptions = struct {243pub fn format(uri: *const Uri, writer: *std.io.Writer) std.io.Writer.Error!void {
228 /// When true, include the scheme part of the URI.244 return writeToStream(uri, writer, .all);
229 scheme: bool = false,245}
230
231 /// When true, include the user and password part of the URI. Ignored if `authority` is false.
232 authentication: bool = false,
233
234 /// When true, include the authority part of the URI.
235 authority: bool = false,
236
237 /// When true, include the path part of the URI.
238 path: bool = false,
239
240 /// When true, include the query part of the URI. Ignored when `path` is false.
241 query: bool = false,
242
243 /// When true, include the fragment part of the URI. Ignored when `path` is false.
244 fragment: bool = false,
245
246 /// When true, include the port part of the URI. Ignored when `port` is null.
247 port: bool = true,
248};
249246
250pub fn writeToStream(247pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void {
251 uri: Uri,248 if (flags.scheme) {
252 options: WriteToStreamOptions,
253 writer: anytype,
254) @TypeOf(writer).Error!void {
255 if (options.scheme) {
256 try writer.print("{s}:", .{uri.scheme});249 try writer.print("{s}:", .{uri.scheme});
257 if (options.authority and uri.host != null) {250 if (flags.authority and uri.host != null) {
258 try writer.writeAll("//");251 try writer.writeAll("//");
259 }252 }
260 }253 }
261 if (options.authority) {254 if (flags.authority) {
262 if (options.authentication and uri.host != null) {255 if (flags.authentication and uri.host != null) {
263 if (uri.user) |user| {256 if (uri.user) |user| {
264 try writer.print("{user}", .{user});257 try user.formatUser(writer);
265 if (uri.password) |password| {258 if (uri.password) |password| {
266 try writer.print(":{password}", .{password});259 try writer.writeByte(':');
260 try password.formatPassword(writer);
267 }261 }
268 try writer.writeByte('@');262 try writer.writeByte('@');
269 }263 }
270 }264 }
271 if (uri.host) |host| {265 if (uri.host) |host| {
272 try writer.print("{host}", .{host});266 try host.formatHost(writer);
273 if (options.port) {267 if (flags.port) {
274 if (uri.port) |port| try writer.print(":{d}", .{port});268 if (uri.port) |port| try writer.print(":{d}", .{port});
275 }269 }
276 }270 }
277 }271 }
278 if (options.path) {272 if (flags.path) {
279 try writer.print("{path}", .{273 const uri_path: Component = if (uri.path.isEmpty()) .{ .percent_encoded = "/" } else uri.path;
280 if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,274 try uri_path.formatPath(writer);
281 });275 if (flags.query) {
282 if (options.query) {276 if (uri.query) |query| {
283 if (uri.query) |query| try writer.print("?{query}", .{query});277 try writer.writeByte('?');
278 try query.formatQuery(writer);
279 }
284 }280 }
285 if (options.fragment) {281 if (flags.fragment) {
286 if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment});282 if (uri.fragment) |fragment| {
283 try writer.writeByte('#');
284 try fragment.formatFragment(writer);
285 }
287 }286 }
288 }287 }
289}288}
290289
291pub fn format(290pub const Format = struct {
292 uri: Uri,291 uri: *const Uri,
293 comptime fmt_str: []const u8,292 flags: Flags = .{},
294 _: std.fmt.FormatOptions,293
295 writer: anytype,294 pub const Flags = struct {
296) @TypeOf(writer).Error!void {295 /// When true, include the scheme part of the URI.
297 const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;296 scheme: bool = false,
298 const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;297 /// When true, include the user and password part of the URI. Ignored if `authority` is false.
299 const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;298 authentication: bool = false,
300 const path = comptime std.mem.indexOfScalar(u8, fmt_str, '/') != null or fmt_str.len == 0;299 /// When true, include the authority part of the URI.
301 const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;300 authority: bool = false,
302 const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0;301 /// When true, include the path part of the URI.
303302 path: bool = false,
304 return writeToStream(uri, .{303 /// When true, include the query part of the URI. Ignored when `path` is false.
305 .scheme = scheme,304 query: bool = false,
306 .authentication = authentication,305 /// When true, include the fragment part of the URI. Ignored when `path` is false.
307 .authority = authority,306 fragment: bool = false,
308 .path = path,307 /// When true, include the port part of the URI. Ignored when `port` is null.
309 .query = query,308 port: bool = true,
310 .fragment = fragment,309
311 }, writer);310 pub const all: Flags = .{
311 .scheme = true,
312 .authentication = true,
313 .authority = true,
314 .path = true,
315 .query = true,
316 .fragment = true,
317 .port = true,
318 };
319 };
320
321 pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
322 return writeToStream(f.uri, writer, f.flags);
323 }
324};
325
326pub fn fmt(uri: *const Uri, flags: Format.Flags) std.fmt.Formatter(Format, Format.default) {
327 return .{ .data = .{ .uri = uri, .flags = flags } };
312}328}
313329
314/// Parses the URI or returns an error.330/// Parses the URI or returns an error.
...@@ -445,14 +461,13 @@ test remove_dot_segments {...@@ -445,14 +461,13 @@ test remove_dot_segments {
445461
446/// 5.2.3. Merge Paths462/// 5.2.3. Merge Paths
447fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {463fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
448 var aux = std.io.fixedBufferStream(aux_buf.*);464 var aux: std.io.Writer = .fixed(aux_buf.*);
449 if (!base.isEmpty()) {465 if (!base.isEmpty()) {
450 try aux.writer().print("{path}", .{base});466 base.formatPath(&aux) catch return error.NoSpaceLeft;
451 aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse467 aux.end = std.mem.lastIndexOfScalar(u8, aux.buffered(), '/') orelse return remove_dot_segments(new);
452 return remove_dot_segments(new);
453 }468 }
454 try aux.writer().print("/{s}", .{new});469 aux.print("/{s}", .{new}) catch return error.NoSpaceLeft;
455 const merged_path = remove_dot_segments(aux.getWritten());470 const merged_path = remove_dot_segments(aux.buffered());
456 aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..];471 aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..];
457 return merged_path;472 return merged_path;
458}473}
...@@ -812,8 +827,11 @@ test "Special test" {...@@ -812,8 +827,11 @@ test "Special test" {
812test "URI percent encoding" {827test "URI percent encoding" {
813 try std.testing.expectFmt(828 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",829 "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad",
815 "{%}",830 "{f}",
816 .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},831 .{std.fmt.alt(
832 @as(Component, .{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }),
833 .formatEscaped,
834 )},
817 );835 );
818}836}
819837
...@@ -822,7 +840,10 @@ test "URI percent decoding" {...@@ -822,7 +840,10 @@ test "URI percent decoding" {
822 const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";840 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".*;841 var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*;
824842
825 try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});843 try std.testing.expectFmt(expected, "{f}", .{std.fmt.alt(
844 @as(Component, .{ .percent_encoded = &input }),
845 .formatRaw,
846 )});
826847
827 var output: [expected.len]u8 = undefined;848 var output: [expected.len]u8 = undefined;
828 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);849 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
...@@ -834,7 +855,10 @@ test "URI percent decoding" {...@@ -834,7 +855,10 @@ test "URI percent decoding" {
834 const expected = "/abc%";855 const expected = "/abc%";
835 var input = expected.*;856 var input = expected.*;
836857
837 try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});858 try std.testing.expectFmt(expected, "{f}", .{std.fmt.alt(
859 @as(Component, .{ .percent_encoded = &input }),
860 .formatRaw,
861 )});
838862
839 var output: [expected.len]u8 = undefined;863 var output: [expected.len]u8 = undefined;
840 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);864 try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
...@@ -848,7 +872,9 @@ test "URI query encoding" {...@@ -848,7 +872,9 @@ test "URI query encoding" {
848 const parsed = try Uri.parse(address);872 const parsed = try Uri.parse(address);
849873
850 // format the URI to percent encode it874 // format the URI to percent encode it
851 try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{/?}", .{parsed});875 try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{f}", .{
876 parsed.fmt(.{ .path = true, .query = true }),
877 });
852}878}
853879
854test "format" {880test "format" {
...@@ -862,7 +888,9 @@ test "format" {...@@ -862,7 +888,9 @@ test "format" {
862 .query = null,888 .query = null,
863 .fragment = null,889 .fragment = null,
864 };890 };
865 try std.testing.expectFmt("file:/foo/bar/baz", "{;/?#}", .{uri});891 try std.testing.expectFmt("file:/foo/bar/baz", "{f}", .{
892 uri.fmt(.{ .scheme = true, .path = true, .query = true, .fragment = true }),
893 });
866}894}
867895
868test "URI malformed input" {896test "URI malformed input" {
...@@ -870,7 +898,3 @@ test "URI malformed input" {...@@ -870,7 +898,3 @@ test "URI malformed input" {
870 try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://]@["));898 try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://]@["));
871 try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://lo]s\x85hc@[/8\x10?0Q"));899 try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://lo]s\x85hc@[/8\x10?0Q"));
872}900}
873
874const std = @import("std.zig");
875const testing = std.testing;
876const Uri = @This();
lib/std/array_list.zig+37-18
...@@ -338,11 +338,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty...@@ -338,11 +338,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty
338 @memcpy(self.items[old_len..][0..items.len], items);338 @memcpy(self.items[old_len..][0..items.len], items);
339 }339 }
340340
341 pub const Writer = if (T != u8)341 pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
342 @compileError("The Writer interface is only defined for ArrayList(u8) " ++342 const gpa = self.allocator;
343 "but the given type is ArrayList(" ++ @typeName(T) ++ ")")343 var unmanaged = self.moveToUnmanaged();
344 else344 defer self.* = unmanaged.toManaged(gpa);
345 std.io.Writer(*Self, Allocator.Error, appendWrite);345 try unmanaged.print(gpa, fmt, args);
346 }
347
348 pub const Writer = if (T != u8) void else std.io.GenericWriter(*Self, Allocator.Error, appendWrite);
346349
347 /// Initializes a Writer which will append to the list.350 /// Initializes a Writer which will append to the list.
348 pub fn writer(self: *Self) Writer {351 pub fn writer(self: *Self) Writer {
...@@ -350,14 +353,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty...@@ -350,14 +353,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty
350 }353 }
351354
352 /// Same as `append` except it returns the number of bytes written, which is always the same355 /// Same as `append` except it returns the number of bytes written, which is always the same
353 /// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.356 /// as `m.len`. The purpose of this function existing is to match `std.io.GenericWriter` API.
354 /// Invalidates element pointers if additional memory is needed.357 /// Invalidates element pointers if additional memory is needed.
355 fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize {358 fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize {
356 try self.appendSlice(m);359 try self.appendSlice(m);
357 return m.len;360 return m.len;
358 }361 }
359362
360 pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed);363 pub const FixedWriter = std.io.GenericWriter(*Self, Allocator.Error, appendWriteFixed);
361364
362 /// Initializes a Writer which will append to the list but will return365 /// Initializes a Writer which will append to the list but will return
363 /// `error.OutOfMemory` rather than increasing capacity.366 /// `error.OutOfMemory` rather than increasing capacity.
...@@ -365,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty...@@ -365,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty
365 return .{ .context = self };368 return .{ .context = self };
366 }369 }
367370
368 /// The purpose of this function existing is to match `std.io.Writer` API.371 /// The purpose of this function existing is to match `std.io.GenericWriter` API.
369 fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {372 fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {
370 const available_capacity = self.capacity - self.items.len;373 const available_capacity = self.capacity - self.items.len;
371 if (m.len > available_capacity)374 if (m.len > available_capacity)
...@@ -933,40 +936,56 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -933,40 +936,56 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
933 @memcpy(self.items[old_len..][0..items.len], items);936 @memcpy(self.items[old_len..][0..items.len], items);
934 }937 }
935938
939 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
940 comptime assert(T == u8);
941 try self.ensureUnusedCapacity(gpa, fmt.len);
942 var aw: std.io.Writer.Allocating = .fromArrayList(gpa, self);
943 defer self.* = aw.toArrayList();
944 return aw.writer.print(fmt, args) catch |err| switch (err) {
945 error.WriteFailed => return error.OutOfMemory,
946 };
947 }
948
949 pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void {
950 comptime assert(T == u8);
951 var w: std.io.Writer = .fixed(self.unusedCapacitySlice());
952 w.print(fmt, args) catch unreachable;
953 self.items.len += w.end;
954 }
955
956 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
936 pub const WriterContext = struct {957 pub const WriterContext = struct {
937 self: *Self,958 self: *Self,
938 allocator: Allocator,959 allocator: Allocator,
939 };960 };
940961
962 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
941 pub const Writer = if (T != u8)963 pub const Writer = if (T != u8)
942 @compileError("The Writer interface is only defined for ArrayList(u8) " ++964 @compileError("The Writer interface is only defined for ArrayList(u8) " ++
943 "but the given type is ArrayList(" ++ @typeName(T) ++ ")")965 "but the given type is ArrayList(" ++ @typeName(T) ++ ")")
944 else966 else
945 std.io.Writer(WriterContext, Allocator.Error, appendWrite);967 std.io.GenericWriter(WriterContext, Allocator.Error, appendWrite);
946968
947 /// Initializes a Writer which will append to the list.969 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
948 pub fn writer(self: *Self, gpa: Allocator) Writer {970 pub fn writer(self: *Self, gpa: Allocator) Writer {
949 return .{ .context = .{ .self = self, .allocator = gpa } };971 return .{ .context = .{ .self = self, .allocator = gpa } };
950 }972 }
951973
952 /// Same as `append` except it returns the number of bytes written,974 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
953 /// which is always the same as `m.len`. The purpose of this function
954 /// existing is to match `std.io.Writer` API.
955 /// Invalidates element pointers if additional memory is needed.
956 fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize {975 fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize {
957 try context.self.appendSlice(context.allocator, m);976 try context.self.appendSlice(context.allocator, m);
958 return m.len;977 return m.len;
959 }978 }
960979
961 pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed);980 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
981 pub const FixedWriter = std.io.GenericWriter(*Self, Allocator.Error, appendWriteFixed);
962982
963 /// Initializes a Writer which will append to the list but will return983 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
964 /// `error.OutOfMemory` rather than increasing capacity.
965 pub fn fixedWriter(self: *Self) FixedWriter {984 pub fn fixedWriter(self: *Self) FixedWriter {
966 return .{ .context = self };985 return .{ .context = self };
967 }986 }
968987
969 /// The purpose of this function existing is to match `std.io.Writer` API.988 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
970 fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {989 fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {
971 const available_capacity = self.capacity - self.items.len;990 const available_capacity = self.capacity - self.items.len;
972 if (m.len > available_capacity)991 if (m.len > available_capacity)
lib/std/ascii.zig+45
...@@ -10,6 +10,10 @@...@@ -10,6 +10,10 @@
1010
11const std = @import("std");11const std = @import("std");
1212
13pub const lowercase = "abcdefghijklmnopqrstuvwxyz";
14pub const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
15pub const letters = lowercase ++ uppercase;
16
13/// The C0 control codes of the ASCII encoding.17/// The C0 control codes of the ASCII encoding.
14///18///
15/// See also: https://en.wikipedia.org/wiki/C0_and_C1_control_codes and `isControl`19/// See also: https://en.wikipedia.org/wiki/C0_and_C1_control_codes and `isControl`
...@@ -435,3 +439,44 @@ pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {...@@ -435,3 +439,44 @@ pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {
435pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {439pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {
436 return orderIgnoreCase(lhs, rhs) == .lt;440 return orderIgnoreCase(lhs, rhs) == .lt;
437}441}
442
443pub const HexEscape = struct {
444 bytes: []const u8,
445 charset: *const [16]u8,
446
447 pub const upper_charset = "0123456789ABCDEF";
448 pub const lower_charset = "0123456789abcdef";
449
450 pub fn format(se: HexEscape, w: *std.io.Writer) std.io.Writer.Error!void {
451 const charset = se.charset;
452
453 var buf: [4]u8 = undefined;
454 buf[0] = '\\';
455 buf[1] = 'x';
456
457 for (se.bytes) |c| {
458 if (std.ascii.isPrint(c)) {
459 try w.writeByte(c);
460 } else {
461 buf[2] = charset[c >> 4];
462 buf[3] = charset[c & 15];
463 try w.writeAll(&buf);
464 }
465 }
466 }
467};
468
469/// Replaces non-ASCII bytes with hex escapes.
470pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Formatter(HexEscape, HexEscape.format) {
471 return .{ .data = .{ .bytes = bytes, .charset = switch (case) {
472 .lower => HexEscape.lower_charset,
473 .upper => HexEscape.upper_charset,
474 } } };
475}
476
477test hexEscape {
478 try std.testing.expectFmt("abc 123", "{f}", .{hexEscape("abc 123", .lower)});
479 try std.testing.expectFmt("ab\\xffc", "{f}", .{hexEscape("ab\xffc", .lower)});
480 try std.testing.expectFmt("abc 123", "{f}", .{hexEscape("abc 123", .upper)});
481 try std.testing.expectFmt("ab\\xFFc", "{f}", .{hexEscape("ab\xffc", .upper)});
482}
lib/std/base64.zig+3-3
...@@ -108,7 +108,7 @@ pub const Base64Encoder = struct {...@@ -108,7 +108,7 @@ pub const Base64Encoder = struct {
108 }108 }
109 }109 }
110110
111 // dest must be compatible with std.io.Writer's writeAll interface111 // dest must be compatible with std.io.GenericWriter's writeAll interface
112 pub fn encodeWriter(encoder: *const Base64Encoder, dest: anytype, source: []const u8) !void {112 pub fn encodeWriter(encoder: *const Base64Encoder, dest: anytype, source: []const u8) !void {
113 var chunker = window(u8, source, 3, 3);113 var chunker = window(u8, source, 3, 3);
114 while (chunker.next()) |chunk| {114 while (chunker.next()) |chunk| {
...@@ -118,8 +118,8 @@ pub const Base64Encoder = struct {...@@ -118,8 +118,8 @@ pub const Base64Encoder = struct {
118 }118 }
119 }119 }
120120
121 // destWriter must be compatible with std.io.Writer's writeAll interface121 // destWriter must be compatible with std.io.GenericWriter's writeAll interface
122 // sourceReader must be compatible with std.io.Reader's read interface122 // sourceReader must be compatible with `std.io.GenericReader` read interface
123 pub fn encodeFromReaderToWriter(encoder: *const Base64Encoder, destWriter: anytype, sourceReader: anytype) !void {123 pub fn encodeFromReaderToWriter(encoder: *const Base64Encoder, destWriter: anytype, sourceReader: anytype) !void {
124 while (true) {124 while (true) {
125 var tempSource: [3]u8 = undefined;125 var tempSource: [3]u8 = undefined;
lib/std/bounded_array.zig+2-2
...@@ -277,7 +277,7 @@ pub fn BoundedArrayAligned(...@@ -277,7 +277,7 @@ pub fn BoundedArrayAligned(
277 @compileError("The Writer interface is only defined for BoundedArray(u8, ...) " ++277 @compileError("The Writer interface is only defined for BoundedArray(u8, ...) " ++
278 "but the given type is BoundedArray(" ++ @typeName(T) ++ ", ...)")278 "but the given type is BoundedArray(" ++ @typeName(T) ++ ", ...)")
279 else279 else
280 std.io.Writer(*Self, error{Overflow}, appendWrite);280 std.io.GenericWriter(*Self, error{Overflow}, appendWrite);
281281
282 /// Initializes a writer which will write into the array.282 /// Initializes a writer which will write into the array.
283 pub fn writer(self: *Self) Writer {283 pub fn writer(self: *Self) Writer {
...@@ -285,7 +285,7 @@ pub fn BoundedArrayAligned(...@@ -285,7 +285,7 @@ pub fn BoundedArrayAligned(
285 }285 }
286286
287 /// Same as `appendSlice` except it returns the number of bytes written, which is always the same287 /// Same as `appendSlice` except it returns the number of bytes written, which is always the same
288 /// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.288 /// as `m.len`. The purpose of this function existing is to match `std.io.GenericWriter` API.
289 fn appendWrite(self: *Self, m: []const u8) error{Overflow}!usize {289 fn appendWrite(self: *Self, m: []const u8) error{Overflow}!usize {
290 try self.appendSlice(m);290 try self.appendSlice(m);
291 return m.len;291 return m.len;
lib/std/builtin.zig+2-10
...@@ -34,24 +34,16 @@ pub const StackTrace = struct {...@@ -34,24 +34,16 @@ 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) std.io.Writer.Error!void {
38 self: StackTrace,
39 comptime fmt: []const u8,
40 options: std.fmt.FormatOptions,
41 writer: anytype,
42 ) !void {
43 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
44
45 // TODO: re-evaluate whether to use format() methods at all.38 // TODO: re-evaluate whether to use format() methods at all.
46 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly39 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly
47 // where it tries to call detectTTYConfig here.40 // where it tries to call detectTTYConfig here.
48 if (builtin.os.tag == .freestanding) return;41 if (builtin.os.tag == .freestanding) return;
4942
50 _ = options;
51 const debug_info = std.debug.getSelfDebugInfo() catch |err| {43 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)});44 return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
53 };45 };
54 const tty_config = std.io.tty.detectConfig(std.io.getStdErr());46 const tty_config = std.io.tty.detectConfig(std.fs.File.stderr());
55 try writer.writeAll("\n");47 try writer.writeAll("\n");
56 std.debug.writeStackTrace(self, writer, debug_info, tty_config) catch |err| {48 std.debug.writeStackTrace(self, writer, debug_info, tty_config) catch |err| {
57 try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)});49 try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)});
lib/std/compress.zig+2-2
...@@ -16,7 +16,7 @@ pub fn HashedReader(ReaderType: type, HasherType: type) type {...@@ -16,7 +16,7 @@ pub fn HashedReader(ReaderType: type, HasherType: type) type {
16 hasher: HasherType,16 hasher: HasherType,
1717
18 pub const Error = ReaderType.Error;18 pub const Error = ReaderType.Error;
19 pub const Reader = std.io.Reader(*@This(), Error, read);19 pub const Reader = std.io.GenericReader(*@This(), Error, read);
2020
21 pub fn read(self: *@This(), buf: []u8) Error!usize {21 pub fn read(self: *@This(), buf: []u8) Error!usize {
22 const amt = try self.child_reader.read(buf);22 const amt = try self.child_reader.read(buf);
...@@ -43,7 +43,7 @@ pub fn HashedWriter(WriterType: type, HasherType: type) type {...@@ -43,7 +43,7 @@ pub fn HashedWriter(WriterType: type, HasherType: type) type {
43 hasher: HasherType,43 hasher: HasherType,
4444
45 pub const Error = WriterType.Error;45 pub const Error = WriterType.Error;
46 pub const Writer = std.io.Writer(*@This(), Error, write);46 pub const Writer = std.io.GenericWriter(*@This(), Error, write);
4747
48 pub fn write(self: *@This(), buf: []const u8) Error!usize {48 pub fn write(self: *@This(), buf: []const u8) Error!usize {
49 const amt = try self.child_writer.write(buf);49 const amt = try self.child_writer.write(buf);
lib/std/compress/flate/deflate.zig+2-2
...@@ -355,7 +355,7 @@ fn Deflate(comptime container: Container, comptime WriterType: type, comptime Bl...@@ -355,7 +355,7 @@ fn Deflate(comptime container: Container, comptime WriterType: type, comptime Bl
355355
356 // Writer interface356 // Writer interface
357357
358 pub const Writer = io.Writer(*Self, Error, write);358 pub const Writer = io.GenericWriter(*Self, Error, write);
359 pub const Error = BlockWriterType.Error;359 pub const Error = BlockWriterType.Error;
360360
361 /// Write `input` of uncompressed data.361 /// Write `input` of uncompressed data.
...@@ -512,7 +512,7 @@ fn SimpleCompressor(...@@ -512,7 +512,7 @@ fn SimpleCompressor(
512512
513 // Writer interface513 // Writer interface
514514
515 pub const Writer = io.Writer(*Self, Error, write);515 pub const Writer = io.GenericWriter(*Self, Error, write);
516 pub const Error = BlockWriterType.Error;516 pub const Error = BlockWriterType.Error;
517517
518 // Write `input` of uncompressed data.518 // Write `input` of uncompressed data.
lib/std/compress/flate/inflate.zig+1-1
...@@ -341,7 +341,7 @@ pub fn Inflate(comptime container: Container, comptime LookaheadType: type, comp...@@ -341,7 +341,7 @@ pub fn Inflate(comptime container: Container, comptime LookaheadType: type, comp
341341
342 // Reader interface342 // Reader interface
343343
344 pub const Reader = std.io.Reader(*Self, Error, read);344 pub const Reader = std.io.GenericReader(*Self, Error, read);
345345
346 /// Returns the number of bytes read. It may be less than buffer.len.346 /// Returns the number of bytes read. It may be less than buffer.len.
347 /// If the number of bytes read is 0, it means end of stream.347 /// If the number of bytes read is 0, it means end of stream.
lib/std/compress/lzma.zig+1-1
...@@ -30,7 +30,7 @@ pub fn Decompress(comptime ReaderType: type) type {...@@ -30,7 +30,7 @@ pub fn Decompress(comptime ReaderType: type) type {
30 Allocator.Error ||30 Allocator.Error ||
31 error{ CorruptInput, EndOfStream, Overflow };31 error{ CorruptInput, EndOfStream, Overflow };
3232
33 pub const Reader = std.io.Reader(*Self, Error, read);33 pub const Reader = std.io.GenericReader(*Self, Error, read);
3434
35 allocator: Allocator,35 allocator: Allocator,
36 in_reader: ReaderType,36 in_reader: ReaderType,
lib/std/compress/xz.zig+1-1
...@@ -34,7 +34,7 @@ pub fn Decompress(comptime ReaderType: type) type {...@@ -34,7 +34,7 @@ pub fn Decompress(comptime ReaderType: type) type {
34 const Self = @This();34 const Self = @This();
3535
36 pub const Error = ReaderType.Error || block.Decoder(ReaderType).Error;36 pub const Error = ReaderType.Error || block.Decoder(ReaderType).Error;
37 pub const Reader = std.io.Reader(*Self, Error, read);37 pub const Reader = std.io.GenericReader(*Self, Error, read);
3838
39 allocator: Allocator,39 allocator: Allocator,
40 block_decoder: block.Decoder(ReaderType),40 block_decoder: block.Decoder(ReaderType),
lib/std/compress/xz/block.zig+1-1
...@@ -27,7 +27,7 @@ pub fn Decoder(comptime ReaderType: type) type {...@@ -27,7 +27,7 @@ pub fn Decoder(comptime ReaderType: type) type {
27 ReaderType.Error ||27 ReaderType.Error ||
28 DecodeError ||28 DecodeError ||
29 Allocator.Error;29 Allocator.Error;
30 pub const Reader = std.io.Reader(*Self, Error, read);30 pub const Reader = std.io.GenericReader(*Self, Error, read);
3131
32 allocator: Allocator,32 allocator: Allocator,
33 inner_reader: ReaderType,33 inner_reader: ReaderType,
lib/std/compress/zstandard.zig+1-1
...@@ -50,7 +50,7 @@ pub fn Decompressor(comptime ReaderType: type) type {...@@ -50,7 +50,7 @@ pub fn Decompressor(comptime ReaderType: type) type {
50 OutOfMemory,50 OutOfMemory,
51 };51 };
5252
53 pub const Reader = std.io.Reader(*Self, Error, read);53 pub const Reader = std.io.GenericReader(*Self, Error, read);
5454
55 pub fn init(source: ReaderType, options: DecompressorOptions) Self {55 pub fn init(source: ReaderType, options: DecompressorOptions) Self {
56 return .{56 return .{
lib/std/compress/zstandard/readers.zig+1-1
...@@ -4,7 +4,7 @@ pub const ReversedByteReader = struct {...@@ -4,7 +4,7 @@ pub const ReversedByteReader = struct {
4 remaining_bytes: usize,4 remaining_bytes: usize,
5 bytes: []const u8,5 bytes: []const u8,
66
7 const Reader = std.io.Reader(*ReversedByteReader, error{}, readFn);7 const Reader = std.io.GenericReader(*ReversedByteReader, error{}, readFn);
88
9 pub fn init(bytes: []const u8) ReversedByteReader {9 pub fn init(bytes: []const u8) ReversedByteReader {
10 return .{10 return .{
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/aegis.zig+1-1
...@@ -803,7 +803,7 @@ fn AegisMac(comptime T: type) type {...@@ -803,7 +803,7 @@ fn AegisMac(comptime T: type) type {
803 }803 }
804804
805 pub const Error = error{};805 pub const Error = error{};
806 pub const Writer = std.io.Writer(*Mac, Error, write);806 pub const Writer = std.io.GenericWriter(*Mac, Error, write);
807807
808 fn write(self: *Mac, bytes: []const u8) Error!usize {808 fn write(self: *Mac, bytes: []const u8) Error!usize {
809 self.update(bytes);809 self.update(bytes);
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.io.getStdOut().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/blake2.zig+1-1
...@@ -187,7 +187,7 @@ pub fn Blake2s(comptime out_bits: usize) type {...@@ -187,7 +187,7 @@ pub fn Blake2s(comptime out_bits: usize) type {
187 }187 }
188188
189 pub const Error = error{};189 pub const Error = error{};
190 pub const Writer = std.io.Writer(*Self, Error, write);190 pub const Writer = std.io.GenericWriter(*Self, Error, write);
191191
192 fn write(self: *Self, bytes: []const u8) Error!usize {192 fn write(self: *Self, bytes: []const u8) Error!usize {
193 self.update(bytes);193 self.update(bytes);
lib/std/crypto/blake3.zig+1-1
...@@ -476,7 +476,7 @@ pub const Blake3 = struct {...@@ -476,7 +476,7 @@ pub const Blake3 = struct {
476 }476 }
477477
478 pub const Error = error{};478 pub const Error = error{};
479 pub const Writer = std.io.Writer(*Blake3, Error, write);479 pub const Writer = std.io.GenericWriter(*Blake3, Error, write);
480480
481 fn write(self: *Blake3, bytes: []const u8) Error!usize {481 fn write(self: *Blake3, bytes: []const u8) Error!usize {
482 self.update(bytes);482 self.update(bytes);
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/codecs/asn1/der/ArrayListReverse.zig+1-1
...@@ -45,7 +45,7 @@ pub fn prependSlice(self: *ArrayListReverse, data: []const u8) Error!void {...@@ -45,7 +45,7 @@ pub fn prependSlice(self: *ArrayListReverse, data: []const u8) Error!void {
45 self.data.ptr = begin;45 self.data.ptr = begin;
46}46}
4747
48pub const Writer = std.io.Writer(*ArrayListReverse, Error, prependSliceSize);48pub const Writer = std.io.GenericWriter(*ArrayListReverse, Error, prependSliceSize);
49/// Warning: This writer writes backwards. `fn print` will NOT work as expected.49/// Warning: This writer writes backwards. `fn print` will NOT work as expected.
50pub fn writer(self: *ArrayListReverse) Writer {50pub fn writer(self: *ArrayListReverse) Writer {
51 return .{ .context = self };51 return .{ .context = self };
lib/std/crypto/ml_kem.zig+6-6
...@@ -1741,7 +1741,7 @@ test "NIST KAT test" {...@@ -1741,7 +1741,7 @@ test "NIST KAT test" {
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.format(fw, "count = {}\n", .{i});
1744 try std.fmt.format(fw, "seed = {s}\n", .{std.fmt.fmtSliceHexUpper(&seed)});1744 try std.fmt.format(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.format(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.format(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.format(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.format(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/sha1.zig+1-1
...@@ -269,7 +269,7 @@ pub const Sha1 = struct {...@@ -269,7 +269,7 @@ pub const Sha1 = struct {
269 }269 }
270270
271 pub const Error = error{};271 pub const Error = error{};
272 pub const Writer = std.io.Writer(*Self, Error, write);272 pub const Writer = std.io.GenericWriter(*Self, Error, write);
273273
274 fn write(self: *Self, bytes: []const u8) Error!usize {274 fn write(self: *Self, bytes: []const u8) Error!usize {
275 self.update(bytes);275 self.update(bytes);
lib/std/crypto/sha2.zig+1-1
...@@ -376,7 +376,7 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {...@@ -376,7 +376,7 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {
376 }376 }
377377
378 pub const Error = error{};378 pub const Error = error{};
379 pub const Writer = std.io.Writer(*Self, Error, write);379 pub const Writer = std.io.GenericWriter(*Self, Error, write);
380380
381 fn write(self: *Self, bytes: []const u8) Error!usize {381 fn write(self: *Self, bytes: []const u8) Error!usize {
382 self.update(bytes);382 self.update(bytes);
lib/std/crypto/sha3.zig+5-5
...@@ -82,7 +82,7 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim...@@ -82,7 +82,7 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim
82 }82 }
8383
84 pub const Error = error{};84 pub const Error = error{};
85 pub const Writer = std.io.Writer(*Self, Error, write);85 pub const Writer = std.io.GenericWriter(*Self, Error, write);
8686
87 fn write(self: *Self, bytes: []const u8) Error!usize {87 fn write(self: *Self, bytes: []const u8) Error!usize {
88 self.update(bytes);88 self.update(bytes);
...@@ -193,7 +193,7 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime...@@ -193,7 +193,7 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime
193 }193 }
194194
195 pub const Error = error{};195 pub const Error = error{};
196 pub const Writer = std.io.Writer(*Self, Error, write);196 pub const Writer = std.io.GenericWriter(*Self, Error, write);
197197
198 fn write(self: *Self, bytes: []const u8) Error!usize {198 fn write(self: *Self, bytes: []const u8) Error!usize {
199 self.update(bytes);199 self.update(bytes);
...@@ -286,7 +286,7 @@ fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime...@@ -286,7 +286,7 @@ fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime
286 }286 }
287287
288 pub const Error = error{};288 pub const Error = error{};
289 pub const Writer = std.io.Writer(*Self, Error, write);289 pub const Writer = std.io.GenericWriter(*Self, Error, write);
290290
291 fn write(self: *Self, bytes: []const u8) Error!usize {291 fn write(self: *Self, bytes: []const u8) Error!usize {
292 self.update(bytes);292 self.update(bytes);
...@@ -392,7 +392,7 @@ fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime r...@@ -392,7 +392,7 @@ fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime r
392 }392 }
393393
394 pub const Error = error{};394 pub const Error = error{};
395 pub const Writer = std.io.Writer(*Self, Error, write);395 pub const Writer = std.io.GenericWriter(*Self, Error, write);
396396
397 fn write(self: *Self, bytes: []const u8) Error!usize {397 fn write(self: *Self, bytes: []const u8) Error!usize {
398 self.update(bytes);398 self.update(bytes);
...@@ -484,7 +484,7 @@ fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, compt...@@ -484,7 +484,7 @@ fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, compt
484 }484 }
485485
486 pub const Error = error{};486 pub const Error = error{};
487 pub const Writer = std.io.Writer(*Self, Error, write);487 pub const Writer = std.io.GenericWriter(*Self, Error, write);
488488
489 fn write(self: *Self, bytes: []const u8) Error!usize {489 fn write(self: *Self, bytes: []const u8) Error!usize {
490 self.update(bytes);490 self.update(bytes);
lib/std/crypto/siphash.zig+1-1
...@@ -240,7 +240,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -240,7 +240,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
240 }240 }
241241
242 pub const Error = error{};242 pub const Error = error{};
243 pub const Writer = std.io.Writer(*Self, Error, write);243 pub const Writer = std.io.GenericWriter(*Self, Error, write);
244244
245 fn write(self: *Self, bytes: []const u8) Error!usize {245 fn write(self: *Self, bytes: []const u8) Error!usize {
246 self.update(bytes);246 self.update(bytes);
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+186-170
...@@ -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 = io.getStdErr().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 = std.io.getStdErr();
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.writer, .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 = io.getStdErr().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 = io.getStdErr().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(io.getStdErr()), 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 = io.getStdErr().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 = io.getStdErr().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(io.getStdErr());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 = io.getStdErr().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 = io.getStdErr().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(io.getStdErr())) 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 = io.getStdErr().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();
...@@ -699,7 +708,7 @@ pub fn defaultPanic(...@@ -699,7 +708,7 @@ pub fn defaultPanic(
699 // A panic happened while trying to print a previous panic message.708 // A panic happened while trying to print a previous panic message.
700 // We're still holding the mutex but that's fine as we're going to709 // We're still holding the mutex but that's fine as we're going to
701 // call abort().710 // call abort().
702 io.getStdErr().writeAll("aborting due to recursive panic\n") catch {};711 fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {};
703 },712 },
704 else => {}, // Panicked while printing the recursive panic message.713 else => {}, // Panicked while printing the recursive panic message.
705 };714 };
...@@ -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.writer;
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,17 @@ test printLineFromFileAnyOs {...@@ -1273,14 +1282,17 @@ 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 buf: [16]u8 = undefined;
1277 try writer.writeByteNTimes('a', std.heap.page_size_min - overlap);1286 var file_writer = file.writer(&buf);
1287 const writer = &file_writer.interface;
1288 try writer.splatByteAll('a', std.heap.page_size_min - overlap);
1278 try writer.writeByte('\n');1289 try writer.writeByte('\n');
1279 try writer.writeByteNTimes('a', overlap);1290 try writer.splatByteAll('a', overlap);
1291 try writer.flush();
12801292
1281 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });1293 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
1282 try expectEqualStrings(("a" ** overlap) ++ "\n", output.items);1294 try expectEqualStrings(("a" ** overlap) ++ "\n", aw.getWritten());
1283 output.clearRetainingCapacity();1295 aw.clearRetainingCapacity();
1284 }1296 }
1285 {1297 {
1286 const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});1298 const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});
...@@ -1288,12 +1300,13 @@ test printLineFromFileAnyOs {...@@ -1288,12 +1300,13 @@ test printLineFromFileAnyOs {
1288 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });1300 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });
1289 defer allocator.free(path);1301 defer allocator.free(path);
12901302
1291 var writer = file.writer();1303 var file_writer = file.writer(&.{});
1292 try writer.writeByteNTimes('a', std.heap.page_size_max);1304 const writer = &file_writer.interface;
1305 try writer.splatByteAll('a', std.heap.page_size_max);
12931306
1294 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1307 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1295 try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", output.items);1308 try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", aw.getWritten());
1296 output.clearRetainingCapacity();1309 aw.clearRetainingCapacity();
1297 }1310 }
1298 {1311 {
1299 const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});1312 const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});
...@@ -1301,24 +1314,25 @@ test printLineFromFileAnyOs {...@@ -1301,24 +1314,25 @@ test printLineFromFileAnyOs {
1301 const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });1314 const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });
1302 defer allocator.free(path);1315 defer allocator.free(path);
13031316
1304 var writer = file.writer();1317 var file_writer = file.writer(&.{});
1305 try writer.writeByteNTimes('a', 3 * std.heap.page_size_max);1318 const writer = &file_writer.interface;
1319 try writer.splatByteAll('a', 3 * std.heap.page_size_max);
13061320
1307 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));1321 try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
13081322
1309 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1323 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
1310 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", output.items);1324 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", aw.getWritten());
1311 output.clearRetainingCapacity();1325 aw.clearRetainingCapacity();
13121326
1313 try writer.writeAll("a\na");1327 try writer.writeAll("a\na");
13141328
1315 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });1329 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);1330 try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", aw.getWritten());
1317 output.clearRetainingCapacity();1331 aw.clearRetainingCapacity();
13181332
1319 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });1333 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
1320 try expectEqualStrings("a\n", output.items);1334 try expectEqualStrings("a\n", aw.getWritten());
1321 output.clearRetainingCapacity();1335 aw.clearRetainingCapacity();
1322 }1336 }
1323 {1337 {
1324 const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});1338 const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});
...@@ -1326,18 +1340,19 @@ test printLineFromFileAnyOs {...@@ -1326,18 +1340,19 @@ test printLineFromFileAnyOs {
1326 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });1340 const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });
1327 defer allocator.free(path);1341 defer allocator.free(path);
13281342
1329 var writer = file.writer();1343 var file_writer = file.writer(&.{});
1344 const writer = &file_writer.interface;
1330 const real_file_start = 3 * std.heap.page_size_min;1345 const real_file_start = 3 * std.heap.page_size_min;
1331 try writer.writeByteNTimes('\n', real_file_start);1346 try writer.splatByteAll('\n', real_file_start);
1332 try writer.writeAll("abc\ndef");1347 try writer.writeAll("abc\ndef");
13331348
1334 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });1349 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });
1335 try expectEqualStrings("abc\n", output.items);1350 try expectEqualStrings("abc\n", aw.getWritten());
1336 output.clearRetainingCapacity();1351 aw.clearRetainingCapacity();
13371352
1338 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });1353 try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });
1339 try expectEqualStrings("def\n", output.items);1354 try expectEqualStrings("def\n", aw.getWritten());
1340 output.clearRetainingCapacity();1355 aw.clearRetainingCapacity();
1341 }1356 }
1342}1357}
13431358
...@@ -1461,7 +1476,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa...@@ -1461,7 +1476,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
1461}1476}
14621477
1463fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {1478fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
1464 const stderr = io.getStdErr().writer();1479 const stderr = lockStderrWriter(&.{});
1480 defer unlockStderrWriter();
1465 _ = switch (sig) {1481 _ = switch (sig) {
1466 posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL1482 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.1483 // x86_64 doesn't have a full 64-bit virtual address space.
...@@ -1471,7 +1487,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)...@@ -1471,7 +1487,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
1471 // but can also happen when no addressable memory is involved;1487 // but can also happen when no addressable memory is involved;
1472 // for example when reading/writing model-specific registers1488 // for example when reading/writing model-specific registers
1473 // by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).1489 // by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).
1474 stderr.print("General protection exception (no address available)\n", .{})1490 stderr.writeAll("General protection exception (no address available)\n")
1475 else1491 else
1476 stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),1492 stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
1477 posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),1493 posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),
...@@ -1509,7 +1525,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)...@@ -1509,7 +1525,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
1509 }, @ptrCast(ctx)).__mcontext_data;1525 }, @ptrCast(ctx)).__mcontext_data;
1510 }1526 }
1511 relocateContext(&new_ctx);1527 relocateContext(&new_ctx);
1512 dumpStackTraceFromBase(&new_ctx);1528 dumpStackTraceFromBase(&new_ctx, stderr);
1513 },1529 },
1514 else => {},1530 else => {},
1515 }1531 }
...@@ -1539,25 +1555,24 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:...@@ -1539,25 +1555,24 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
1539 _ = panicking.fetchAdd(1, .seq_cst);1555 _ = panicking.fetchAdd(1, .seq_cst);
15401556
1541 {1557 {
1542 lockStdErr();1558 const stderr = lockStderrWriter(&.{});
1543 defer unlockStdErr();1559 defer unlockStderrWriter();
15441560
1545 dumpSegfaultInfoWindows(info, msg, label);1561 dumpSegfaultInfoWindows(info, msg, label, stderr);
1546 }1562 }
15471563
1548 waitForOtherThreadToFinishPanicking();1564 waitForOtherThreadToFinishPanicking();
1549 },1565 },
1550 1 => {1566 1 => {
1551 panic_stage = 2;1567 panic_stage = 2;
1552 io.getStdErr().writeAll("aborting due to recursive panic\n") catch {};1568 fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {};
1553 },1569 },
1554 else => {},1570 else => {},
1555 };1571 };
1556 posix.abort();1572 posix.abort();
1557}1573}
15581574
1559fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {1575fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *Writer) void {
1560 const stderr = io.getStdErr().writer();
1561 _ = switch (msg) {1576 _ = switch (msg) {
1562 0 => stderr.print("{s}\n", .{label.?}),1577 0 => stderr.print("{s}\n", .{label.?}),
1563 1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),1578 1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
...@@ -1565,7 +1580,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[...@@ -1565,7 +1580,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[
1565 else => unreachable,1580 else => unreachable,
1566 } catch posix.abort();1581 } catch posix.abort();
15671582
1568 dumpStackTraceFromBase(info.ContextRecord);1583 dumpStackTraceFromBase(info.ContextRecord, stderr);
1569}1584}
15701585
1571pub fn dumpStackPointerAddr(prefix: []const u8) void {1586pub fn dumpStackPointerAddr(prefix: []const u8) void {
...@@ -1588,10 +1603,10 @@ test "manage resources correctly" {...@@ -1588,10 +1603,10 @@ test "manage resources correctly" {
1588 // self-hosted debug info is still too buggy1603 // self-hosted debug info is still too buggy
1589 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;1604 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
15901605
1591 const writer = std.io.null_writer;1606 var discarding: std.io.Writer.Discarding = .init(&.{});
1592 var di = try SelfInfo.open(testing.allocator);1607 var di = try SelfInfo.open(testing.allocator);
1593 defer di.deinit();1608 defer di.deinit();
1594 try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.io.getStdErr()));1609 try printSourceAtAddress(&di, &discarding.writer, showMyTrace(), io.tty.detectConfig(.stderr()));
1595}1610}
15961611
1597noinline fn showMyTrace() usize {1612noinline fn showMyTrace() usize {
...@@ -1657,8 +1672,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1657,8 +1672,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1657 pub fn dump(t: @This()) void {1672 pub fn dump(t: @This()) void {
1658 if (!enabled) return;1673 if (!enabled) return;
16591674
1660 const tty_config = io.tty.detectConfig(std.io.getStdErr());1675 const tty_config = io.tty.detectConfig(.stderr());
1661 const stderr = io.getStdErr().writer();1676 const stderr = lockStderrWriter(&.{});
1677 defer unlockStderrWriter();
1662 const end = @min(t.index, size);1678 const end = @min(t.index, size);
1663 const debug_info = getSelfDebugInfo() catch |err| {1679 const debug_info = getSelfDebugInfo() catch |err| {
1664 stderr.print(1680 stderr.print(
...@@ -1688,7 +1704,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1688,7 +1704,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1688 t: @This(),1704 t: @This(),
1689 comptime fmt: []const u8,1705 comptime fmt: []const u8,
1690 options: std.fmt.FormatOptions,1706 options: std.fmt.FormatOptions,
1691 writer: anytype,1707 writer: *Writer,
1692 ) !void {1708 ) !void {
1693 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);1709 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
1694 _ = options;1710 _ = 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+3-3
...@@ -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;
...@@ -562,7 +562,7 @@ const MsfStream = struct {...@@ -562,7 +562,7 @@ const MsfStream = struct {
562 return block * self.block_size + offset;562 return block * self.block_size + offset;
563 }563 }
564564
565 pub fn reader(self: *MsfStream) std.io.Reader(*MsfStream, Error, read) {565 pub fn reader(self: *MsfStream) std.io.GenericReader(*MsfStream, Error, read) {
566 return .{ .context = self };566 return .{ .context = self };
567 }567 }
568};568};
lib/std/debug/simple_panic.zig+1-1
...@@ -15,7 +15,7 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn {...@@ -15,7 +15,7 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn {
15 @branchHint(.cold);15 @branchHint(.cold);
16 _ = ra;16 _ = ra;
17 std.debug.lockStdErr();17 std.debug.lockStdErr();
18 const stderr = std.io.getStdErr();18 const stderr: std.fs.File = .stderr();
19 stderr.writeAll(msg) catch {};19 stderr.writeAll(msg) catch {};
20 @trap();20 @trap();
21}21}
lib/std/elf.zig+5-5
...@@ -511,7 +511,7 @@ pub const Header = struct {...@@ -511,7 +511,7 @@ pub const Header = struct {
511 pub fn read(parse_source: anytype) !Header {511 pub fn read(parse_source: anytype) !Header {
512 var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;512 var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;
513 try parse_source.seekableStream().seekTo(0);513 try parse_source.seekableStream().seekTo(0);
514 try parse_source.reader().readNoEof(&hdr_buf);514 try parse_source.deprecatedReader().readNoEof(&hdr_buf);
515 return Header.parse(&hdr_buf);515 return Header.parse(&hdr_buf);
516 }516 }
517517
...@@ -586,7 +586,7 @@ pub fn ProgramHeaderIterator(comptime ParseSource: anytype) type {...@@ -586,7 +586,7 @@ pub fn ProgramHeaderIterator(comptime ParseSource: anytype) type {
586 var phdr: Elf64_Phdr = undefined;586 var phdr: Elf64_Phdr = undefined;
587 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;587 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;
588 try self.parse_source.seekableStream().seekTo(offset);588 try self.parse_source.seekableStream().seekTo(offset);
589 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));589 try self.parse_source.deprecatedReader().readNoEof(mem.asBytes(&phdr));
590590
591 // ELF endianness matches native endianness.591 // ELF endianness matches native endianness.
592 if (self.elf_header.endian == native_endian) return phdr;592 if (self.elf_header.endian == native_endian) return phdr;
...@@ -599,7 +599,7 @@ pub fn ProgramHeaderIterator(comptime ParseSource: anytype) type {...@@ -599,7 +599,7 @@ pub fn ProgramHeaderIterator(comptime ParseSource: anytype) type {
599 var phdr: Elf32_Phdr = undefined;599 var phdr: Elf32_Phdr = undefined;
600 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;600 const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index;
601 try self.parse_source.seekableStream().seekTo(offset);601 try self.parse_source.seekableStream().seekTo(offset);
602 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));602 try self.parse_source.deprecatedReader().readNoEof(mem.asBytes(&phdr));
603603
604 // ELF endianness does NOT match native endianness.604 // ELF endianness does NOT match native endianness.
605 if (self.elf_header.endian != native_endian) {605 if (self.elf_header.endian != native_endian) {
...@@ -636,7 +636,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type {...@@ -636,7 +636,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type {
636 var shdr: Elf64_Shdr = undefined;636 var shdr: Elf64_Shdr = undefined;
637 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;637 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;
638 try self.parse_source.seekableStream().seekTo(offset);638 try self.parse_source.seekableStream().seekTo(offset);
639 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));639 try self.parse_source.deprecatedReader().readNoEof(mem.asBytes(&shdr));
640640
641 // ELF endianness matches native endianness.641 // ELF endianness matches native endianness.
642 if (self.elf_header.endian == native_endian) return shdr;642 if (self.elf_header.endian == native_endian) return shdr;
...@@ -649,7 +649,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type {...@@ -649,7 +649,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type {
649 var shdr: Elf32_Shdr = undefined;649 var shdr: Elf32_Shdr = undefined;
650 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;650 const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index;
651 try self.parse_source.seekableStream().seekTo(offset);651 try self.parse_source.seekableStream().seekTo(offset);
652 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));652 try self.parse_source.deprecatedReader().readNoEof(mem.asBytes(&shdr));
653653
654 // ELF endianness does NOT match native endianness.654 // ELF endianness does NOT match native endianness.
655 if (self.elf_header.endian != native_endian) {655 if (self.elf_header.endian != native_endian) {
lib/std/fifo.zig+4-4
...@@ -38,8 +38,8 @@ pub fn LinearFifo(...@@ -38,8 +38,8 @@ pub fn LinearFifo(
38 count: usize,38 count: usize,
3939
40 const Self = @This();40 const Self = @This();
41 pub const Reader = std.io.Reader(*Self, error{}, readFn);41 pub const Reader = std.io.GenericReader(*Self, error{}, readFn);
42 pub const Writer = std.io.Writer(*Self, error{OutOfMemory}, appendWrite);42 pub const Writer = std.io.GenericWriter(*Self, error{OutOfMemory}, appendWrite);
4343
44 // Type of Self argument for slice operations.44 // Type of Self argument for slice operations.
45 // If buffer is inline (Static) then we need to ensure we haven't45 // If buffer is inline (Static) then we need to ensure we haven't
...@@ -231,7 +231,7 @@ pub fn LinearFifo(...@@ -231,7 +231,7 @@ pub fn LinearFifo(
231 }231 }
232232
233 /// Same as `read` except it returns an error union233 /// Same as `read` except it returns an error union
234 /// The purpose of this function existing is to match `std.io.Reader` API.234 /// The purpose of this function existing is to match `std.io.GenericReader` API.
235 fn readFn(self: *Self, dest: []u8) error{}!usize {235 fn readFn(self: *Self, dest: []u8) error{}!usize {
236 return self.read(dest);236 return self.read(dest);
237 }237 }
...@@ -320,7 +320,7 @@ pub fn LinearFifo(...@@ -320,7 +320,7 @@ pub fn LinearFifo(
320 }320 }
321321
322 /// Same as `write` except it returns the number of bytes written, which is always the same322 /// Same as `write` except it returns the number of bytes written, which is always the same
323 /// as `bytes.len`. The purpose of this function existing is to match `std.io.Writer` API.323 /// as `bytes.len`. The purpose of this function existing is to match `std.io.GenericWriter` API.
324 fn appendWrite(self: *Self, bytes: []const u8) error{OutOfMemory}!usize {324 fn appendWrite(self: *Self, bytes: []const u8) error{OutOfMemory}!usize {
325 try self.write(bytes);325 try self.write(bytes);
326 return bytes.len;326 return bytes.len;
lib/std/fmt.zig+290-1715
...@@ -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
...@@ -21,237 +24,91 @@ pub const Alignment = enum {...@@ -21,237 +24,91 @@ pub const Alignment = enum {
21 right,24 right,
22};25};
2326
27pub const Case = enum { lower, upper };
28
24const default_alignment = .right;29const default_alignment = .right;
25const default_fill_char = ' ';30const default_fill_char = ' ';
2631
27pub const FormatOptions = struct {32/// Deprecated in favor of `Options`.
33pub const FormatOptions = Options;
34
35pub const Options = struct {
28 precision: ?usize = null,36 precision: ?usize = null,
29 width: ?usize = null,37 width: ?usize = null,
30 alignment: Alignment = default_alignment,38 alignment: Alignment = default_alignment,
31 fill: u21 = default_fill_char,39 fill: u8 = default_fill_char,
32};40
3341 pub fn toNumber(o: Options, mode: Number.Mode, case: Case) Number {
34/// Renders fmt string with args, calling `writer` with slices of bytes.42 return .{
35/// If `writer` returns an error, the error is returned from `format` and43 .mode = mode,
36/// `writer` is not called again.44 .case = case,
37///45 .precision = o.precision,
38/// The format string must be comptime-known and may contain placeholders following46 .width = o.width,
39/// this format:47 .alignment = o.alignment,
40/// `{[argument][specifier]:[fill][alignment][width].[precision]}`48 .fill = o.fill,
41///
42/// Above, each word including its surrounding [ and ] is a parameter which you have to replace with something:
43///
44/// - *argument* is either the numeric index or the field name of the argument that should be inserted
45/// - 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...}
47/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
48/// - *fill* is a single unicode codepoint which is used to pad the formatted text
49/// - *alignment* is one of the three bytes '<', '^', or '>' to make the text left-, center-, or right-aligned, respectively
50/// - *width* is the total width of the field in unicode codepoints
51/// - *precision* specifies how many decimals a formatted number should have
52///
53/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when
54/// all parameters after the separator are omitted.
55/// Only exception is the *fill* parameter. If a non-zero *fill* character is required at the same time as *width* is specified,
56/// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*.
57///
58/// The *specifier* has several options for types:
59/// - `x` and `X`: output numeric value in hexadecimal notation
60/// - `s`:
61/// - 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-termination
63/// - `e`: output floating point value in scientific notation
64/// - `d`: output numeric value in decimal notation
65/// - `b`: output integer value in binary notation
66/// - `o`: output integer value in octal notation
67/// - `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.
69/// - `?`: 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.
71/// - `*`: output the address of the value instead of the value itself.
72/// - `any`: output a value of any type using its default format.
73///
74/// If a formatted user type contains a function of the type
75/// ```
76/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void
77/// ```
78/// 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.
80///
81/// A user type may be a `struct`, `vector`, `union` or `enum` type.
82///
83/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
84pub fn format(
85 writer: anytype,
86 comptime fmt: []const u8,
87 args: anytype,
88) !void {
89 const ArgsType = @TypeOf(args);
90 const args_type_info = @typeInfo(ArgsType);
91 if (args_type_info != .@"struct") {
92 @compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType));
93 }
94
95 const fields_info = args_type_info.@"struct".fields;
96 if (fields_info.len > max_format_args) {
97 @compileError("32 arguments max are supported per format call");
98 }
99
100 @setEvalBranchQuota(2000000);
101 comptime var arg_state: ArgState = .{ .args_len = fields_info.len };
102 comptime var i = 0;
103 comptime var literal: []const u8 = "";
104 inline while (true) {
105 const start_index = i;
106
107 inline while (i < fmt.len) : (i += 1) {
108 switch (fmt[i]) {
109 '{', '}' => break,
110 else => {},
111 }
112 }
113
114 comptime var end_index = i;
115 comptime var unescape_brace = false;
116
117 // Handle {{ and }}, those are un-escaped as single braces
118 if (i + 1 < fmt.len and fmt[i + 1] == fmt[i]) {
119 unescape_brace = true;
120 // Make the first brace part of the literal...
121 end_index += 1;
122 // ...and skip both
123 i += 2;
124 }
125
126 literal = literal ++ fmt[start_index..end_index];
127
128 // We've already skipped the other brace, restart the loop
129 if (unescape_brace) continue;
130
131 // Write out the literal
132 if (literal.len != 0) {
133 try writer.writeAll(literal);
134 literal = "";
135 }
136
137 if (i >= fmt.len) break;
138
139 if (fmt[i] == '}') {
140 @compileError("missing opening {");
141 }
142
143 // Get past the {
144 comptime assert(fmt[i] == '{');
145 i += 1;
146
147 const fmt_begin = i;
148 // Find the closing brace
149 inline while (i < fmt.len and fmt[i] != '}') : (i += 1) {}
150 const fmt_end = i;
151
152 if (i >= fmt.len) {
153 @compileError("missing closing }");
154 }
155
156 // Get past the }
157 comptime assert(fmt[i] == '}');
158 i += 1;
159
160 const placeholder = comptime Placeholder.parse(fmt[fmt_begin..fmt_end].*);
161 const arg_pos = comptime switch (placeholder.arg) {
162 .none => null,
163 .number => |pos| pos,
164 .named => |arg_name| meta.fieldIndex(ArgsType, arg_name) orelse
165 @compileError("no argument with name '" ++ arg_name ++ "'"),
166 };
167
168 const width = switch (placeholder.width) {
169 .none => null,
170 .number => |v| v,
171 .named => |arg_name| blk: {
172 const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse
173 @compileError("no argument with name '" ++ arg_name ++ "'");
174 _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments");
175 break :blk @field(args, arg_name);
176 },
177 };
178
179 const precision = switch (placeholder.precision) {
180 .none => null,
181 .number => |v| v,
182 .named => |arg_name| blk: {
183 const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse
184 @compileError("no argument with name '" ++ arg_name ++ "'");
185 _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments");
186 break :blk @field(args, arg_name);
187 },
188 };49 };
50 }
51};
18952
190 const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse53pub const Number = struct {
191 @compileError("too few arguments");54 mode: Mode = .decimal,
19255 /// Affects hex digits as well as floating point "inf"/"INF".
193 try formatType(56 case: Case = .lower,
194 @field(args, fields_info[arg_to_print].name),57 precision: ?usize = null,
195 placeholder.specifier_arg,58 width: ?usize = null,
196 FormatOptions{59 alignment: Alignment = default_alignment,
197 .fill = placeholder.fill,60 fill: u8 = default_fill_char,
198 .alignment = placeholder.alignment,61
199 .width = width,62 pub const Mode = enum {
200 .precision = precision,63 decimal,
201 },64 binary,
202 writer,65 octal,
203 std.options.fmt_max_depth,66 hex,
204 );67 scientific,
205 }68
20669 pub fn base(mode: Mode) ?u8 {
207 if (comptime arg_state.hasUnusedArgs()) {70 return switch (mode) {
208 const missing_count = arg_state.args_len - @popCount(arg_state.used_args);71 .decimal => 10,
209 switch (missing_count) {72 .binary => 2,
210 0 => unreachable,73 .octal => 8,
211 1 => @compileError("unused argument in '" ++ fmt ++ "'"),74 .hex => 16,
212 else => @compileError(comptimePrint("{d}", .{missing_count}) ++ " unused arguments in '" ++ fmt ++ "'"),75 .scientific => null,
76 };
213 }77 }
214 }78 };
215}79};
21680
217fn cacheString(str: anytype) []const u8 {81/// Deprecated in favor of `Writer.print`.
218 return &str;82pub fn format(writer: anytype, comptime fmt: []const u8, args: anytype) !void {
83 var adapter = writer.adaptToNewApi();
84 return adapter.new_interface.print(fmt, args) catch |err| switch (err) {
85 error.WriteFailed => return adapter.err.?,
86 };
219}87}
22088
221pub const Placeholder = struct {89pub const Placeholder = struct {
222 specifier_arg: []const u8,90 specifier_arg: []const u8,
223 fill: u21,91 fill: u8,
224 alignment: Alignment,92 alignment: Alignment,
225 arg: Specifier,93 arg: Specifier,
226 width: Specifier,94 width: Specifier,
227 precision: Specifier,95 precision: Specifier,
22896
229 pub fn parse(comptime str: anytype) Placeholder {97 pub fn parse(comptime bytes: []const u8) Placeholder {
230 const view = std.unicode.Utf8View.initComptime(&str);98 var parser: Parser = .{ .bytes = bytes, .i = 0 };
231 comptime var parser = Parser{99 const arg = parser.specifier() catch |err| @compileError(@errorName(err));
232 .iter = view.iterator(),100 const specifier_arg = parser.until(':');
233 };101 if (parser.char()) |b| {
234102 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 }103 }
248104
249 // Parse the fill character, if present.105 // Parse the fill byte, if present.
250 // When the width field is also specified, the fill character must106 //
107 // When the width field is also specified, the fill byte must
251 // be followed by an alignment specifier, unless it's '0' (zero)108 // be followed by an alignment specifier, unless it's '0' (zero)
252 // (in which case it's handled as part of the width specifier)109 // (in which case it's handled as part of the width specifier).
253 var fill: ?u21 = comptime if (parser.peek(1)) |ch|110 var fill: ?u8 = if (parser.peek(1)) |b|
254 switch (ch) {111 switch (b) {
255 '<', '^', '>' => parser.char(),112 '<', '^', '>' => parser.char(),
256 else => null,113 else => null,
257 }114 }
...@@ -259,8 +116,8 @@ pub const Placeholder = struct {...@@ -259,8 +116,8 @@ pub const Placeholder = struct {
259 null;116 null;
260117
261 // Parse the alignment parameter118 // Parse the alignment parameter
262 const alignment: ?Alignment = comptime if (parser.peek(0)) |ch| init: {119 const alignment: ?Alignment = if (parser.peek(0)) |b| init: {
263 switch (ch) {120 switch (b) {
264 '<', '^', '>' => {121 '<', '^', '>' => {
265 // consume the character122 // consume the character
266 break :init switch (parser.char().?) {123 break :init switch (parser.char().?) {
...@@ -276,30 +133,26 @@ pub const Placeholder = struct {...@@ -276,30 +133,26 @@ pub const Placeholder = struct {
276 // When none of the fill character and the alignment specifier have133 // When none of the fill character and the alignment specifier have
277 // been provided, check whether the width starts with a zero.134 // been provided, check whether the width starts with a zero.
278 if (fill == null and alignment == null) {135 if (fill == null and alignment == null) {
279 fill = comptime if (parser.peek(0) == '0') '0' else null;136 fill = if (parser.peek(0) == '0') '0' else null;
280 }137 }
281138
282 // Parse the width parameter139 // Parse the width parameter
283 const width = comptime parser.specifier() catch |err|140 const width = parser.specifier() catch |err| @compileError(@errorName(err));
284 @compileError(@errorName(err));
285141
286 // Skip the dot, if present142 // Skip the dot, if present
287 if (comptime parser.char()) |ch| {143 if (parser.char()) |b| {
288 if (ch != '.') {144 if (b != '.') @compileError("expected . or }, found '" ++ &[1]u8{b} ++ "'");
289 @compileError("expected . or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
290 }
291 }145 }
292146
293 // Parse the precision parameter147 // Parse the precision parameter
294 const precision = comptime parser.specifier() catch |err|148 const precision = parser.specifier() catch |err| @compileError(@errorName(err));
295 @compileError(@errorName(err));
296149
297 if (comptime parser.char()) |ch| {150 if (parser.char()) |b| @compileError("extraneous trailing character '" ++ &[1]u8{b} ++ "'");
298 @compileError("extraneous trailing character '" ++ unicode.utf8EncodeComptime(ch) ++ "'");151
299 }152 const specifier_array = specifier_arg[0..specifier_arg.len].*;
300153
301 return Placeholder{154 return .{
302 .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),155 .specifier_arg = &specifier_array,
303 .fill = fill orelse default_fill_char,156 .fill = fill orelse default_fill_char,
304 .alignment = alignment orelse default_alignment,157 .alignment = alignment orelse default_alignment,
305 .arg = arg,158 .arg = arg,
...@@ -320,93 +173,64 @@ pub const Specifier = union(enum) {...@@ -320,93 +173,64 @@ pub const Specifier = union(enum) {
320/// Allows to implement formatters compatible with std.fmt without replicating173/// Allows to implement formatters compatible with std.fmt without replicating
321/// the standard library behavior.174/// the standard library behavior.
322pub const Parser = struct {175pub const Parser = struct {
323 iter: std.unicode.Utf8Iterator,176 bytes: []const u8,
177 i: usize,
324178
325 // Returns a decimal number or null if the current character is not a
326 // digit
327 pub fn number(self: *@This()) ?usize {179 pub fn number(self: *@This()) ?usize {
328 var r: ?usize = null;180 var r: ?usize = null;
329181 while (self.peek(0)) |byte| {
330 while (self.peek(0)) |code_point| {182 switch (byte) {
331 switch (code_point) {
332 '0'...'9' => {183 '0'...'9' => {
333 if (r == null) r = 0;184 if (r == null) r = 0;
334 r.? *= 10;185 r.? *= 10;
335 r.? += code_point - '0';186 r.? += byte - '0';
336 },187 },
337 else => break,188 else => break,
338 }189 }
339 _ = self.iter.nextCodepoint();190 self.i += 1;
340 }191 }
341
342 return r;192 return r;
343 }193 }
344194
345 // Returns a substring of the input starting from the current position195 pub fn until(self: *@This(), delimiter: u8) []const u8 {
346 // and ending where `ch` is found or until the end if not found196 const start = self.i;
347 pub fn until(self: *@This(), ch: u21) []const u8 {197 self.i = std.mem.indexOfScalarPos(u8, self.bytes, self.i, delimiter) orelse self.bytes.len;
348 const start = self.iter.i;198 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 }199 }
356200
357 // Returns the character pointed to by the iterator if available, or201 pub fn char(self: *@This()) ?u8 {
358 // null otherwise202 const i = self.i;
359 pub fn char(self: *@This()) ?u21 {203 if (self.bytes.len - i == 0) return null;
360 if (self.iter.nextCodepoint()) |code_point| {204 self.i = i + 1;
361 return code_point;205 return self.bytes[i];
362 }
363 return null;
364 }206 }
365207
366 // Returns true if the iterator points to an existing character and208 pub fn maybe(self: *@This(), byte: u8) bool {
367 // false otherwise209 if (self.peek(0) == byte) {
368 pub fn maybe(self: *@This(), val: u21) bool {210 self.i += 1;
369 if (self.peek(0) == val) {
370 _ = self.iter.nextCodepoint();
371 return true;211 return true;
372 }212 }
373 return false;213 return false;
374 }214 }
375215
376 // Returns a decimal number or null if the current character is not a
377 // digit
378 pub fn specifier(self: *@This()) !Specifier {216 pub fn specifier(self: *@This()) !Specifier {
379 if (self.maybe('[')) {217 if (self.maybe('[')) {
380 const arg_name = self.until(']');218 const arg_name = self.until(']');
381219 if (!self.maybe(']')) return error.@"Expected closing ]";
382 if (!self.maybe(']'))220 return .{ .named = arg_name };
383 return @field(anyerror, "Expected closing ]");
384
385 return Specifier{ .named = arg_name };
386 }221 }
387 if (self.number()) |i|222 if (self.number()) |i| return .{ .number = i };
388 return Specifier{ .number = i };223 return .{ .none = {} };
389
390 return Specifier{ .none = {} };
391 }224 }
392225
393 // Returns the n-th next character or null if that's past the end226 pub fn peek(self: *@This(), i: usize) ?u8 {
394 pub fn peek(self: *@This(), n: usize) ?u21 {227 const peek_index = self.i + i;
395 const original_i = self.iter.i;228 if (peek_index >= self.bytes.len) return null;
396 defer self.iter.i = original_i;229 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 }230 }
406};231};
407232
408pub const ArgSetType = u32;233pub const ArgSetType = u32;
409const max_format_args = @typeInfo(ArgSetType).int.bits;
410234
411pub const ArgState = struct {235pub const ArgState = struct {
412 next_arg: usize = 0,236 next_arg: usize = 0,
...@@ -434,1075 +258,66 @@ pub const ArgState = struct {...@@ -434,1075 +258,66 @@ pub const ArgState = struct {
434 }258 }
435};259};
436260
437pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @TypeOf(writer).Error!void {261/// Asserts the rendered integer value fits in `buffer`.
438 _ = options;262/// Returns the end index within `buffer`.
439 const T = @TypeOf(value);263pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {
440264 var w: Writer = .fixed(buffer);
441 switch (@typeInfo(T)) {265 w.printInt(value, base, case, options) catch unreachable;
442 .pointer => |info| {266 return w.end;
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}267}
462268
463// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948269/// Converts values in the range [0, 100) to a base 10 string.
464const ANY = "any";270pub fn digits2(value: u8) [2]u8 {
465271 if (builtin.mode == .ReleaseSmall) {
466pub fn defaultSpec(comptime T: type) [:0]const u8 {272 return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) };
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 {273 } else {
812 invalidFmtError(fmt, value);274 return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
813 }275 }
814}276}
815277
816test {278/// Deprecated in favor of `Alt`.
817 _ = &format_float;279pub const Formatter = Alt;
818}
819
820pub const Case = enum { lower, upper };
821
822fn SliceHex(comptime case: Case) type {
823 const charset = "0123456789" ++ if (case == .upper) "ABCDEF" else "abcdef";
824
825 return struct {
826 pub fn format(
827 bytes: []const u8,
828 comptime fmt: []const u8,
829 options: std.fmt.FormatOptions,
830 writer: anytype,
831 ) !void {
832 _ = fmt;
833 _ = options;
834 var buf: [2]u8 = undefined;
835
836 for (bytes) |c| {
837 buf[0] = charset[c >> 4];
838 buf[1] = charset[c & 15];
839 try writer.writeAll(&buf);
840 }
841 }
842 };
843}
844
845const formatSliceHexLower = SliceHex(.lower).format;
846const formatSliceHexUpper = SliceHex(.upper).format;
847
848/// Return a Formatter for a []const u8 where every byte is formatted as a pair
849/// of lowercase hexadecimal digits.
850pub fn fmtSliceHexLower(bytes: []const u8) std.fmt.Formatter(formatSliceHexLower) {
851 return .{ .data = bytes };
852}
853
854/// Return a Formatter for a []const u8 where every byte is formatted as pair
855/// of uppercase hexadecimal digits.
856pub fn fmtSliceHexUpper(bytes: []const u8) std.fmt.Formatter(formatSliceHexUpper) {
857 return .{ .data = bytes };
858}
859
860fn SliceEscape(comptime case: Case) type {
861 const charset = "0123456789" ++ if (case == .upper) "ABCDEF" else "abcdef";
862280
281/// Creates a type suitable for instantiating and passing to a "{f}" placeholder.
282pub fn Alt(
283 comptime Data: type,
284 comptime formatFn: fn (data: Data, writer: *Writer) Writer.Error!void,
285) type {
863 return struct {286 return struct {
864 pub fn format(287 data: Data,
865 bytes: []const u8,288 pub inline fn format(self: @This(), writer: *Writer) Writer.Error!void {
866 comptime fmt: []const u8,289 try formatFn(self.data, writer);
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 }290 }
887 };291 };
888}292}
889293
890const formatSliceEscapeLower = SliceEscape(.lower).format;294/// Helper for calling alternate format methods besides one named "format".
891const formatSliceEscapeUpper = SliceEscape(.upper).format;295pub fn alt(
892296 context: anytype,
893/// Return a Formatter for a []const u8 where every non-printable ASCII297 comptime func_name: @TypeOf(.enum_literal),
894/// character is escaped as \xNN, where NN is the character in lowercase298) Formatter(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) {
895/// hexadecimal notation.299 return .{ .data = context };
896pub fn fmtSliceEscapeLower(bytes: []const u8) std.fmt.Formatter(formatSliceEscapeLower) {
897 return .{ .data = bytes };
898}300}
899301
900/// Return a Formatter for a []const u8 where every non-printable ASCII302test alt {
901/// character is escaped as \xNN, where NN is the character in uppercase303 const Example = struct {
902/// hexadecimal notation.304 number: u8,
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";
924305
925 const log2 = math.log2(value);306 pub fn other(ex: @This(), w: *Writer) Writer.Error!void {
926 const magnitude = switch (base) {307 try w.writeByte(ex.number);
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 }308 }
963 };309 };
964}310 const ex: Example = .{ .number = 'a' };
965const formatSizeDec = Size(1000).format;311 try expectFmt("a", "{f}", .{alt(ex, .other)});
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}
1254
1255/// Converts values in the range [0, 100) to a base 10 string.
1256pub fn digits2(value: u8) [2]u8 {
1257 if (builtin.mode == .ReleaseSmall) {
1258 return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) };
1259 } else {
1260 return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
1261 }
1262}
1263
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}312}
1471313
1472pub const ParseIntError = error{314pub const ParseIntError = error{
1473 /// The result cannot fit in the type specified315 /// The result cannot fit in the type specified.
1474 Overflow,316 Overflow,
1475317 /// The input was empty or contained an invalid character.
1476 /// The input was empty or contained an invalid character
1477 InvalidCharacter,318 InvalidCharacter,
1478};319};
1479320
1480/// Creates a Formatter type from a format function. Wrapping data in Formatter(func) causes
1481/// the data to be formatted using the given function `func`. `func` must be of the following
1482/// form:
1483///
1484/// fn formatExample(
1485/// data: T,
1486/// comptime fmt: []const u8,
1487/// options: std.fmt.FormatOptions,
1488/// writer: anytype,
1489/// ) !void;
1490///
1491pub fn Formatter(comptime formatFn: anytype) type {
1492 const Data = @typeInfo(@TypeOf(formatFn)).@"fn".params[0].type.?;
1493 return struct {
1494 data: Data,
1495 pub fn format(
1496 self: @This(),
1497 comptime fmt: []const u8,
1498 options: std.fmt.FormatOptions,
1499 writer: anytype,
1500 ) @TypeOf(writer).Error!void {
1501 try formatFn(self.data, fmt, options, writer);
1502 }
1503 };
1504}
1505
1506/// Parses the string `buf` as signed or unsigned representation in the321/// Parses the string `buf` as signed or unsigned representation in the
1507/// specified base of an integral value of type `T`.322/// specified base of an integral value of type `T`.
1508///323///
...@@ -1793,15 +608,13 @@ pub const BufPrintError = error{...@@ -1793,15 +608,13 @@ pub const BufPrintError = error{
1793 NoSpaceLeft,608 NoSpaceLeft,
1794};609};
1795610
1796/// Print a Formatter string into `buf`. Actually just a thin wrapper around `format` and `fixedBufferStream`.611/// 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 {612pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {
1799 var fbs = std.io.fixedBufferStream(buf);613 var w: Writer = .fixed(buf);
1800 format(fbs.writer().any(), fmt, args) catch |err| switch (err) {614 w.print(fmt, args) catch |err| switch (err) {
1801 error.NoSpaceLeft => return error.NoSpaceLeft,615 error.WriteFailed => return error.NoSpaceLeft,
1802 else => unreachable,
1803 };616 };
1804 return fbs.getWritten();617 return w.buffered();
1805}618}
1806619
1807pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![:0]u8 {620pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![:0]u8 {
...@@ -1809,51 +622,37 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr...@@ -1809,51 +622,37 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr
1809 return result[0 .. result.len - 1 :0];622 return result[0 .. result.len - 1 :0];
1810}623}
1811624
1812/// Count the characters needed for format. Useful for preallocating memory625/// Count the characters needed for format.
1813pub fn count(comptime fmt: []const u8, args: anytype) u64 {626pub fn count(comptime fmt: []const u8, args: anytype) usize {
1814 var counting_writer = std.io.countingWriter(std.io.null_writer);627 var trash_buffer: [64]u8 = undefined;
1815 format(counting_writer.writer().any(), fmt, args) catch unreachable;628 var dw: Writer.Discarding = .init(&trash_buffer);
1816 return counting_writer.bytes_written;629 dw.writer.print(fmt, args) catch |err| switch (err) {
1817}630 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 };631 };
632 return @intCast(dw.count + dw.writer.end);
1827}633}
1828634
1829pub fn allocPrintZ(allocator: mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![:0]u8 {635pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {
1830 const result = try allocPrint(allocator, fmt ++ "\x00", args);636 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
1831 return result[0 .. result.len - 1 :0];637 defer aw.deinit();
1832}638 aw.writer.print(fmt, args) catch |err| switch (err) {
1833639 error.WriteFailed => return error.OutOfMemory,
1834test bufPrintIntToSlice {640 };
1835 var buffer: [100]u8 = undefined;641 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}642}
1854643
1855pub fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) []u8 {644pub fn allocPrintSentinel(
1856 return buf[0..formatIntBuf(buf, value, base, case, options)];645 gpa: Allocator,
646 comptime fmt: []const u8,
647 args: anytype,
648 comptime sentinel: u8,
649) Allocator.Error![:sentinel]u8 {
650 var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
651 defer aw.deinit();
652 aw.writer.print(fmt, args) catch |err| switch (err) {
653 error.WriteFailed => return error.OutOfMemory,
654 };
655 return aw.toOwnedSliceSentinel(sentinel);
1857}656}
1858657
1859pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {658pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
...@@ -1984,26 +783,22 @@ test "int.padded" {...@@ -1984,26 +783,22 @@ test "int.padded" {
1984 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});783 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});
1985 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});784 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});
1986 try expectFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});785 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}786}
1992787
1993test "buffer" {788test "buffer" {
1994 {789 {
1995 var buf1: [32]u8 = undefined;790 var buf1: [32]u8 = undefined;
1996 var fbs = std.io.fixedBufferStream(&buf1);791 var w: Writer = .fixed(&buf1);
1997 try formatType(1234, "", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);792 try w.printValue("", .{}, 1234, std.options.fmt_max_depth);
1998 try std.testing.expectEqualStrings("1234", fbs.getWritten());793 try std.testing.expectEqualStrings("1234", w.buffered());
1999794
2000 fbs.reset();795 w = .fixed(&buf1);
2001 try formatType('a', "c", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);796 try w.printValue("c", .{}, 'a', std.options.fmt_max_depth);
2002 try std.testing.expectEqualStrings("a", fbs.getWritten());797 try std.testing.expectEqualStrings("a", w.buffered());
2003798
2004 fbs.reset();799 w = .fixed(&buf1);
2005 try formatType(0b1100, "b", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth);800 try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);
2006 try std.testing.expectEqualStrings("1100", fbs.getWritten());801 try std.testing.expectEqualStrings("1100", w.buffered());
2007 }802 }
2008}803}
2009804
...@@ -2017,36 +812,24 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime...@@ -2017,36 +812,24 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime
2017}812}
2018813
2019test "array" {814test "array" {
2020 {815 const value: [3]u8 = "abc".*;
2021 const value: [3]u8 = "abc".*;816 try expectArrayFmt("array: abc\n", "array: {s}\n", value);
2022 try expectArrayFmt("array: abc\n", "array: {s}\n", value);817 try expectArrayFmt("array: 616263\n", "array: {x}\n", value);
2023 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\n", value);818 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
2024 try expectArrayFmt("array: { 61, 62, 63 }\n", "array: {x}\n", value);
2025 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
2026
2027 var buf: [100]u8 = undefined;
2028 try expectFmt(
2029 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
2030 "array: {*}\n",
2031 .{&value},
2032 );
2033 }
2034
2035 {
2036 const value = [2][3]u8{ "abc".*, "def".* };
2037819
2038 try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value);820 var buf: [100]u8 = undefined;
2039 try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value);821 try expectFmt(
2040 try expectArrayFmt("array: { { 61, 62, 63 }, { 64, 65, 66 } }\n", "array: {x}\n", value);822 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
2041 }823 "array: {*}\n",
824 .{&value},
825 );
2042}826}
2043827
2044test "slice" {828test "slice" {
2045 {829 {
2046 const value: []const u8 = "abc";830 const value: []const u8 = "abc";
2047 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});831 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});
2048 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value});832 try expectFmt("slice: 616263\n", "slice: {x}\n", .{value});
2049 try expectFmt("slice: { 61, 62, 63 }\n", "slice: {x}\n", .{value});
2050 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});833 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});
2051 }834 }
2052 {835 {
...@@ -2060,45 +843,33 @@ test "slice" {...@@ -2060,45 +843,33 @@ test "slice" {
2060 try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice});843 try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice});
2061 }844 }
2062845
2063 try expectFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});
2064 try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});846 try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
2065847
2066 {848 {
2067 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };849 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
2068 var runtime_zero: usize = 0;850 const input: []const u32 = &int_slice;
2069 _ = &runtime_zero;851 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{input});
2070 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{int_slice[runtime_zero..]});
2071 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});
2072 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
2073 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
2074 }852 }
2075 {853 {
2076 const S1 = struct {854 const S1 = struct {
2077 x: u8,855 x: u8,
2078 };856 };
2079 const struct_slice: []const S1 = &[_]S1{ S1{ .x = 8 }, S1{ .x = 42 } };857 const struct_slice: []const S1 = &[_]S1{ S1{ .x = 8 }, S1{ .x = 42 } };
2080 try expectFmt("slice: { fmt.test.slice.S1{ .x = 8 }, fmt.test.slice.S1{ .x = 42 } }", "slice: {any}", .{struct_slice});858 try expectFmt("slice: { .{ .x = 8 }, .{ .x = 42 } }", "slice: {any}", .{struct_slice});
2081 }859 }
2082 {860 {
2083 const S2 = struct {861 const S2 = struct {
2084 x: u8,862 x: u8,
2085863
2086 pub fn format(s: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {864 pub fn format(s: @This(), writer: *Writer) Writer.Error!void {
2087 try writer.print("S2({})", .{s.x});865 try writer.print("S2({})", .{s.x});
2088 }866 }
2089 };867 };
2090 const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } };868 const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } };
2091 try expectFmt("slice: { S2(8), S2(42) }", "slice: {any}", .{struct_slice});869 try expectFmt("slice: { .{ .x = 8 }, .{ .x = 42 } }", "slice: {any}", .{struct_slice});
2092 }870 }
2093}871}
2094872
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" {873test "pointer" {
2103 {874 {
2104 const value = @as(*align(1) i32, @ptrFromInt(0xdeadbeef));875 const value = @as(*align(1) i32, @ptrFromInt(0xdeadbeef));
...@@ -2122,26 +893,6 @@ test "cstr" {...@@ -2122,26 +893,6 @@ test "cstr" {
2122 "cstr: {s}\n",893 "cstr: {s}\n",
2123 .{@as([*c]const u8, @ptrCast("Test C"))},894 .{@as([*c]const u8, @ptrCast("Test C"))},
2124 );895 );
2125 try expectFmt(
2126 "cstr: Test C\n",
2127 "cstr: {s:10}\n",
2128 .{@as([*c]const u8, @ptrCast("Test C"))},
2129 );
2130}
2131
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}896}
2146897
2147test "struct" {898test "struct" {
...@@ -2150,8 +901,8 @@ test "struct" {...@@ -2150,8 +901,8 @@ test "struct" {
2150 field: u8,901 field: u8,
2151 };902 };
2152 const value = Struct{ .field = 42 };903 const value = Struct{ .field = 42 };
2153 try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{value});904 try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{value});
2154 try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{&value});905 try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{&value});
2155 }906 }
2156 {907 {
2157 const Struct = struct {908 const Struct = struct {
...@@ -2159,7 +910,7 @@ test "struct" {...@@ -2159,7 +910,7 @@ test "struct" {
2159 b: u1,910 b: u1,
2160 };911 };
2161 const value = Struct{ .a = 0, .b = 1 };912 const value = Struct{ .a = 0, .b = 1 };
2162 try expectFmt("struct: fmt.test.struct.Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});913 try expectFmt("struct: .{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
2163 }914 }
2164915
2165 const S = struct {916 const S = struct {
...@@ -2172,11 +923,11 @@ test "struct" {...@@ -2172,11 +923,11 @@ test "struct" {
2172 .b = error.Unused,923 .b = error.Unused,
2173 };924 };
2174925
2175 try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst});926 try expectFmt(".{ .a = 456, .b = error.Unused }", "{}", .{inst});
2176 // Tuples927 // Tuples
2177 try expectFmt("{ }", "{}", .{.{}});928 try expectFmt(".{ }", "{}", .{.{}});
2178 try expectFmt("{ -1 }", "{}", .{.{-1}});929 try expectFmt(".{ -1 }", "{}", .{.{-1}});
2179 try expectFmt("{ -1, 42, 2.5e4 }", "{}", .{.{ -1, 42, 0.25e5 }});930 try expectFmt(".{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }});
2180}931}
2181932
2182test "enum" {933test "enum" {
...@@ -2185,15 +936,15 @@ test "enum" {...@@ -2185,15 +936,15 @@ test "enum" {
2185 Two,936 Two,
2186 };937 };
2187 const value = Enum.Two;938 const value = Enum.Two;
2188 try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{value});939 try expectFmt("enum: .Two\n", "enum: {}\n", .{value});
2189 try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{&value});940 try expectFmt("enum: .Two\n", "enum: {}\n", .{&value});
2190 try expectFmt("enum: fmt.test.enum.Enum.One\n", "enum: {}\n", .{Enum.One});941 try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One});
2191 try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{Enum.Two});942 try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two});
2192943
2193 // test very large enum to verify ct branch quota is large enough944 // test very large enum to verify ct branch quota is large enough
2194 // TODO: https://github.com/ziglang/zig/issues/15609945 // TODO: https://github.com/ziglang/zig/issues/15609
2195 if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) {946 if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) {
2196 try expectFmt("enum: os.windows.win32error.Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});947 try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
2197 }948 }
2198949
2199 const E = enum {950 const E = enum {
...@@ -2204,7 +955,7 @@ test "enum" {...@@ -2204,7 +955,7 @@ test "enum" {
2204955
2205 const inst = E.Two;956 const inst = E.Two;
2206957
2207 try expectFmt("fmt.test.enum.E.Two", "{}", .{inst});958 try expectFmt(".Two", "{}", .{inst});
2208}959}
2209960
2210test "non-exhaustive enum" {961test "non-exhaustive enum" {
...@@ -2213,13 +964,17 @@ test "non-exhaustive enum" {...@@ -2213,13 +964,17 @@ test "non-exhaustive enum" {
2213 Two = 0xbeef,964 Two = 0xbeef,
2214 _,965 _,
2215 };966 };
2216 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One});967 try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One});
2217 try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two});968 try expectFmt("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))});969 try expectFmt("enum: @enumFromInt(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});970 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});971 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});972 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))});973 try expectFmt("enum: 1234\n", "enum: {x}\n", .{@as(Enum, @enumFromInt(0x1234))});
974
975 try expectFmt("enum: 15\n", "enum: {d}\n", .{Enum.One});
976 try expectFmt("enum: 48879\n", "enum: {d}\n", .{Enum.Two});
977 try expectFmt("enum: 4660\n", "enum: {d}\n", .{@as(Enum, @enumFromInt(0x1234))});
2223}978}
2224979
2225test "float.scientific" {980test "float.scientific" {
...@@ -2345,41 +1100,6 @@ test "float.libc.sanity" {...@@ -2345,41 +1100,6 @@ test "float.libc.sanity" {
2345 try expectFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1518338049))))});1100 try expectFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1518338049))))});
2346}1101}
23471102
2348test "custom" {
2349 const Vec2 = struct {
2350 const SelfType = @This();
2351 x: f32,
2352 y: f32,
2353
2354 pub fn format(
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")) {
2362 return std.fmt.format(writer, "({d:.3},{d:.3})", .{ self.x, self.y });
2363 } else if (comptime std.mem.eql(u8, fmt, "d")) {
2364 return std.fmt.format(writer, "{d:.3}x{d:.3}", .{ self.x, self.y });
2365 } else {
2366 @compileError("unknown format character: '" ++ fmt ++ "'");
2367 }
2368 }
2369 };
2370
2371 var value = Vec2{
2372 .x = 10.2,
2373 .y = 2.22,
2374 };
2375 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
2376 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
2377
2378 // same thing but not passing a pointer
2379 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
2380 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
2381}
2382
2383test "union" {1103test "union" {
2384 const TU = union(enum) {1104 const TU = union(enum) {
2385 float: f32,1105 float: f32,
...@@ -2396,18 +1116,13 @@ test "union" {...@@ -2396,18 +1116,13 @@ test "union" {
2396 int: u32,1116 int: u32,
2397 };1117 };
23981118
2399 const tu_inst = TU{ .int = 123 };1119 const tu_inst: TU = .{ .int = 123 };
2400 const uu_inst = UU{ .int = 456 };1120 const uu_inst: UU = .{ .int = 456 };
2401 const eu_inst = EU{ .float = 321.123 };1121 const eu_inst: EU = .{ .float = 321.123 };
2402
2403 try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst});
24041122
2405 var buf: [100]u8 = undefined;1123 try expectFmt(".{ .int = 123 }", "{}", .{tu_inst});
2406 const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});1124 try expectFmt(".{ ... }", "{}", .{uu_inst});
2407 try std.testing.expectEqualStrings("fmt.test.union.UU@", uu_result[0..18]);1125 try expectFmt(".{ .float = 321.123, .int = 1134596030 }", "{}", .{eu_inst});
2408
2409 const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
2410 try std.testing.expectEqualStrings("fmt.test.union.EU@", eu_result[0..18]);
2411}1126}
24121127
2413test "struct.self-referential" {1128test "struct.self-referential" {
...@@ -2421,7 +1136,7 @@ test "struct.self-referential" {...@@ -2421,7 +1136,7 @@ test "struct.self-referential" {
2421 };1136 };
2422 inst.a = &inst;1137 inst.a = &inst;
24231138
2424 try expectFmt("fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ ... } } } }", "{}", .{inst});1139 try expectFmt(".{ .a = .{ .a = .{ .a = .{ ... } } } }", "{}", .{inst});
2425}1140}
24261141
2427test "struct.zero-size" {1142test "struct.zero-size" {
...@@ -2436,18 +1151,7 @@ test "struct.zero-size" {...@@ -2436,18 +1151,7 @@ test "struct.zero-size" {
2436 const a = A{};1151 const a = A{};
2437 const b = B{ .a = a, .c = 0 };1152 const b = B{ .a = a, .c = 0 };
24381153
2439 try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b});1154 try expectFmt(".{ .a = .{ }, .c = 0 }", "{}", .{b});
2440}
2441
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}1155}
24521156
2453/// Encodes a sequence of bytes as hexadecimal digits.1157/// Encodes a sequence of bytes as hexadecimal digits.
...@@ -2494,110 +1198,14 @@ test bytesToHex {...@@ -2494,110 +1198,14 @@ test bytesToHex {
24941198
2495test hexToBytes {1199test hexToBytes {
2496 var buf: [32]u8 = undefined;1200 var buf: [32]u8 = undefined;
2497 try expectFmt("90" ** 32, "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "90" ** 32))});1201 try expectFmt("90" ** 32, "{X}", .{try hexToBytes(&buf, "90" ** 32)});
2498 try expectFmt("ABCD", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "ABCD"))});1202 try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")});
2499 try expectFmt("", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, ""))});1203 try expectFmt("", "{X}", .{try hexToBytes(&buf, "")});
2500 try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));1204 try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));
2501 try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));1205 try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));
2502 try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));1206 try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));
2503}1207}
25041208
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" {1209test "positional" {
2602 try expectFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });1210 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) });1211 try expectFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
...@@ -2654,33 +1262,17 @@ test "enum-literal" {...@@ -2654,33 +1262,17 @@ test "enum-literal" {
26541262
2655test "padding" {1263test "padding" {
2656 try expectFmt("Simple", "{s}", .{"Simple"});1264 try expectFmt("Simple", "{s}", .{"Simple"});
2657 try expectFmt(" true", "{:10}", .{true});1265 try expectFmt(" 1234", "{:10}", .{1234});
2658 try expectFmt(" true", "{:>10}", .{true});1266 try expectFmt(" 1234", "{:>10}", .{1234});
2659 try expectFmt("======true", "{:=>10}", .{true});1267 try expectFmt("======1234", "{:=>10}", .{1234});
2660 try expectFmt("true======", "{:=<10}", .{true});1268 try expectFmt("1234======", "{:=<10}", .{1234});
2661 try expectFmt(" true ", "{:^10}", .{true});1269 try expectFmt(" 1234 ", "{:^10}", .{1234});
2662 try expectFmt("===true===", "{:=^10}", .{true});1270 try expectFmt("===1234===", "{:=^10}", .{1234});
2663 try expectFmt(" Minimum width", "{s:18} width", .{"Minimum"});
2664 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});
2665 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});
2666 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'});1271 try expectFmt("====a", "{c:=>5}", .{'a'});
2671 try expectFmt("==a==", "{c:=^5}", .{'a'});1272 try expectFmt("==a==", "{c:=^5}", .{'a'});
2672 try expectFmt("a====", "{c:=<5}", .{'a'});1273 try expectFmt("a====", "{c:=<5}", .{'a'});
2673}1274}
26741275
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" {1276test "decimal float padding" {
2685 const number: f32 = 3.1415;1277 const number: f32 = 3.1415;
2686 try expectFmt("left-pad: **3.142\n", "left-pad: {d:*>7.3}\n", .{number});1278 try expectFmt("left-pad: **3.142\n", "left-pad: {d:*>7.3}\n", .{number});
...@@ -2723,17 +1315,17 @@ test "named arguments" {...@@ -2723,17 +1315,17 @@ test "named arguments" {
27231315
2724test "runtime width specifier" {1316test "runtime width specifier" {
2725 const width: usize = 9;1317 const width: usize = 9;
2726 try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });1318 try expectFmt("~~12345~~", "{d:~^[1]}", .{ 12345, width });
2727 try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });1319 try expectFmt("~~12345~~", "{d:~^[width]}", .{ .string = 12345, .width = width });
2728 try expectFmt(" hello", "{s:[1]}", .{ "hello", width });1320 try expectFmt(" 12345", "{d:[1]}", .{ 12345, width });
2729 try expectFmt("42 hello", "{d} {s:[2]}", .{ 42, "hello", width });1321 try expectFmt("42 12345", "{d} {d:[2]}", .{ 42, 12345, width });
2730}1322}
27311323
2732test "runtime precision specifier" {1324test "runtime precision specifier" {
2733 const number: f32 = 3.1415;1325 const number: f32 = 3.1415;
2734 const precision: usize = 2;1326 const precision: usize = 2;
2735 try expectFmt("3.14e0", "{:1.[1]}", .{ number, precision });1327 try expectFmt("3.14e0", "{e:1.[1]}", .{ number, precision });
2736 try expectFmt("3.14e0", "{:1.[precision]}", .{ .number = number, .precision = precision });1328 try expectFmt("3.14e0", "{e:1.[precision]}", .{ .number = number, .precision = precision });
2737}1329}
27381330
2739test "recursive format function" {1331test "recursive format function" {
...@@ -2742,16 +1334,16 @@ test "recursive format function" {...@@ -2742,16 +1334,16 @@ test "recursive format function" {
2742 Leaf: i32,1334 Leaf: i32,
2743 Branch: struct { left: *const R, right: *const R },1335 Branch: struct { left: *const R, right: *const R },
27441336
2745 pub fn format(self: R, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {1337 pub fn format(self: R, writer: *Writer) Writer.Error!void {
2746 return switch (self) {1338 return switch (self) {
2747 .Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}),1339 .Leaf => |n| writer.print("Leaf({})", .{n}),
2748 .Branch => |b| std.fmt.format(writer, "Branch({}, {})", .{ b.left, b.right }),1340 .Branch => |b| writer.print("Branch({f}, {f})", .{ b.left, b.right }),
2749 };1341 };
2750 }1342 }
2751 };1343 };
27521344
2753 var r = R{ .Leaf = 1 };1345 var r: R = .{ .Leaf = 1 };
2754 try expectFmt("Leaf(1)\n", "{}\n", .{&r});1346 try expectFmt("Leaf(1)\n", "{f}\n", .{&r});
2755}1347}
27561348
2757pub const hex_charset = "0123456789abcdef";1349pub const hex_charset = "0123456789abcdef";
...@@ -2785,54 +1377,39 @@ test hex {...@@ -2785,54 +1377,39 @@ test hex {
27851377
2786test "parser until" {1378test "parser until" {
2787 { // return substring till ':'1379 { // return substring till ':'
2788 var parser: Parser = .{1380 var parser: Parser = .{ .bytes = "abc:1234", .i = 0 };
2789 .iter = .{ .bytes = "abc:1234", .i = 0 },
2790 };
2791 try testing.expectEqualStrings("abc", parser.until(':'));1381 try testing.expectEqualStrings("abc", parser.until(':'));
2792 }1382 }
27931383
2794 { // return the entire string - `ch` not found1384 { // return the entire string - `ch` not found
2795 var parser: Parser = .{1385 var parser: Parser = .{ .bytes = "abc1234", .i = 0 };
2796 .iter = .{ .bytes = "abc1234", .i = 0 },
2797 };
2798 try testing.expectEqualStrings("abc1234", parser.until(':'));1386 try testing.expectEqualStrings("abc1234", parser.until(':'));
2799 }1387 }
28001388
2801 { // substring is empty - `ch` is the only character1389 { // substring is empty - `ch` is the only character
2802 var parser: Parser = .{1390 var parser: Parser = .{ .bytes = ":", .i = 0 };
2803 .iter = .{ .bytes = ":", .i = 0 },
2804 };
2805 try testing.expectEqualStrings("", parser.until(':'));1391 try testing.expectEqualStrings("", parser.until(':'));
2806 }1392 }
28071393
2808 { // empty string and `ch` not found1394 { // empty string and `ch` not found
2809 var parser: Parser = .{1395 var parser: Parser = .{ .bytes = "", .i = 0 };
2810 .iter = .{ .bytes = "", .i = 0 },
2811 };
2812 try testing.expectEqualStrings("", parser.until(':'));1396 try testing.expectEqualStrings("", parser.until(':'));
2813 }1397 }
28141398
2815 { // substring starts at index 2 and goes upto `ch`1399 { // substring starts at index 2 and goes upto `ch`
2816 var parser: Parser = .{1400 var parser: Parser = .{ .bytes = "abc:1234", .i = 2 };
2817 .iter = .{ .bytes = "abc:1234", .i = 2 },
2818 };
2819 try testing.expectEqualStrings("c", parser.until(':'));1401 try testing.expectEqualStrings("c", parser.until(':'));
2820 }1402 }
28211403
2822 { // substring starts at index 4 and goes upto the end - `ch` not found1404 { // substring starts at index 4 and goes upto the end - `ch` not found
2823 var parser: Parser = .{1405 var parser: Parser = .{ .bytes = "abc1234", .i = 4 };
2824 .iter = .{ .bytes = "abc1234", .i = 4 },
2825 };
2826 try testing.expectEqualStrings("234", parser.until(':'));1406 try testing.expectEqualStrings("234", parser.until(':'));
2827 }1407 }
2828}1408}
28291409
2830test "parser peek" {1410test "parser peek" {
2831 { // start iteration from the first index1411 { // start iteration from the first index
2832 var parser: Parser = .{1412 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));1413 try testing.expectEqual('h', parser.peek(0));
2837 try testing.expectEqual('e', parser.peek(1));1414 try testing.expectEqual('e', parser.peek(1));
2838 try testing.expectEqual(' ', parser.peek(5));1415 try testing.expectEqual(' ', parser.peek(5));
...@@ -2841,9 +1418,7 @@ test "parser peek" {...@@ -2841,9 +1418,7 @@ test "parser peek" {
2841 }1418 }
28421419
2843 { // start iteration from the second last index1420 { // start iteration from the second last index
2844 var parser: Parser = .{1421 var parser: Parser = .{ .bytes = "hello world!", .i = 10 };
2845 .iter = .{ .bytes = "hello world!", .i = 10 },
2846 };
28471422
2848 try testing.expectEqual('d', parser.peek(0));1423 try testing.expectEqual('d', parser.peek(0));
2849 try testing.expectEqual('!', parser.peek(1));1424 try testing.expectEqual('!', parser.peek(1));
...@@ -2851,18 +1426,14 @@ test "parser peek" {...@@ -2851,18 +1426,14 @@ test "parser peek" {
2851 }1426 }
28521427
2853 { // start iteration beyond the length of the string1428 { // start iteration beyond the length of the string
2854 var parser: Parser = .{1429 var parser: Parser = .{ .bytes = "hello", .i = 5 };
2855 .iter = .{ .bytes = "hello", .i = 5 },
2856 };
28571430
2858 try testing.expectEqual(null, parser.peek(0));1431 try testing.expectEqual(null, parser.peek(0));
2859 try testing.expectEqual(null, parser.peek(1));1432 try testing.expectEqual(null, parser.peek(1));
2860 }1433 }
28611434
2862 { // empty string1435 { // empty string
2863 var parser: Parser = .{1436 var parser: Parser = .{ .bytes = "", .i = 0 };
2864 .iter = .{ .bytes = "", .i = 0 },
2865 };
28661437
2867 try testing.expectEqual(null, parser.peek(0));1438 try testing.expectEqual(null, parser.peek(0));
2868 try testing.expectEqual(null, parser.peek(2));1439 try testing.expectEqual(null, parser.peek(2));
...@@ -2871,78 +1442,78 @@ test "parser peek" {...@@ -2871,78 +1442,78 @@ test "parser peek" {
28711442
2872test "parser char" {1443test "parser char" {
2873 // character exists - iterator at 01444 // character exists - iterator at 0
2874 var parser: Parser = .{ .iter = .{ .bytes = "~~hello", .i = 0 } };1445 var parser: Parser = .{ .bytes = "~~hello", .i = 0 };
2875 try testing.expectEqual('~', parser.char());1446 try testing.expectEqual('~', parser.char());
28761447
2877 // character exists - iterator in the middle1448 // character exists - iterator in the middle
2878 parser = .{ .iter = .{ .bytes = "~~hello", .i = 3 } };1449 parser = .{ .bytes = "~~hello", .i = 3 };
2879 try testing.expectEqual('e', parser.char());1450 try testing.expectEqual('e', parser.char());
28801451
2881 // character exists - iterator at the end1452 // character exists - iterator at the end
2882 parser = .{ .iter = .{ .bytes = "~~hello", .i = 6 } };1453 parser = .{ .bytes = "~~hello", .i = 6 };
2883 try testing.expectEqual('o', parser.char());1454 try testing.expectEqual('o', parser.char());
28841455
2885 // character doesn't exist - iterator beyond the length of the string1456 // character doesn't exist - iterator beyond the length of the string
2886 parser = .{ .iter = .{ .bytes = "~~hello", .i = 7 } };1457 parser = .{ .bytes = "~~hello", .i = 7 };
2887 try testing.expectEqual(null, parser.char());1458 try testing.expectEqual(null, parser.char());
2888}1459}
28891460
2890test "parser maybe" {1461test "parser maybe" {
2891 // character exists - iterator at 01462 // character exists - iterator at 0
2892 var parser: Parser = .{ .iter = .{ .bytes = "hello world", .i = 0 } };1463 var parser: Parser = .{ .bytes = "hello world", .i = 0 };
2893 try testing.expect(parser.maybe('h'));1464 try testing.expect(parser.maybe('h'));
28941465
2895 // character exists - iterator at space1466 // character exists - iterator at space
2896 parser = .{ .iter = .{ .bytes = "hello world", .i = 5 } };1467 parser = .{ .bytes = "hello world", .i = 5 };
2897 try testing.expect(parser.maybe(' '));1468 try testing.expect(parser.maybe(' '));
28981469
2899 // character exists - iterator at the end1470 // character exists - iterator at the end
2900 parser = .{ .iter = .{ .bytes = "hello world", .i = 10 } };1471 parser = .{ .bytes = "hello world", .i = 10 };
2901 try testing.expect(parser.maybe('d'));1472 try testing.expect(parser.maybe('d'));
29021473
2903 // character doesn't exist - iterator beyond the length of the string1474 // character doesn't exist - iterator beyond the length of the string
2904 parser = .{ .iter = .{ .bytes = "hello world", .i = 11 } };1475 parser = .{ .bytes = "hello world", .i = 11 };
2905 try testing.expect(!parser.maybe('e'));1476 try testing.expect(!parser.maybe('e'));
2906}1477}
29071478
2908test "parser number" {1479test "parser number" {
2909 // input is a single digit natural number - iterator at 01480 // input is a single digit natural number - iterator at 0
2910 var parser: Parser = .{ .iter = .{ .bytes = "7", .i = 0 } };1481 var parser: Parser = .{ .bytes = "7", .i = 0 };
2911 try testing.expect(7 == parser.number());1482 try testing.expect(7 == parser.number());
29121483
2913 // input is a two digit natural number - iterator at 11484 // input is a two digit natural number - iterator at 1
2914 parser = .{ .iter = .{ .bytes = "29", .i = 1 } };1485 parser = .{ .bytes = "29", .i = 1 };
2915 try testing.expect(9 == parser.number());1486 try testing.expect(9 == parser.number());
29161487
2917 // input is a two digit natural number - iterator beyond the length of the string1488 // input is a two digit natural number - iterator beyond the length of the string
2918 parser = .{ .iter = .{ .bytes = "32", .i = 2 } };1489 parser = .{ .bytes = "32", .i = 2 };
2919 try testing.expectEqual(null, parser.number());1490 try testing.expectEqual(null, parser.number());
29201491
2921 // input is an integer1492 // input is an integer
2922 parser = .{ .iter = .{ .bytes = "0", .i = 0 } };1493 parser = .{ .bytes = "0", .i = 0 };
2923 try testing.expect(0 == parser.number());1494 try testing.expect(0 == parser.number());
29241495
2925 // input is a negative integer1496 // input is a negative integer
2926 parser = .{ .iter = .{ .bytes = "-2", .i = 0 } };1497 parser = .{ .bytes = "-2", .i = 0 };
2927 try testing.expectEqual(null, parser.number());1498 try testing.expectEqual(null, parser.number());
29281499
2929 // input is a string1500 // input is a string
2930 parser = .{ .iter = .{ .bytes = "no_number", .i = 2 } };1501 parser = .{ .bytes = "no_number", .i = 2 };
2931 try testing.expectEqual(null, parser.number());1502 try testing.expectEqual(null, parser.number());
29321503
2933 // input is a single character string1504 // input is a single character string
2934 parser = .{ .iter = .{ .bytes = "n", .i = 0 } };1505 parser = .{ .bytes = "n", .i = 0 };
2935 try testing.expectEqual(null, parser.number());1506 try testing.expectEqual(null, parser.number());
29361507
2937 // input is an empty string1508 // input is an empty string
2938 parser = .{ .iter = .{ .bytes = "", .i = 0 } };1509 parser = .{ .bytes = "", .i = 0 };
2939 try testing.expectEqual(null, parser.number());1510 try testing.expectEqual(null, parser.number());
2940}1511}
29411512
2942test "parser specifier" {1513test "parser specifier" {
2943 { // input string is a digit; iterator at 01514 { // input string is a digit; iterator at 0
2944 const expected: Specifier = Specifier{ .number = 1 };1515 const expected: Specifier = Specifier{ .number = 1 };
2945 var parser: Parser = .{ .iter = .{ .bytes = "1", .i = 0 } };1516 var parser: Parser = .{ .bytes = "1", .i = 0 };
29461517
2947 const result = try parser.specifier();1518 const result = try parser.specifier();
2948 try testing.expect(expected.number == result.number);1519 try testing.expect(expected.number == result.number);
...@@ -2950,7 +1521,7 @@ test "parser specifier" {...@@ -2950,7 +1521,7 @@ test "parser specifier" {
29501521
2951 { // input string is a two digit number; iterator at 01522 { // input string is a two digit number; iterator at 0
2952 const digit: Specifier = Specifier{ .number = 42 };1523 const digit: Specifier = Specifier{ .number = 42 };
2953 var parser: Parser = .{ .iter = .{ .bytes = "42", .i = 0 } };1524 var parser: Parser = .{ .bytes = "42", .i = 0 };
29541525
2955 const result = try parser.specifier();1526 const result = try parser.specifier();
2956 try testing.expect(digit.number == result.number);1527 try testing.expect(digit.number == result.number);
...@@ -2958,7 +1529,7 @@ test "parser specifier" {...@@ -2958,7 +1529,7 @@ test "parser specifier" {
29581529
2959 { // input string is a two digit number digit; iterator at 11530 { // input string is a two digit number digit; iterator at 1
2960 const digit: Specifier = Specifier{ .number = 8 };1531 const digit: Specifier = Specifier{ .number = 8 };
2961 var parser: Parser = .{ .iter = .{ .bytes = "28", .i = 1 } };1532 var parser: Parser = .{ .bytes = "28", .i = 1 };
29621533
2963 const result = try parser.specifier();1534 const result = try parser.specifier();
2964 try testing.expect(digit.number == result.number);1535 try testing.expect(digit.number == result.number);
...@@ -2966,7 +1537,7 @@ test "parser specifier" {...@@ -2966,7 +1537,7 @@ test "parser specifier" {
29661537
2967 { // input string is a two digit number with square brackets; iterator at 01538 { // input string is a two digit number with square brackets; iterator at 0
2968 const digit: Specifier = Specifier{ .named = "15" };1539 const digit: Specifier = Specifier{ .named = "15" };
2969 var parser: Parser = .{ .iter = .{ .bytes = "[15]", .i = 0 } };1540 var parser: Parser = .{ .bytes = "[15]", .i = 0 };
29701541
2971 const result = try parser.specifier();1542 const result = try parser.specifier();
2972 try testing.expectEqualStrings(digit.named, result.named);1543 try testing.expectEqualStrings(digit.named, result.named);
...@@ -2974,21 +1545,21 @@ test "parser specifier" {...@@ -2974,21 +1545,21 @@ test "parser specifier" {
29741545
2975 { // input string is not a number and contains square brackets; iterator at 01546 { // input string is not a number and contains square brackets; iterator at 0
2976 const digit: Specifier = Specifier{ .named = "hello" };1547 const digit: Specifier = Specifier{ .named = "hello" };
2977 var parser: Parser = .{ .iter = .{ .bytes = "[hello]", .i = 0 } };1548 var parser: Parser = .{ .bytes = "[hello]", .i = 0 };
29781549
2979 const result = try parser.specifier();1550 const result = try parser.specifier();
2980 try testing.expectEqualStrings(digit.named, result.named);1551 try testing.expectEqualStrings(digit.named, result.named);
2981 }1552 }
29821553
2983 { // input string is not a number and doesn't contain closing square bracket; iterator at 01554 { // 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 } };1555 var parser: Parser = .{ .bytes = "[hello", .i = 0 };
29851556
2986 const result = parser.specifier();1557 const result = parser.specifier();
2987 try testing.expectError(@field(anyerror, "Expected closing ]"), result);1558 try testing.expectError(@field(anyerror, "Expected closing ]"), result);
2988 }1559 }
29891560
2990 { // input string is not a number and doesn't contain closing square bracket; iterator at 21561 { // 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 } };1562 var parser: Parser = .{ .bytes = "[[[[hello", .i = 2 };
29921563
2993 const result = parser.specifier();1564 const result = parser.specifier();
2994 try testing.expectError(@field(anyerror, "Expected closing ]"), result);1565 try testing.expectError(@field(anyerror, "Expected closing ]"), result);
...@@ -2996,7 +1567,7 @@ test "parser specifier" {...@@ -2996,7 +1567,7 @@ test "parser specifier" {
29961567
2997 { // input string is not a number and contains unbalanced square brackets; iterator at 01568 { // input string is not a number and contains unbalanced square brackets; iterator at 0
2998 const digit: Specifier = Specifier{ .named = "[[hello" };1569 const digit: Specifier = Specifier{ .named = "[[hello" };
2999 var parser: Parser = .{ .iter = .{ .bytes = "[[[hello]", .i = 0 } };1570 var parser: Parser = .{ .bytes = "[[[hello]", .i = 0 };
30001571
3001 const result = try parser.specifier();1572 const result = try parser.specifier();
3002 try testing.expectEqualStrings(digit.named, result.named);1573 try testing.expectEqualStrings(digit.named, result.named);
...@@ -3004,7 +1575,7 @@ test "parser specifier" {...@@ -3004,7 +1575,7 @@ test "parser specifier" {
30041575
3005 { // input string is not a number and contains unbalanced square brackets; iterator at 11576 { // input string is not a number and contains unbalanced square brackets; iterator at 1
3006 const digit: Specifier = Specifier{ .named = "[[hello" };1577 const digit: Specifier = Specifier{ .named = "[[hello" };
3007 var parser: Parser = .{ .iter = .{ .bytes = "[[[[hello]]]]]", .i = 1 } };1578 var parser: Parser = .{ .bytes = "[[[[hello]]]]]", .i = 1 };
30081579
3009 const result = try parser.specifier();1580 const result = try parser.specifier();
3010 try testing.expectEqualStrings(digit.named, result.named);1581 try testing.expectEqualStrings(digit.named, result.named);
...@@ -3012,9 +1583,13 @@ test "parser specifier" {...@@ -3012,9 +1583,13 @@ test "parser specifier" {
30121583
3013 { // input string is neither a digit nor a named argument1584 { // input string is neither a digit nor a named argument
3014 const char: Specifier = Specifier{ .none = {} };1585 const char: Specifier = Specifier{ .none = {} };
3015 var parser: Parser = .{ .iter = .{ .bytes = "hello", .i = 0 } };1586 var parser: Parser = .{ .bytes = "hello", .i = 0 };
30161587
3017 const result = try parser.specifier();1588 const result = try parser.specifier();
3018 try testing.expectEqual(char.none, result.none);1589 try testing.expectEqual(char.none, result.none);
3019 }1590 }
3020}1591}
1592
1593test {
1594 _ = float;
1595}
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+857-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.Reader(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.Writer(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,800 @@ pub const SeekableStream = io.SeekableStream(...@@ -1603,10 +1222,800 @@ 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 /// Tracks the true seek position in the file. To obtain the logical
1244 /// position, subtract the buffer size from this value.
1245 pos: u64 = 0,
1246 size: ?u64 = null,
1247 size_err: ?GetEndPosError = null,
1248 seek_err: ?Reader.SeekError = null,
1249 interface: std.io.Reader,
1250
1251 pub const SeekError = File.SeekError || error{
1252 /// Seeking fell back to reading, and reached the end before the requested seek position.
1253 /// `pos` remains at the end of the file.
1254 EndOfStream,
1255 /// Seeking fell back to reading, which failed.
1256 ReadFailed,
1257 };
1258
1259 pub const Mode = enum {
1260 streaming,
1261 positional,
1262 /// Avoid syscalls other than `read` and `readv`.
1263 streaming_reading,
1264 /// Avoid syscalls other than `pread` and `preadv`.
1265 positional_reading,
1266 /// Indicates reading cannot continue because of a seek failure.
1267 failure,
1268
1269 pub fn toStreaming(m: @This()) @This() {
1270 return switch (m) {
1271 .positional, .streaming => .streaming,
1272 .positional_reading, .streaming_reading => .streaming_reading,
1273 .failure => .failure,
1274 };
1275 }
1276
1277 pub fn toReading(m: @This()) @This() {
1278 return switch (m) {
1279 .positional, .positional_reading => .positional_reading,
1280 .streaming, .streaming_reading => .streaming_reading,
1281 .failure => .failure,
1282 };
1283 }
1284 };
1285
1286 pub fn initInterface(buffer: []u8) std.io.Reader {
1287 return .{
1288 .vtable = &.{
1289 .stream = Reader.stream,
1290 .discard = Reader.discard,
1291 },
1292 .buffer = buffer,
1293 .seek = 0,
1294 .end = 0,
1295 };
1296 }
1297
1298 pub fn init(file: File, buffer: []u8) Reader {
1299 return .{
1300 .file = file,
1301 .interface = initInterface(buffer),
1302 };
1303 }
1304
1305 pub fn initSize(file: File, buffer: []u8, size: ?u64) Reader {
1306 return .{
1307 .file = file,
1308 .interface = initInterface(buffer),
1309 .size = size,
1310 };
1311 }
1312
1313 pub fn initMode(file: File, buffer: []u8, init_mode: Reader.Mode) Reader {
1314 return .{
1315 .file = file,
1316 .interface = initInterface(buffer),
1317 .mode = init_mode,
1318 };
1319 }
1320
1321 pub fn getSize(r: *Reader) GetEndPosError!u64 {
1322 return r.size orelse {
1323 if (r.size_err) |err| return err;
1324 if (r.file.getEndPos()) |size| {
1325 r.size = size;
1326 return size;
1327 } else |err| {
1328 r.size_err = err;
1329 return err;
1330 }
1331 };
1332 }
1333
1334 pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
1335 switch (r.mode) {
1336 .positional, .positional_reading => {
1337 // TODO: make += operator allow any integer types
1338 r.pos = @intCast(@as(i64, @intCast(r.pos)) + offset);
1339 },
1340 .streaming, .streaming_reading => {
1341 const seek_err = r.seek_err orelse e: {
1342 if (posix.lseek_CUR(r.file.handle, offset)) |_| {
1343 // TODO: make += operator allow any integer types
1344 r.pos = @intCast(@as(i64, @intCast(r.pos)) + offset);
1345 return;
1346 } else |err| {
1347 r.seek_err = err;
1348 break :e err;
1349 }
1350 };
1351 var remaining = std.math.cast(u64, offset) orelse return seek_err;
1352 while (remaining > 0) {
1353 const n = discard(&r.interface, .limited64(remaining)) catch |err| {
1354 r.seek_err = err;
1355 return err;
1356 };
1357 r.pos += n;
1358 remaining -= n;
1359 }
1360 },
1361 .failure => return r.seek_err.?,
1362 }
1363 }
1364
1365 pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
1366 switch (r.mode) {
1367 .positional, .positional_reading => {
1368 r.pos = offset;
1369 },
1370 .streaming, .streaming_reading => {
1371 if (offset >= r.pos) return Reader.seekBy(r, offset - r.pos);
1372 if (r.seek_err) |err| return err;
1373 posix.lseek_SET(r.file.handle, offset) catch |err| {
1374 r.seek_err = err;
1375 return err;
1376 };
1377 r.pos = offset;
1378 },
1379 .failure => return r.seek_err.?,
1380 }
1381 }
1382
1383 /// Number of slices to store on the stack, when trying to send as many byte
1384 /// vectors through the underlying read calls as possible.
1385 const max_buffers_len = 16;
1386
1387 fn stream(io_reader: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
1388 const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
1389 switch (r.mode) {
1390 .positional, .streaming => return w.sendFile(r, limit) catch |write_err| switch (write_err) {
1391 error.Unimplemented => {
1392 r.mode = r.mode.toReading();
1393 return 0;
1394 },
1395 else => |e| return e,
1396 },
1397 .positional_reading => {
1398 if (is_windows) {
1399 // Unfortunately, `ReadFileScatter` cannot be used since it
1400 // requires page alignment.
1401 const dest = limit.slice(try w.writableSliceGreedy(1));
1402 const n = try readPositional(r, dest);
1403 w.advance(n);
1404 return n;
1405 }
1406 var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
1407 const dest = try w.writableVectorPosix(&iovecs_buffer, limit);
1408 assert(dest[0].len > 0);
1409 const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
1410 error.Unseekable => {
1411 r.mode = r.mode.toStreaming();
1412 const pos = r.pos;
1413 if (pos != 0) {
1414 r.pos = 0;
1415 r.seekBy(@intCast(pos)) catch {
1416 r.mode = .failure;
1417 return error.ReadFailed;
1418 };
1419 }
1420 return 0;
1421 },
1422 else => |e| {
1423 r.err = e;
1424 return error.ReadFailed;
1425 },
1426 };
1427 if (n == 0) {
1428 r.size = r.pos;
1429 return error.EndOfStream;
1430 }
1431 r.pos += n;
1432 return n;
1433 },
1434 .streaming_reading => {
1435 if (is_windows) {
1436 // Unfortunately, `ReadFileScatter` cannot be used since it
1437 // requires page alignment.
1438 const dest = limit.slice(try w.writableSliceGreedy(1));
1439 const n = try readStreaming(r, dest);
1440 w.advance(n);
1441 return n;
1442 }
1443 var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
1444 const dest = try w.writableVectorPosix(&iovecs_buffer, limit);
1445 assert(dest[0].len > 0);
1446 const n = posix.readv(r.file.handle, dest) catch |err| {
1447 r.err = err;
1448 return error.ReadFailed;
1449 };
1450 if (n == 0) {
1451 r.size = r.pos;
1452 return error.EndOfStream;
1453 }
1454 r.pos += n;
1455 return n;
1456 },
1457 .failure => return error.ReadFailed,
1458 }
1459 }
1460
1461 fn discard(io_reader: *std.io.Reader, limit: std.io.Limit) std.io.Reader.Error!usize {
1462 const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
1463 const file = r.file;
1464 const pos = r.pos;
1465 switch (r.mode) {
1466 .positional, .positional_reading => {
1467 const size = r.size orelse {
1468 if (file.getEndPos()) |size| {
1469 r.size = size;
1470 } else |err| {
1471 r.size_err = err;
1472 r.mode = r.mode.toStreaming();
1473 }
1474 return 0;
1475 };
1476 const delta = @min(@intFromEnum(limit), size - pos);
1477 r.pos = pos + delta;
1478 return delta;
1479 },
1480 .streaming, .streaming_reading => {
1481 // Unfortunately we can't seek forward without knowing the
1482 // size because the seek syscalls provided to us will not
1483 // return the true end position if a seek would exceed the
1484 // end.
1485 fallback: {
1486 if (r.size_err == null and r.seek_err == null) break :fallback;
1487 var trash_buffer: [128]u8 = undefined;
1488 const trash = &trash_buffer;
1489 if (is_windows) {
1490 const n = windows.ReadFile(file.handle, trash, null) catch |err| {
1491 r.err = err;
1492 return error.ReadFailed;
1493 };
1494 if (n == 0) {
1495 r.size = pos;
1496 return error.EndOfStream;
1497 }
1498 r.pos = pos + n;
1499 return n;
1500 }
1501 var iovecs: [max_buffers_len]std.posix.iovec = undefined;
1502 var iovecs_i: usize = 0;
1503 var remaining = @intFromEnum(limit);
1504 while (remaining > 0 and iovecs_i < iovecs.len) {
1505 iovecs[iovecs_i] = .{ .base = trash, .len = @min(trash.len, remaining) };
1506 remaining -= iovecs[iovecs_i].len;
1507 iovecs_i += 1;
1508 }
1509 const n = posix.readv(file.handle, iovecs[0..iovecs_i]) catch |err| {
1510 r.err = err;
1511 return error.ReadFailed;
1512 };
1513 if (n == 0) {
1514 r.size = pos;
1515 return error.EndOfStream;
1516 }
1517 r.pos = pos + n;
1518 return n;
1519 }
1520 const size = r.size orelse {
1521 if (file.getEndPos()) |size| {
1522 r.size = size;
1523 } else |err| {
1524 r.size_err = err;
1525 }
1526 return 0;
1527 };
1528 const n = @min(size - pos, std.math.maxInt(i64), @intFromEnum(limit));
1529 file.seekBy(n) catch |err| {
1530 r.seek_err = err;
1531 return 0;
1532 };
1533 r.pos = pos + n;
1534 return n;
1535 },
1536 .failure => return error.ReadFailed,
1537 }
1538 }
1539
1540 pub fn readPositional(r: *Reader, dest: []u8) std.io.Reader.Error!usize {
1541 const n = r.file.pread(dest, r.pos) catch |err| switch (err) {
1542 error.Unseekable => {
1543 r.mode = r.mode.toStreaming();
1544 const pos = r.pos;
1545 if (pos != 0) {
1546 r.pos = 0;
1547 r.seekBy(@intCast(pos)) catch {
1548 r.mode = .failure;
1549 return error.ReadFailed;
1550 };
1551 }
1552 return 0;
1553 },
1554 else => |e| {
1555 r.err = e;
1556 return error.ReadFailed;
1557 },
1558 };
1559 if (n == 0) {
1560 r.size = r.pos;
1561 return error.EndOfStream;
1562 }
1563 r.pos += n;
1564 return n;
1565 }
1566
1567 pub fn readStreaming(r: *Reader, dest: []u8) std.io.Reader.Error!usize {
1568 const n = r.file.read(dest) catch |err| {
1569 r.err = err;
1570 return error.ReadFailed;
1571 };
1572 if (n == 0) {
1573 r.size = r.pos;
1574 return error.EndOfStream;
1575 }
1576 r.pos += n;
1577 return n;
1578 }
1579
1580 pub fn read(r: *Reader, dest: []u8) std.io.Reader.Error!usize {
1581 switch (r.mode) {
1582 .positional, .positional_reading => return readPositional(r, dest),
1583 .streaming, .streaming_reading => return readStreaming(r, dest),
1584 .failure => return error.ReadFailed,
1585 }
1586 }
1587
1588 pub fn atEnd(r: *Reader) bool {
1589 // Even if stat fails, size is set when end is encountered.
1590 const size = r.size orelse return false;
1591 return size - r.pos == 0;
1592 }
1593};
1594
1595pub const Writer = struct {
1596 file: File,
1597 err: ?WriteError = null,
1598 mode: Writer.Mode = .positional,
1599 /// Tracks the true seek position in the file. To obtain the logical
1600 /// position, add the buffer size to this value.
1601 pos: u64 = 0,
1602 sendfile_err: ?SendfileError = null,
1603 copy_file_range_err: ?CopyFileRangeError = null,
1604 fcopyfile_err: ?FcopyfileError = null,
1605 seek_err: ?SeekError = null,
1606 interface: std.io.Writer,
1607
1608 pub const Mode = Reader.Mode;
1609
1610 pub const SendfileError = error{
1611 UnsupportedOperation,
1612 SystemResources,
1613 InputOutput,
1614 BrokenPipe,
1615 WouldBlock,
1616 Unexpected,
1617 };
1618
1619 pub const CopyFileRangeError = std.os.freebsd.CopyFileRangeError || std.os.linux.wrapped.CopyFileRangeError;
1620
1621 pub const FcopyfileError = error{
1622 OperationNotSupported,
1623 OutOfMemory,
1624 Unexpected,
1625 };
1626
1627 /// Number of slices to store on the stack, when trying to send as many byte
1628 /// vectors through the underlying write calls as possible.
1629 const max_buffers_len = 16;
1630
1631 pub fn init(file: File, buffer: []u8) Writer {
1632 return initMode(file, buffer, .positional);
1633 }
1634
1635 pub fn initMode(file: File, buffer: []u8, init_mode: Writer.Mode) Writer {
1636 return .{
1637 .file = file,
1638 .interface = initInterface(buffer),
1639 .mode = init_mode,
1640 };
1641 }
1642
1643 pub fn initInterface(buffer: []u8) std.io.Writer {
1644 return .{
1645 .vtable = &.{
1646 .drain = drain,
1647 .sendFile = sendFile,
1648 },
1649 .buffer = buffer,
1650 };
1651 }
1652
1653 pub fn moveToReader(w: *Writer) Reader {
1654 defer w.* = undefined;
1655 return .{
1656 .file = w.file,
1657 .mode = w.mode,
1658 .pos = w.pos,
1659 .seek_err = w.seek_err,
1660 };
1661 }
1662
1663 pub fn drain(io_w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
1664 const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
1665 const handle = w.file.handle;
1666 const buffered = io_w.buffered();
1667 if (is_windows) switch (w.mode) {
1668 .positional, .positional_reading => {
1669 if (buffered.len != 0) {
1670 const n = windows.WriteFile(handle, buffered, w.pos) catch |err| {
1671 w.err = err;
1672 return error.WriteFailed;
1673 };
1674 w.pos += n;
1675 return io_w.consume(n);
1676 }
1677 for (data[0 .. data.len - 1]) |buf| {
1678 if (buf.len == 0) continue;
1679 const n = windows.WriteFile(handle, buf, w.pos) catch |err| {
1680 w.err = err;
1681 return error.WriteFailed;
1682 };
1683 w.pos += n;
1684 return io_w.consume(n);
1685 }
1686 const pattern = data[data.len - 1];
1687 if (pattern.len == 0 or splat == 0) return 0;
1688 const n = windows.WriteFile(handle, pattern, w.pos) catch |err| {
1689 w.err = err;
1690 return error.WriteFailed;
1691 };
1692 w.pos += n;
1693 return io_w.consume(n);
1694 },
1695 .streaming, .streaming_reading => {
1696 if (buffered.len != 0) {
1697 const n = windows.WriteFile(handle, buffered, null) catch |err| {
1698 w.err = err;
1699 return error.WriteFailed;
1700 };
1701 w.pos += n;
1702 return io_w.consume(n);
1703 }
1704 for (data[0 .. data.len - 1]) |buf| {
1705 if (buf.len == 0) continue;
1706 const n = windows.WriteFile(handle, buf, null) catch |err| {
1707 w.err = err;
1708 return error.WriteFailed;
1709 };
1710 w.pos += n;
1711 return io_w.consume(n);
1712 }
1713 const pattern = data[data.len - 1];
1714 if (pattern.len == 0 or splat == 0) return 0;
1715 const n = windows.WriteFile(handle, pattern, null) catch |err| {
1716 std.debug.print("windows write file failed3: {t}\n", .{err});
1717 w.err = err;
1718 return error.WriteFailed;
1719 };
1720 w.pos += n;
1721 return io_w.consume(n);
1722 },
1723 .failure => return error.WriteFailed,
1724 };
1725 var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
1726 var len: usize = 0;
1727 if (buffered.len > 0) {
1728 iovecs[len] = .{ .base = buffered.ptr, .len = buffered.len };
1729 len += 1;
1730 }
1731 for (data[0 .. data.len - 1]) |d| {
1732 if (d.len == 0) continue;
1733 iovecs[len] = .{ .base = d.ptr, .len = d.len };
1734 len += 1;
1735 if (iovecs.len - len == 0) break;
1736 }
1737 const pattern = data[data.len - 1];
1738 if (iovecs.len - len != 0) switch (splat) {
1739 0 => {},
1740 1 => if (pattern.len != 0) {
1741 iovecs[len] = .{ .base = pattern.ptr, .len = pattern.len };
1742 len += 1;
1743 },
1744 else => switch (pattern.len) {
1745 0 => {},
1746 1 => {
1747 const splat_buffer_candidate = io_w.buffer[io_w.end..];
1748 var backup_buffer: [64]u8 = undefined;
1749 const splat_buffer = if (splat_buffer_candidate.len >= backup_buffer.len)
1750 splat_buffer_candidate
1751 else
1752 &backup_buffer;
1753 const memset_len = @min(splat_buffer.len, splat);
1754 const buf = splat_buffer[0..memset_len];
1755 @memset(buf, pattern[0]);
1756 iovecs[len] = .{ .base = buf.ptr, .len = buf.len };
1757 len += 1;
1758 var remaining_splat = splat - buf.len;
1759 while (remaining_splat > splat_buffer.len and iovecs.len - len != 0) {
1760 assert(buf.len == splat_buffer.len);
1761 iovecs[len] = .{ .base = splat_buffer.ptr, .len = splat_buffer.len };
1762 len += 1;
1763 remaining_splat -= splat_buffer.len;
1764 }
1765 if (remaining_splat > 0 and iovecs.len - len != 0) {
1766 iovecs[len] = .{ .base = splat_buffer.ptr, .len = remaining_splat };
1767 len += 1;
1768 }
1769 },
1770 else => for (0..splat) |_| {
1771 iovecs[len] = .{ .base = pattern.ptr, .len = pattern.len };
1772 len += 1;
1773 if (iovecs.len - len == 0) break;
1774 },
1775 },
1776 };
1777 if (len == 0) return 0;
1778 switch (w.mode) {
1779 .positional, .positional_reading => {
1780 const n = std.posix.pwritev(handle, iovecs[0..len], w.pos) catch |err| switch (err) {
1781 error.Unseekable => {
1782 w.mode = w.mode.toStreaming();
1783 const pos = w.pos;
1784 if (pos != 0) {
1785 w.pos = 0;
1786 w.seekTo(@intCast(pos)) catch {
1787 w.mode = .failure;
1788 return error.WriteFailed;
1789 };
1790 }
1791 return 0;
1792 },
1793 else => |e| {
1794 w.err = e;
1795 return error.WriteFailed;
1796 },
1797 };
1798 w.pos += n;
1799 return io_w.consume(n);
1800 },
1801 .streaming, .streaming_reading => {
1802 const n = std.posix.writev(handle, iovecs[0..len]) catch |err| {
1803 w.err = err;
1804 return error.WriteFailed;
1805 };
1806 w.pos += n;
1807 return io_w.consume(n);
1808 },
1809 .failure => return error.WriteFailed,
1810 }
1811 }
1812
1813 pub fn sendFile(
1814 io_w: *std.io.Writer,
1815 file_reader: *Reader,
1816 limit: std.io.Limit,
1817 ) std.io.Writer.FileError!usize {
1818 const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
1819 const out_fd = w.file.handle;
1820 const in_fd = file_reader.file.handle;
1821 // TODO try using copy_file_range on FreeBSD
1822 // TODO try using sendfile on macOS
1823 // TODO try using sendfile on FreeBSD
1824 if (native_os == .linux and w.mode == .streaming) sf: {
1825 // Try using sendfile on Linux.
1826 if (w.sendfile_err != null) break :sf;
1827 // Linux sendfile does not support headers.
1828 const buffered = limit.slice(file_reader.interface.buffer);
1829 if (io_w.end != 0 or buffered.len != 0) return drain(io_w, &.{buffered}, 1);
1830 const max_count = 0x7ffff000; // Avoid EINVAL.
1831 var off: std.os.linux.off_t = undefined;
1832 const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {
1833 .positional => o: {
1834 const size = file_reader.size orelse {
1835 if (file_reader.file.getEndPos()) |size| {
1836 file_reader.size = size;
1837 } else |err| {
1838 file_reader.size_err = err;
1839 file_reader.mode = .streaming;
1840 }
1841 return 0;
1842 };
1843 off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed;
1844 break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) };
1845 },
1846 .streaming => .{ null, limit.minInt(max_count) },
1847 .streaming_reading, .positional_reading => break :sf,
1848 .failure => return error.ReadFailed,
1849 };
1850 const n = std.os.linux.wrapped.sendfile(out_fd, in_fd, off_ptr, count) catch |err| switch (err) {
1851 error.Unseekable => {
1852 file_reader.mode = file_reader.mode.toStreaming();
1853 const pos = file_reader.pos;
1854 if (pos != 0) {
1855 file_reader.pos = 0;
1856 file_reader.seekBy(@intCast(pos)) catch {
1857 file_reader.mode = .failure;
1858 return error.ReadFailed;
1859 };
1860 }
1861 return 0;
1862 },
1863 else => |e| {
1864 w.sendfile_err = e;
1865 return 0;
1866 },
1867 };
1868 if (n == 0) {
1869 file_reader.size = file_reader.pos;
1870 return error.EndOfStream;
1871 }
1872 file_reader.pos += n;
1873 w.pos += n;
1874 return n;
1875 }
1876 const copy_file_range = switch (native_os) {
1877 .freebsd => std.os.freebsd.copy_file_range,
1878 .linux => if (std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })) std.os.linux.wrapped.copy_file_range else {},
1879 else => {},
1880 };
1881 if (@TypeOf(copy_file_range) != void) cfr: {
1882 if (w.copy_file_range_err != null) break :cfr;
1883 const buffered = limit.slice(file_reader.interface.buffer);
1884 if (io_w.end != 0 or buffered.len != 0) return drain(io_w, &.{buffered}, 1);
1885 var off_in: i64 = undefined;
1886 var off_out: i64 = undefined;
1887 const off_in_ptr: ?*i64 = switch (file_reader.mode) {
1888 .positional_reading, .streaming_reading => return error.Unimplemented,
1889 .positional => p: {
1890 off_in = @intCast(file_reader.pos);
1891 break :p &off_in;
1892 },
1893 .streaming => null,
1894 .failure => return error.WriteFailed,
1895 };
1896 const off_out_ptr: ?*i64 = switch (w.mode) {
1897 .positional_reading, .streaming_reading => return error.Unimplemented,
1898 .positional => p: {
1899 off_out = @intCast(w.pos);
1900 break :p &off_out;
1901 },
1902 .streaming => null,
1903 .failure => return error.WriteFailed,
1904 };
1905 const n = copy_file_range(in_fd, off_in_ptr, out_fd, off_out_ptr, @intFromEnum(limit), 0) catch |err| {
1906 w.copy_file_range_err = err;
1907 return 0;
1908 };
1909 if (n == 0) {
1910 file_reader.size = file_reader.pos;
1911 return error.EndOfStream;
1912 }
1913 file_reader.pos += n;
1914 w.pos += n;
1915 return n;
1916 }
1917
1918 if (builtin.os.tag.isDarwin()) fcf: {
1919 if (w.fcopyfile_err != null) break :fcf;
1920 if (file_reader.pos != 0) break :fcf;
1921 if (w.pos != 0) break :fcf;
1922 if (limit != .unlimited) break :fcf;
1923 const rc = std.c.fcopyfile(in_fd, out_fd, null, .{ .DATA = true });
1924 switch (posix.errno(rc)) {
1925 .SUCCESS => {},
1926 .INVAL => if (builtin.mode == .Debug) @panic("invalid API usage") else {
1927 w.fcopyfile_err = error.Unexpected;
1928 return 0;
1929 },
1930 .NOMEM => {
1931 w.fcopyfile_err = error.OutOfMemory;
1932 return 0;
1933 },
1934 .OPNOTSUPP => {
1935 w.fcopyfile_err = error.OperationNotSupported;
1936 return 0;
1937 },
1938 else => |err| {
1939 w.fcopyfile_err = posix.unexpectedErrno(err);
1940 return 0;
1941 },
1942 }
1943 const n = if (file_reader.size) |size| size else @panic("TODO figure out how much copied");
1944 file_reader.pos = n;
1945 w.pos = n;
1946 return n;
1947 }
1948
1949 return error.Unimplemented;
1950 }
1951
1952 pub fn seekTo(w: *Writer, offset: u64) SeekError!void {
1953 switch (w.mode) {
1954 .positional, .positional_reading => {
1955 w.pos = offset;
1956 },
1957 .streaming, .streaming_reading => {
1958 if (w.seek_err) |err| return err;
1959 posix.lseek_SET(w.file.handle, offset) catch |err| {
1960 w.seek_err = err;
1961 return err;
1962 };
1963 w.pos = offset;
1964 },
1965 .failure => return w.seek_err.?,
1966 }
1967 }
1968
1969 pub const EndError = SetEndPosError || std.io.Writer.Error;
1970
1971 /// Flushes any buffered data and sets the end position of the file.
1972 ///
1973 /// If not overwriting existing contents, then calling `interface.flush`
1974 /// directly is sufficient.
1975 ///
1976 /// Flush failure is handled by setting `err` so that it can be handled
1977 /// along with other write failures.
1978 pub fn end(w: *Writer) EndError!void {
1979 try w.interface.flush();
1980 return w.file.setEndPos(w.pos);
1981 }
1982};
1983
1984/// Defaults to positional reading; falls back to streaming.
1985///
1986/// Positional is more threadsafe, since the global seek position is not
1987/// affected.
1988pub fn reader(file: File, buffer: []u8) Reader {
1989 return .init(file, buffer);
1990}
1991
1992/// Positional is more threadsafe, since the global seek position is not
1993/// affected, but when such syscalls are not available, preemptively choosing
1994/// `Reader.Mode.streaming` will skip a failed syscall.
1995pub fn readerStreaming(file: File, buffer: []u8) Reader {
1996 return .{
1997 .file = file,
1998 .interface = Reader.initInterface(buffer),
1999 .mode = .streaming,
2000 .seek_err = error.Unseekable,
2001 };
2002}
2003
2004/// Defaults to positional reading; falls back to streaming.
2005///
2006/// Positional is more threadsafe, since the global seek position is not
2007/// affected.
2008pub fn writer(file: File, buffer: []u8) Writer {
2009 return .init(file, buffer);
2010}
2011
2012/// Positional is more threadsafe, since the global seek position is not
2013/// affected, but when such syscalls are not available, preemptively choosing
2014/// `Writer.Mode.streaming` will skip a failed syscall.
2015pub fn writerStreaming(file: File, buffer: []u8) Writer {
2016 return .initMode(file, buffer, .streaming);
2017}
2018
1610const range_off: windows.LARGE_INTEGER = 0;2019const range_off: windows.LARGE_INTEGER = 0;
1611const range_len: windows.LARGE_INTEGER = 1;2020const range_len: windows.LARGE_INTEGER = 1;
16122021
...@@ -1769,18 +2178,3 @@ pub fn downgradeLock(file: File) LockError!void {...@@ -1769,18 +2178,3 @@ pub fn downgradeLock(file: File) LockError!void {
1769 };2178 };
1770 }2179 }
1771}2180}
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.io.getStdOut().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+12-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,8 @@ pub const Method = enum(u64) {...@@ -38,8 +42,8 @@ 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) std.io.Writer.Error!void {
42 const bytes = std.mem.asBytes(&@intFromEnum(self));46 const bytes: []const u8 = @ptrCast(&@intFromEnum(self));
43 const str = std.mem.sliceTo(bytes, 0);47 const str = std.mem.sliceTo(bytes, 0);
44 try w.writeAll(str);48 try w.writeAll(str);
45 }49 }
...@@ -77,7 +81,9 @@ pub const Method = enum(u64) {...@@ -77,7 +81,9 @@ pub const Method = enum(u64) {
77 };81 };
78 }82 }
7983
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.84 /// An HTTP method is idempotent if an identical request can be made once
85 /// or several times in a row with the same effect while leaving the server
86 /// in the same state.
81 ///87 ///
82 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent88 /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
83 ///89 ///
...@@ -90,7 +96,8 @@ pub const Method = enum(u64) {...@@ -90,7 +96,8 @@ pub const Method = enum(u64) {
90 };96 };
91 }97 }
9298
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.99 /// A cacheable response can be stored to be retrieved and used later,
100 /// saving a new request to the server.
94 ///101 ///
95 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable102 /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable
96 ///103 ///
...@@ -282,10 +289,10 @@ pub const Status = enum(u10) {...@@ -282,10 +289,10 @@ pub const Status = enum(u10) {
282 }289 }
283};290};
284291
292/// compression is intentionally omitted here since it is handled in `ContentEncoding`.
285pub const TransferEncoding = enum {293pub const TransferEncoding = enum {
286 chunked,294 chunked,
287 none,295 none,
288 // compression is intentionally omitted here, as std.http.Client stores it as content-encoding
289};296};
290297
291pub const ContentEncoding = enum {298pub const ContentEncoding = enum {
...@@ -308,9 +315,6 @@ pub const Header = struct {...@@ -308,9 +315,6 @@ pub const Header = struct {
308 value: []const u8,315 value: []const u8,
309};316};
310317
311const builtin = @import("builtin");
312const std = @import("std.zig");
313
314test {318test {
315 if (builtin.os.tag != .wasi) {319 if (builtin.os.tag != .wasi) {
316 _ = Client;320 _ = Client;
lib/std/http/Client.zig+37-24
...@@ -311,7 +311,7 @@ pub const Connection = struct {...@@ -311,7 +311,7 @@ pub const Connection = struct {
311 EndOfStream,311 EndOfStream,
312 };312 };
313313
314 pub const Reader = std.io.Reader(*Connection, ReadError, read);314 pub const Reader = std.io.GenericReader(*Connection, ReadError, read);
315315
316 pub fn reader(conn: *Connection) Reader {316 pub fn reader(conn: *Connection) Reader {
317 return Reader{ .context = conn };317 return Reader{ .context = conn };
...@@ -374,7 +374,7 @@ pub const Connection = struct {...@@ -374,7 +374,7 @@ pub const Connection = struct {
374 UnexpectedWriteFailure,374 UnexpectedWriteFailure,
375 };375 };
376376
377 pub const Writer = std.io.Writer(*Connection, WriteError, write);377 pub const Writer = std.io.GenericWriter(*Connection, WriteError, write);
378378
379 pub fn writer(conn: *Connection) Writer {379 pub fn writer(conn: *Connection) Writer {
380 return Writer{ .context = conn };380 return Writer{ .context = conn };
...@@ -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
...@@ -934,7 +941,7 @@ pub const Request = struct {...@@ -934,7 +941,7 @@ pub const Request = struct {
934941
935 const TransferReadError = Connection.ReadError || proto.HeadersParser.ReadError;942 const TransferReadError = Connection.ReadError || proto.HeadersParser.ReadError;
936943
937 const TransferReader = std.io.Reader(*Request, TransferReadError, transferRead);944 const TransferReader = std.io.GenericReader(*Request, TransferReadError, transferRead);
938945
939 fn transferReader(req: *Request) TransferReader {946 fn transferReader(req: *Request) TransferReader {
940 return .{ .context = req };947 return .{ .context = req };
...@@ -1094,7 +1101,7 @@ pub const Request = struct {...@@ -1094,7 +1101,7 @@ pub const Request = struct {
1094 pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError ||1101 pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError ||
1095 error{ DecompressionFailure, InvalidTrailers };1102 error{ DecompressionFailure, InvalidTrailers };
10961103
1097 pub const Reader = std.io.Reader(*Request, ReadError, read);1104 pub const Reader = std.io.GenericReader(*Request, ReadError, read);
10981105
1099 pub fn reader(req: *Request) Reader {1106 pub fn reader(req: *Request) Reader {
1100 return .{ .context = req };1107 return .{ .context = req };
...@@ -1134,7 +1141,7 @@ pub const Request = struct {...@@ -1134,7 +1141,7 @@ pub const Request = struct {
11341141
1135 pub const WriteError = Connection.WriteError || error{ NotWriteable, MessageTooLong };1142 pub const WriteError = Connection.WriteError || error{ NotWriteable, MessageTooLong };
11361143
1137 pub const Writer = std.io.Writer(*Request, WriteError, write);1144 pub const Writer = std.io.GenericWriter(*Request, WriteError, write);
11381145
1139 pub fn writer(req: *Request) Writer {1146 pub fn writer(req: *Request) Writer {
1140 return .{ .context = req };1147 return .{ .context = req };
...@@ -1283,26 +1290,32 @@ pub const basic_authorization = struct {...@@ -1283,26 +1290,32 @@ pub const basic_authorization = struct {
1283 }1290 }
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 const user: Uri.Component = uri.user orelse .empty;
1287 try stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty});1294 const password: Uri.Component = uri.password orelse .empty;
1288 const user_len = stream.bytes_written;1295
1289 stream.bytes_written = 0;1296 var dw: std.io.Writer.Discarding = .init(&.{});
1290 try stream.writer().print("{password}", .{uri.password orelse Uri.Component.empty});1297 user.formatUser(&dw.writer) catch unreachable; // discarding
1291 const password_len = stream.bytes_written;1298 const user_len = dw.count + dw.writer.end;
1299
1300 dw.count = 0;
1301 dw.writer.end = 0;
1302 password.formatPassword(&dw.writer) catch unreachable; // discarding
1303 const password_len = dw.count + dw.writer.end;
1304
1292 return valueLength(@intCast(user_len), @intCast(password_len));1305 return valueLength(@intCast(user_len), @intCast(password_len));
1293 }1306 }
12941307
1295 pub fn value(uri: Uri, out: []u8) []u8 {1308 pub fn value(uri: Uri, out: []u8) []u8 {
1309 const user: Uri.Component = uri.user orelse .empty;
1310 const password: Uri.Component = uri.password orelse .empty;
1311
1296 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;1312 var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
1297 var stream = std.io.fixedBufferStream(&buf);1313 var w: std.io.Writer = .fixed(&buf);
1298 stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch1314 user.formatUser(&w) catch unreachable; // fixed
1299 unreachable;1315 password.formatPassword(&w) catch unreachable; // fixed
1300 assert(stream.pos <= max_user_len);
1301 stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch
1302 unreachable;
13031316
1304 @memcpy(out[0..prefix.len], prefix);1317 @memcpy(out[0..prefix.len], prefix);
1305 const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], stream.getWritten());1318 const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], w.buffered());
1306 return out[0 .. prefix.len + base64.len];1319 return out[0 .. prefix.len + base64.len];
1307 }1320 }
1308};1321};
lib/std/http/protocol.zig+2-2
...@@ -344,7 +344,7 @@ const MockBufferedConnection = struct {...@@ -344,7 +344,7 @@ const MockBufferedConnection = struct {
344 }344 }
345345
346 pub const ReadError = std.io.FixedBufferStream([]const u8).ReadError || error{EndOfStream};346 pub const ReadError = std.io.FixedBufferStream([]const u8).ReadError || error{EndOfStream};
347 pub const Reader = std.io.Reader(*MockBufferedConnection, ReadError, read);347 pub const Reader = std.io.GenericReader(*MockBufferedConnection, ReadError, read);
348348
349 pub fn reader(conn: *MockBufferedConnection) Reader {349 pub fn reader(conn: *MockBufferedConnection) Reader {
350 return Reader{ .context = conn };350 return Reader{ .context = conn };
...@@ -359,7 +359,7 @@ const MockBufferedConnection = struct {...@@ -359,7 +359,7 @@ const MockBufferedConnection = struct {
359 }359 }
360360
361 pub const WriteError = std.io.FixedBufferStream([]const u8).WriteError;361 pub const WriteError = std.io.FixedBufferStream([]const u8).WriteError;
362 pub const Writer = std.io.Writer(*MockBufferedConnection, WriteError, write);362 pub const Writer = std.io.GenericWriter(*MockBufferedConnection, WriteError, write);
363363
364 pub fn writer(conn: *MockBufferedConnection) Writer {364 pub fn writer(conn: *MockBufferedConnection) Writer {
365 return Writer{ .context = conn };365 return Writer{ .context = conn };
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+90-42
...@@ -14,54 +14,80 @@ const File = std.fs.File;...@@ -14,54 +14,80 @@ const File = std.fs.File;
14const Allocator = std.mem.Allocator;14const Allocator = std.mem.Allocator;
15const Alignment = std.mem.Alignment;15const Alignment = std.mem.Alignment;
1616
17fn getStdOutHandle() posix.fd_t {17pub const Limit = enum(usize) {
18 if (is_windows) {18 nothing = 0,
19 return windows.peb().ProcessParameters.hStdOutput;19 unlimited = std.math.maxInt(usize),
20 _,
21
22 /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`.
23 pub fn limited(n: usize) Limit {
24 return @enumFromInt(n);
20 }25 }
2126
22 if (@hasDecl(root, "os") and @hasDecl(root.os, "io") and @hasDecl(root.os.io, "getStdOutHandle")) {27 /// Any value grater than `std.math.maxInt(usize)` is interpreted to mean
23 return root.os.io.getStdOutHandle();28 /// `.unlimited`.
29 pub fn limited64(n: u64) Limit {
30 return @enumFromInt(@min(n, std.math.maxInt(usize)));
24 }31 }
2532
26 return posix.STDOUT_FILENO;33 pub fn countVec(data: []const []const u8) Limit {
27}34 var total: usize = 0;
35 for (data) |d| total += d.len;
36 return .limited(total);
37 }
2838
29pub fn getStdOut() File {39 pub fn min(a: Limit, b: Limit) Limit {
30 return .{ .handle = getStdOutHandle() };40 return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
31}41 }
3242
33fn getStdErrHandle() posix.fd_t {43 pub fn minInt(l: Limit, n: usize) usize {
34 if (is_windows) {44 return @min(n, @intFromEnum(l));
35 return windows.peb().ProcessParameters.hStdError;
36 }45 }
3746
38 if (@hasDecl(root, "os") and @hasDecl(root.os, "io") and @hasDecl(root.os.io, "getStdErrHandle")) {47 pub fn minInt64(l: Limit, n: u64) usize {
39 return root.os.io.getStdErrHandle();48 return @min(n, @intFromEnum(l));
40 }49 }
4150
42 return posix.STDERR_FILENO;51 pub fn slice(l: Limit, s: []u8) []u8 {
43}52 return s[0..l.minInt(s.len)];
53 }
4454
45pub fn getStdErr() File {55 pub fn sliceConst(l: Limit, s: []const u8) []const u8 {
46 return .{ .handle = getStdErrHandle() };56 return s[0..l.minInt(s.len)];
47}57 }
4858
49fn getStdInHandle() posix.fd_t {59 pub fn toInt(l: Limit) ?usize {
50 if (is_windows) {60 return switch (l) {
51 return windows.peb().ProcessParameters.hStdInput;61 else => @intFromEnum(l),
62 .unlimited => null,
63 };
52 }64 }
5365
54 if (@hasDecl(root, "os") and @hasDecl(root.os, "io") and @hasDecl(root.os.io, "getStdInHandle")) {66 /// Reduces a slice to account for the limit, leaving room for one extra
55 return root.os.io.getStdInHandle();67 /// byte above the limit, allowing for the use case of differentiating
68 /// between end-of-stream and reaching the limit.
69 pub fn slice1(l: Limit, non_empty_buffer: []u8) []u8 {
70 assert(non_empty_buffer.len >= 1);
71 return non_empty_buffer[0..@min(@intFromEnum(l) +| 1, non_empty_buffer.len)];
56 }72 }
5773
58 return posix.STDIN_FILENO;74 pub fn nonzero(l: Limit) bool {
59}75 return @intFromEnum(l) > 0;
76 }
6077
61pub fn getStdIn() File {78 /// Return a new limit reduced by `amount` or return `null` indicating
62 return .{ .handle = getStdInHandle() };79 /// limit would be exceeded.
63}80 pub fn subtract(l: Limit, amount: usize) ?Limit {
81 if (l == .unlimited) return .unlimited;
82 if (amount > @intFromEnum(l)) return null;
83 return @enumFromInt(@intFromEnum(l) - amount);
84 }
85};
86
87pub const Reader = @import("io/Reader.zig");
88pub const Writer = @import("io/Writer.zig");
6489
90/// Deprecated in favor of `Reader`.
65pub fn GenericReader(91pub fn GenericReader(
66 comptime Context: type,92 comptime Context: type,
67 comptime ReadError: type,93 comptime ReadError: type,
...@@ -289,6 +315,7 @@ pub fn GenericReader(...@@ -289,6 +315,7 @@ pub fn GenericReader(
289 };315 };
290}316}
291317
318/// Deprecated in favor of `Writer`.
292pub fn GenericWriter(319pub fn GenericWriter(
293 comptime Context: type,320 comptime Context: type,
294 comptime WriteError: type,321 comptime WriteError: type,
...@@ -347,18 +374,39 @@ pub fn GenericWriter(...@@ -347,18 +374,39 @@ pub fn GenericWriter(
347 const ptr: *const Context = @alignCast(@ptrCast(context));374 const ptr: *const Context = @alignCast(@ptrCast(context));
348 return writeFn(ptr.*, bytes);375 return writeFn(ptr.*, bytes);
349 }376 }
377
378 /// Helper for bridging to the new `Writer` API while upgrading.
379 pub fn adaptToNewApi(self: *const Self) Adapter {
380 return .{
381 .derp_writer = self.*,
382 .new_interface = .{
383 .buffer = &.{},
384 .vtable = &.{ .drain = Adapter.drain },
385 },
386 };
387 }
388
389 pub const Adapter = struct {
390 derp_writer: Self,
391 new_interface: Writer,
392 err: ?Error = null,
393
394 fn drain(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
395 _ = splat;
396 const a: *@This() = @fieldParentPtr("new_interface", w);
397 return a.derp_writer.write(data[0]) catch |err| {
398 a.err = err;
399 return error.WriteFailed;
400 };
401 }
402 };
350 };403 };
351}404}
352405
353/// Deprecated; consider switching to `AnyReader` or use `GenericReader`406/// Deprecated in favor of `Reader`.
354/// to use previous API.407pub const AnyReader = @import("io/DeprecatedReader.zig");
355pub const Reader = GenericReader;408/// Deprecated in favor of `Writer`.
356/// Deprecated; consider switching to `AnyWriter` or use `GenericWriter`409pub const AnyWriter = @import("io/DeprecatedWriter.zig");
357/// to use previous API.
358pub const Writer = GenericWriter;
359
360pub const AnyReader = @import("io/Reader.zig");
361pub const AnyWriter = @import("io/Writer.zig");
362410
363pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;411pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
364412
...@@ -407,7 +455,7 @@ pub const tty = @import("io/tty.zig");...@@ -407,7 +455,7 @@ pub const tty = @import("io/tty.zig");
407/// A Writer that doesn't write to anything.455/// A Writer that doesn't write to anything.
408pub const null_writer: NullWriter = .{ .context = {} };456pub const null_writer: NullWriter = .{ .context = {} };
409457
410pub const NullWriter = Writer(void, error{}, dummyWrite);458pub const NullWriter = GenericWriter(void, error{}, dummyWrite);
411fn dummyWrite(context: void, data: []const u8) error{}!usize {459fn dummyWrite(context: void, data: []const u8) error{}!usize {
412 _ = context;460 _ = context;
413 return data.len;461 return data.len;
...@@ -819,8 +867,8 @@ pub fn PollFiles(comptime StreamEnum: type) type {...@@ -819,8 +867,8 @@ pub fn PollFiles(comptime StreamEnum: type) type {
819}867}
820868
821test {869test {
822 _ = AnyReader;870 _ = Reader;
823 _ = AnyWriter;871 _ = Writer;
824 _ = @import("io/bit_reader.zig");872 _ = @import("io/bit_reader.zig");
825 _ = @import("io/bit_writer.zig");873 _ = @import("io/bit_writer.zig");
826 _ = @import("io/buffered_atomic_file.zig");874 _ = @import("io/buffered_atomic_file.zig");
lib/std/io/DeprecatedReader.zig created+386
...@@ -0,0 +1,386 @@
1context: *const anyopaque,
2readFn: *const fn (context: *const anyopaque, buffer: []u8) anyerror!usize,
3
4pub const Error = anyerror;
5
6/// Returns the number of bytes read. It may be less than buffer.len.
7/// If the number of bytes read is 0, it means end of stream.
8/// End of stream is not an error condition.
9pub fn read(self: Self, buffer: []u8) anyerror!usize {
10 return self.readFn(self.context, buffer);
11}
12
13/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
14/// means the stream reached the end. Reaching the end of a stream is not an error
15/// condition.
16pub fn readAll(self: Self, buffer: []u8) anyerror!usize {
17 return readAtLeast(self, buffer, buffer.len);
18}
19
20/// Returns the number of bytes read, calling the underlying read
21/// function the minimal number of times until the buffer has at least
22/// `len` bytes filled. If the number read is less than `len` it means
23/// the stream reached the end. Reaching the end of the stream is not
24/// an error condition.
25pub fn readAtLeast(self: Self, buffer: []u8, len: usize) anyerror!usize {
26 assert(len <= buffer.len);
27 var index: usize = 0;
28 while (index < len) {
29 const amt = try self.read(buffer[index..]);
30 if (amt == 0) break;
31 index += amt;
32 }
33 return index;
34}
35
36/// If the number read would be smaller than `buf.len`, `error.EndOfStream` is returned instead.
37pub fn readNoEof(self: Self, buf: []u8) anyerror!void {
38 const amt_read = try self.readAll(buf);
39 if (amt_read < buf.len) return error.EndOfStream;
40}
41
42/// Appends to the `std.ArrayList` contents by reading from the stream
43/// until end of stream is found.
44/// If the number of bytes appended would exceed `max_append_size`,
45/// `error.StreamTooLong` is returned
46/// and the `std.ArrayList` has exactly `max_append_size` bytes appended.
47pub fn readAllArrayList(
48 self: Self,
49 array_list: *std.ArrayList(u8),
50 max_append_size: usize,
51) anyerror!void {
52 return self.readAllArrayListAligned(null, array_list, max_append_size);
53}
54
55pub fn readAllArrayListAligned(
56 self: Self,
57 comptime alignment: ?Alignment,
58 array_list: *std.ArrayListAligned(u8, alignment),
59 max_append_size: usize,
60) anyerror!void {
61 try array_list.ensureTotalCapacity(@min(max_append_size, 4096));
62 const original_len = array_list.items.len;
63 var start_index: usize = original_len;
64 while (true) {
65 array_list.expandToCapacity();
66 const dest_slice = array_list.items[start_index..];
67 const bytes_read = try self.readAll(dest_slice);
68 start_index += bytes_read;
69
70 if (start_index - original_len > max_append_size) {
71 array_list.shrinkAndFree(original_len + max_append_size);
72 return error.StreamTooLong;
73 }
74
75 if (bytes_read != dest_slice.len) {
76 array_list.shrinkAndFree(start_index);
77 return;
78 }
79
80 // This will trigger ArrayList to expand superlinearly at whatever its growth rate is.
81 try array_list.ensureTotalCapacity(start_index + 1);
82 }
83}
84
85/// Allocates enough memory to hold all the contents of the stream. If the allocated
86/// memory would be greater than `max_size`, returns `error.StreamTooLong`.
87/// Caller owns returned memory.
88/// If this function returns an error, the contents from the stream read so far are lost.
89pub fn readAllAlloc(self: Self, allocator: mem.Allocator, max_size: usize) anyerror![]u8 {
90 var array_list = std.ArrayList(u8).init(allocator);
91 defer array_list.deinit();
92 try self.readAllArrayList(&array_list, max_size);
93 return try array_list.toOwnedSlice();
94}
95
96/// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead.
97/// Replaces the `std.ArrayList` contents by reading from the stream until `delimiter` is found.
98/// Does not include the delimiter in the result.
99/// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the
100/// `std.ArrayList` is populated with `max_size` bytes from the stream.
101pub fn readUntilDelimiterArrayList(
102 self: Self,
103 array_list: *std.ArrayList(u8),
104 delimiter: u8,
105 max_size: usize,
106) anyerror!void {
107 array_list.shrinkRetainingCapacity(0);
108 try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size);
109}
110
111/// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead.
112/// Allocates enough memory to read until `delimiter`. If the allocated
113/// memory would be greater than `max_size`, returns `error.StreamTooLong`.
114/// Caller owns returned memory.
115/// If this function returns an error, the contents from the stream read so far are lost.
116pub fn readUntilDelimiterAlloc(
117 self: Self,
118 allocator: mem.Allocator,
119 delimiter: u8,
120 max_size: usize,
121) anyerror![]u8 {
122 var array_list = std.ArrayList(u8).init(allocator);
123 defer array_list.deinit();
124 try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size);
125 return try array_list.toOwnedSlice();
126}
127
128/// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead.
129/// Reads from the stream until specified byte is found. If the buffer is not
130/// large enough to hold the entire contents, `error.StreamTooLong` is returned.
131/// If end-of-stream is found, `error.EndOfStream` is returned.
132/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The
133/// delimiter byte is written to the output buffer but is not included
134/// in the returned slice.
135pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) anyerror![]u8 {
136 var fbs = std.io.fixedBufferStream(buf);
137 try self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len);
138 const output = fbs.getWritten();
139 buf[output.len] = delimiter; // emulating old behaviour
140 return output;
141}
142
143/// Deprecated: use `streamUntilDelimiter` with ArrayList's (or any other's) writer instead.
144/// Allocates enough memory to read until `delimiter` or end-of-stream.
145/// If the allocated memory would be greater than `max_size`, returns
146/// `error.StreamTooLong`. If end-of-stream is found, returns the rest
147/// of the stream. If this function is called again after that, returns
148/// null.
149/// Caller owns returned memory.
150/// If this function returns an error, the contents from the stream read so far are lost.
151pub fn readUntilDelimiterOrEofAlloc(
152 self: Self,
153 allocator: mem.Allocator,
154 delimiter: u8,
155 max_size: usize,
156) anyerror!?[]u8 {
157 var array_list = std.ArrayList(u8).init(allocator);
158 defer array_list.deinit();
159 self.streamUntilDelimiter(array_list.writer(), delimiter, max_size) catch |err| switch (err) {
160 error.EndOfStream => if (array_list.items.len == 0) {
161 return null;
162 },
163 else => |e| return e,
164 };
165 return try array_list.toOwnedSlice();
166}
167
168/// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead.
169/// Reads from the stream until specified byte is found. If the buffer is not
170/// large enough to hold the entire contents, `error.StreamTooLong` is returned.
171/// If end-of-stream is found, returns the rest of the stream. If this
172/// function is called again after that, returns null.
173/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The
174/// delimiter byte is written to the output buffer but is not included
175/// in the returned slice.
176pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) anyerror!?[]u8 {
177 var fbs = std.io.fixedBufferStream(buf);
178 self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len) catch |err| switch (err) {
179 error.EndOfStream => if (fbs.getWritten().len == 0) {
180 return null;
181 },
182
183 else => |e| return e,
184 };
185 const output = fbs.getWritten();
186 buf[output.len] = delimiter; // emulating old behaviour
187 return output;
188}
189
190/// Appends to the `writer` contents by reading from the stream until `delimiter` is found.
191/// Does not write the delimiter itself.
192/// If `optional_max_size` is not null and amount of written bytes exceeds `optional_max_size`,
193/// returns `error.StreamTooLong` and finishes appending.
194/// If `optional_max_size` is null, appending is unbounded.
195pub fn streamUntilDelimiter(
196 self: Self,
197 writer: anytype,
198 delimiter: u8,
199 optional_max_size: ?usize,
200) anyerror!void {
201 if (optional_max_size) |max_size| {
202 for (0..max_size) |_| {
203 const byte: u8 = try self.readByte();
204 if (byte == delimiter) return;
205 try writer.writeByte(byte);
206 }
207 return error.StreamTooLong;
208 } else {
209 while (true) {
210 const byte: u8 = try self.readByte();
211 if (byte == delimiter) return;
212 try writer.writeByte(byte);
213 }
214 // Can not throw `error.StreamTooLong` since there are no boundary.
215 }
216}
217
218/// Reads from the stream until specified byte is found, discarding all data,
219/// including the delimiter.
220/// If end-of-stream is found, this function succeeds.
221pub fn skipUntilDelimiterOrEof(self: Self, delimiter: u8) anyerror!void {
222 while (true) {
223 const byte = self.readByte() catch |err| switch (err) {
224 error.EndOfStream => return,
225 else => |e| return e,
226 };
227 if (byte == delimiter) return;
228 }
229}
230
231/// Reads 1 byte from the stream or returns `error.EndOfStream`.
232pub fn readByte(self: Self) anyerror!u8 {
233 var result: [1]u8 = undefined;
234 const amt_read = try self.read(result[0..]);
235 if (amt_read < 1) return error.EndOfStream;
236 return result[0];
237}
238
239/// Same as `readByte` except the returned byte is signed.
240pub fn readByteSigned(self: Self) anyerror!i8 {
241 return @as(i8, @bitCast(try self.readByte()));
242}
243
244/// Reads exactly `num_bytes` bytes and returns as an array.
245/// `num_bytes` must be comptime-known
246pub fn readBytesNoEof(self: Self, comptime num_bytes: usize) anyerror![num_bytes]u8 {
247 var bytes: [num_bytes]u8 = undefined;
248 try self.readNoEof(&bytes);
249 return bytes;
250}
251
252/// Reads bytes until `bounded.len` is equal to `num_bytes`,
253/// or the stream ends.
254///
255/// * it is assumed that `num_bytes` will not exceed `bounded.capacity()`
256pub fn readIntoBoundedBytes(
257 self: Self,
258 comptime num_bytes: usize,
259 bounded: *std.BoundedArray(u8, num_bytes),
260) anyerror!void {
261 while (bounded.len < num_bytes) {
262 // get at most the number of bytes free in the bounded array
263 const bytes_read = try self.read(bounded.unusedCapacitySlice());
264 if (bytes_read == 0) return;
265
266 // bytes_read will never be larger than @TypeOf(bounded.len)
267 // due to `self.read` being bounded by `bounded.unusedCapacitySlice()`
268 bounded.len += @as(@TypeOf(bounded.len), @intCast(bytes_read));
269 }
270}
271
272/// Reads at most `num_bytes` and returns as a bounded array.
273pub fn readBoundedBytes(self: Self, comptime num_bytes: usize) anyerror!std.BoundedArray(u8, num_bytes) {
274 var result = std.BoundedArray(u8, num_bytes){};
275 try self.readIntoBoundedBytes(num_bytes, &result);
276 return result;
277}
278
279pub inline fn readInt(self: Self, comptime T: type, endian: std.builtin.Endian) anyerror!T {
280 const bytes = try self.readBytesNoEof(@divExact(@typeInfo(T).int.bits, 8));
281 return mem.readInt(T, &bytes, endian);
282}
283
284pub fn readVarInt(
285 self: Self,
286 comptime ReturnType: type,
287 endian: std.builtin.Endian,
288 size: usize,
289) anyerror!ReturnType {
290 assert(size <= @sizeOf(ReturnType));
291 var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
292 const bytes = bytes_buf[0..size];
293 try self.readNoEof(bytes);
294 return mem.readVarInt(ReturnType, bytes, endian);
295}
296
297/// Optional parameters for `skipBytes`
298pub const SkipBytesOptions = struct {
299 buf_size: usize = 512,
300};
301
302// `num_bytes` is a `u64` to match `off_t`
303/// Reads `num_bytes` bytes from the stream and discards them
304pub fn skipBytes(self: Self, num_bytes: u64, comptime options: SkipBytesOptions) anyerror!void {
305 var buf: [options.buf_size]u8 = undefined;
306 var remaining = num_bytes;
307
308 while (remaining > 0) {
309 const amt = @min(remaining, options.buf_size);
310 try self.readNoEof(buf[0..amt]);
311 remaining -= amt;
312 }
313}
314
315/// Reads `slice.len` bytes from the stream and returns if they are the same as the passed slice
316pub fn isBytes(self: Self, slice: []const u8) anyerror!bool {
317 var i: usize = 0;
318 var matches = true;
319 while (i < slice.len) : (i += 1) {
320 if (slice[i] != try self.readByte()) {
321 matches = false;
322 }
323 }
324 return matches;
325}
326
327pub fn readStruct(self: Self, comptime T: type) anyerror!T {
328 // Only extern and packed structs have defined in-memory layout.
329 comptime assert(@typeInfo(T).@"struct".layout != .auto);
330 var res: [1]T = undefined;
331 try self.readNoEof(mem.sliceAsBytes(res[0..]));
332 return res[0];
333}
334
335pub fn readStructEndian(self: Self, comptime T: type, endian: std.builtin.Endian) anyerror!T {
336 var res = try self.readStruct(T);
337 if (native_endian != endian) {
338 mem.byteSwapAllFields(T, &res);
339 }
340 return res;
341}
342
343/// Reads an integer with the same size as the given enum's tag type. If the integer matches
344/// an enum tag, casts the integer to the enum tag and returns it. Otherwise, returns an `error.InvalidValue`.
345/// TODO optimization taking advantage of most fields being in order
346pub fn readEnum(self: Self, comptime Enum: type, endian: std.builtin.Endian) anyerror!Enum {
347 const E = error{
348 /// An integer was read, but it did not match any of the tags in the supplied enum.
349 InvalidValue,
350 };
351 const type_info = @typeInfo(Enum).@"enum";
352 const tag = try self.readInt(type_info.tag_type, endian);
353
354 inline for (std.meta.fields(Enum)) |field| {
355 if (tag == field.value) {
356 return @field(Enum, field.name);
357 }
358 }
359
360 return E.InvalidValue;
361}
362
363/// Reads the stream until the end, ignoring all the data.
364/// Returns the number of bytes discarded.
365pub fn discard(self: Self) anyerror!u64 {
366 var trash: [4096]u8 = undefined;
367 var index: u64 = 0;
368 while (true) {
369 const n = try self.read(&trash);
370 if (n == 0) return index;
371 index += n;
372 }
373}
374
375const std = @import("../std.zig");
376const Self = @This();
377const math = std.math;
378const assert = std.debug.assert;
379const mem = std.mem;
380const testing = std.testing;
381const native_endian = @import("builtin").target.cpu.arch.endian();
382const Alignment = std.mem.Alignment;
383
384test {
385 _ = @import("Reader/test.zig");
386}
lib/std/io/DeprecatedWriter.zig created+109
...@@ -0,0 +1,109 @@
1const std = @import("../std.zig");
2const assert = std.debug.assert;
3const mem = std.mem;
4const native_endian = @import("builtin").target.cpu.arch.endian();
5
6context: *const anyopaque,
7writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize,
8
9const Self = @This();
10pub const Error = anyerror;
11
12pub fn write(self: Self, bytes: []const u8) anyerror!usize {
13 return self.writeFn(self.context, bytes);
14}
15
16pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {
17 var index: usize = 0;
18 while (index != bytes.len) {
19 index += try self.write(bytes[index..]);
20 }
21}
22
23pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {
24 return std.fmt.format(self, format, args);
25}
26
27pub fn writeByte(self: Self, byte: u8) anyerror!void {
28 const array = [1]u8{byte};
29 return self.writeAll(&array);
30}
31
32pub fn writeByteNTimes(self: Self, byte: u8, n: usize) anyerror!void {
33 var bytes: [256]u8 = undefined;
34 @memset(bytes[0..], byte);
35
36 var remaining: usize = n;
37 while (remaining > 0) {
38 const to_write = @min(remaining, bytes.len);
39 try self.writeAll(bytes[0..to_write]);
40 remaining -= to_write;
41 }
42}
43
44pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) anyerror!void {
45 var i: usize = 0;
46 while (i < n) : (i += 1) {
47 try self.writeAll(bytes);
48 }
49}
50
51pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) anyerror!void {
52 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
53 mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
54 return self.writeAll(&bytes);
55}
56
57pub fn writeStruct(self: Self, value: anytype) anyerror!void {
58 // Only extern and packed structs have defined in-memory layout.
59 comptime assert(@typeInfo(@TypeOf(value)).@"struct".layout != .auto);
60 return self.writeAll(mem.asBytes(&value));
61}
62
63pub fn writeStructEndian(self: Self, value: anytype, endian: std.builtin.Endian) anyerror!void {
64 // TODO: make sure this value is not a reference type
65 if (native_endian == endian) {
66 return self.writeStruct(value);
67 } else {
68 var copy = value;
69 mem.byteSwapAllFields(@TypeOf(value), &copy);
70 return self.writeStruct(copy);
71 }
72}
73
74pub fn writeFile(self: Self, file: std.fs.File) anyerror!void {
75 // TODO: figure out how to adjust std lib abstractions so that this ends up
76 // doing sendfile or maybe even copy_file_range under the right conditions.
77 var buf: [4000]u8 = undefined;
78 while (true) {
79 const n = try file.readAll(&buf);
80 try self.writeAll(buf[0..n]);
81 if (n < buf.len) return;
82 }
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+1660-315
...@@ -1,386 +1,1731 @@...@@ -1,386 +1,1731 @@
1context: *const anyopaque,1const Reader = @This();
2readFn: *const fn (context: *const anyopaque, buffer: []u8) anyerror!usize,
32
4pub const Error = anyerror;3const builtin = @import("builtin");
4const native_endian = builtin.target.cpu.arch.endian();
55
6/// Returns the number of bytes read. It may be less than buffer.len.6const std = @import("../std.zig");
7/// If the number of bytes read is 0, it means end of stream.7const Writer = std.io.Writer;
8/// End of stream is not an error condition.8const assert = std.debug.assert;
9pub fn read(self: Self, buffer: []u8) anyerror!usize {9const testing = std.testing;
10 return self.readFn(self.context, buffer);10const Allocator = std.mem.Allocator;
11const ArrayList = std.ArrayListUnmanaged;
12const Limit = std.io.Limit;
13
14pub const Limited = @import("Reader/Limited.zig");
15
16vtable: *const VTable,
17buffer: []u8,
18/// Number of bytes which have been consumed from `buffer`.
19seek: usize,
20/// In `buffer` before this are buffered bytes, after this is `undefined`.
21end: usize,
22
23pub const VTable = struct {
24 /// Writes bytes from the internally tracked logical position to `w`.
25 ///
26 /// Returns the number of bytes written, which will be at minimum `0` and
27 /// 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 the
29 /// buffer capacity of `w`, a value whose minimum size is determined by the
30 /// stream implementation.
31 ///
32 /// The reader's internal logical seek position moves forward in accordance
33 /// with the number of bytes returned from this function.
34 ///
35 /// Implementations are encouraged to utilize mandatory minimum buffer
36 /// sizes combined with short reads (returning a value less than `limit`)
37 /// in order to minimize complexity.
38 ///
39 /// Although this function is usually called when `buffer` is empty, it is
40 /// also called when it needs to be filled more due to the API user
41 /// requesting contiguous memory. In either case, the existing buffer data
42 /// should be ignored; new data written to `w`.
43 ///
44 /// In addition to, or instead of writing to `w`, the implementation may
45 /// choose to store data in `buffer`, modifying `seek` and `end`
46 /// accordingly. Stream implementations are encouraged to take advantage of
47 /// this if simplifies the logic.
48 stream: *const fn (r: *Reader, w: *Writer, limit: Limit) StreamError!usize,
49
50 /// Consumes bytes from the internally tracked stream position without
51 /// providing access to them.
52 ///
53 /// Returns the number of bytes discarded, which will be at minimum `0` and
54 /// at most `limit`. The number of bytes returned, including zero, does not
55 /// indicate end of stream.
56 ///
57 /// The reader's internal logical seek position moves forward in accordance
58 /// with the number of bytes returned from this function.
59 ///
60 /// Implementations are encouraged to utilize mandatory minimum buffer
61 /// sizes combined with short reads (returning a value less than `limit`)
62 /// in order to minimize complexity.
63 ///
64 /// The default implementation is is based on calling `stream`, borrowing
65 /// `buffer` to construct a temporary `Writer` and ignoring the written
66 /// data.
67 ///
68 /// This function is only called when `buffer` is empty.
69 discard: *const fn (r: *Reader, limit: Limit) Error!usize = defaultDiscard,
70};
71
72pub const StreamError = error{
73 /// See the `Reader` implementation for detailed diagnostics.
74 ReadFailed,
75 /// See the `Writer` implementation for detailed diagnostics.
76 WriteFailed,
77 /// End of stream indicated from the `Reader`. This error cannot originate
78 /// from the `Writer`.
79 EndOfStream,
80};
81
82pub const Error = error{
83 /// See the `Reader` implementation for detailed diagnostics.
84 ReadFailed,
85 EndOfStream,
86};
87
88pub const StreamRemainingError = error{
89 /// See the `Reader` implementation for detailed diagnostics.
90 ReadFailed,
91 /// See the `Writer` implementation for detailed diagnostics.
92 WriteFailed,
93};
94
95pub const ShortError = error{
96 /// See the `Reader` implementation for detailed diagnostics.
97 ReadFailed,
98};
99
100pub const failing: Reader = .{
101 .vtable = &.{
102 .read = failingStream,
103 .discard = failingDiscard,
104 },
105 .buffer = &.{},
106 .seek = 0,
107 .end = 0,
108};
109
110/// This is generally safe to `@constCast` because it has an empty buffer, so
111/// there is not really a way to accidentally attempt mutation of these fields.
112const ending_state: Reader = .fixed(&.{});
113pub const ending: *Reader = @constCast(&ending_state);
114
115pub fn limited(r: *Reader, limit: Limit, buffer: []u8) Limited {
116 return .init(r, limit, buffer);
11}117}
12118
13/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it119/// Constructs a `Reader` such that it will read from `buffer` and then end.
14/// means the stream reached the end. Reaching the end of a stream is not an error120pub fn fixed(buffer: []const u8) Reader {
15/// condition.121 return .{
16pub fn readAll(self: Self, buffer: []u8) anyerror!usize {122 .vtable = &.{
17 return readAtLeast(self, buffer, buffer.len);123 .stream = endingStream,
124 .discard = endingDiscard,
125 },
126 // This cast is safe because all potential writes to it will instead
127 // return `error.EndOfStream`.
128 .buffer = @constCast(buffer),
129 .end = buffer.len,
130 .seek = 0,
131 };
18}132}
19133
20/// Returns the number of bytes read, calling the underlying read134pub fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
21/// function the minimal number of times until the buffer has at least135 const buffer = limit.slice(r.buffer[r.seek..r.end]);
22/// `len` bytes filled. If the number read is less than `len` it means136 if (buffer.len > 0) {
23/// the stream reached the end. Reaching the end of the stream is not137 @branchHint(.likely);
24/// an error condition.138 const n = try w.write(buffer);
25pub fn readAtLeast(self: Self, buffer: []u8, len: usize) anyerror!usize {139 r.seek += n;
26 assert(len <= buffer.len);140 return n;
27 var index: usize = 0;141 }
28 while (index < len) {142 const n = try r.vtable.stream(r, w, limit);
29 const amt = try self.read(buffer[index..]);143 assert(n <= @intFromEnum(limit));
30 if (amt == 0) break;144 return n;
31 index += amt;145}
146
147pub fn discard(r: *Reader, limit: Limit) Error!usize {
148 const buffered_len = r.end - r.seek;
149 const remaining: Limit = if (limit.toInt()) |n| l: {
150 if (buffered_len >= n) {
151 r.seek += n;
152 return n;
153 }
154 break :l .limited(n - buffered_len);
155 } else .unlimited;
156 r.seek = 0;
157 r.end = 0;
158 const n = try r.vtable.discard(r, remaining);
159 assert(n <= @intFromEnum(remaining));
160 return buffered_len + n;
161}
162
163pub fn defaultDiscard(r: *Reader, limit: Limit) Error!usize {
164 assert(r.seek == 0);
165 assert(r.end == 0);
166 var dw: Writer.Discarding = .init(r.buffer);
167 const n = r.stream(&dw.writer, limit) catch |err| switch (err) {
168 error.WriteFailed => unreachable,
169 error.ReadFailed => return error.ReadFailed,
170 error.EndOfStream => return error.EndOfStream,
171 };
172 assert(n <= @intFromEnum(limit));
173 return n;
174}
175
176/// "Pump" exactly `n` bytes from the reader to the writer.
177pub fn streamExact(r: *Reader, w: *Writer, n: usize) StreamError!void {
178 var remaining = n;
179 while (remaining != 0) remaining -= try r.stream(w, .limited(remaining));
180}
181
182/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as
183/// a success case.
184///
185/// Returns total number of bytes written to `w`.
186pub fn streamRemaining(r: *Reader, w: *Writer) StreamRemainingError!usize {
187 var offset: usize = 0;
188 while (true) {
189 offset += r.stream(w, .unlimited) catch |err| switch (err) {
190 error.EndOfStream => return offset,
191 else => |e| return e,
192 };
32 }193 }
33 return index;194}
34}195
35196/// Consumes the stream until the end, ignoring all the data, returning the
36/// If the number read would be smaller than `buf.len`, `error.EndOfStream` is returned instead.197/// number of bytes discarded.
37pub fn readNoEof(self: Self, buf: []u8) anyerror!void {198pub fn discardRemaining(r: *Reader) ShortError!usize {
38 const amt_read = try self.readAll(buf);199 var offset: usize = r.end - r.seek;
39 if (amt_read < buf.len) return error.EndOfStream;200 r.seek = 0;
40}201 r.end = 0;
41
42/// Appends to the `std.ArrayList` contents by reading from the stream
43/// until end of stream is found.
44/// If the number of bytes appended would exceed `max_append_size`,
45/// `error.StreamTooLong` is returned
46/// and the `std.ArrayList` has exactly `max_append_size` bytes appended.
47pub fn readAllArrayList(
48 self: Self,
49 array_list: *std.ArrayList(u8),
50 max_append_size: usize,
51) anyerror!void {
52 return self.readAllArrayListAligned(null, array_list, max_append_size);
53}
54
55pub fn readAllArrayListAligned(
56 self: Self,
57 comptime alignment: ?Alignment,
58 array_list: *std.ArrayListAligned(u8, alignment),
59 max_append_size: usize,
60) anyerror!void {
61 try array_list.ensureTotalCapacity(@min(max_append_size, 4096));
62 const original_len = array_list.items.len;
63 var start_index: usize = original_len;
64 while (true) {202 while (true) {
65 array_list.expandToCapacity();203 offset += r.vtable.discard(r, .unlimited) catch |err| switch (err) {
66 const dest_slice = array_list.items[start_index..];204 error.EndOfStream => return offset,
67 const bytes_read = try self.readAll(dest_slice);205 else => |e| return e,
68 start_index += bytes_read;206 };
207 }
208}
209
210pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLong};
69211
70 if (start_index - original_len > max_append_size) {212/// Transfers all bytes from the current position to the end of the stream, up
71 array_list.shrinkAndFree(original_len + max_append_size);213/// to `limit`, returning them as a caller-owned allocated slice.
214///
215/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
216/// such case, the next byte that would be read will be the first one to exceed
217/// `limit`, and all preceeding bytes have been discarded.
218///
219/// Asserts `buffer` has nonzero capacity.
220///
221/// See also:
222/// * `appendRemaining`
223pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 {
224 var buffer: ArrayList(u8) = .empty;
225 defer buffer.deinit(gpa);
226 try appendRemaining(r, gpa, null, &buffer, limit);
227 return buffer.toOwnedSlice(gpa);
228}
229
230/// Transfers all bytes from the current position to the end of the stream, up
231/// to `limit`, appending them to `list`.
232///
233/// If `limit` would be exceeded, `error.StreamTooLong` is returned instead. In
234/// such case, the next byte that would be read will be the first one to exceed
235/// `limit`, and all preceeding bytes have been appended to `list`.
236///
237/// Asserts `buffer` has nonzero capacity.
238///
239/// See also:
240/// * `allocRemaining`
241pub fn appendRemaining(
242 r: *Reader,
243 gpa: Allocator,
244 comptime alignment: ?std.mem.Alignment,
245 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
246 limit: Limit,
247) LimitedAllocError!void {
248 const buffer = r.buffer;
249 const buffer_contents = buffer[r.seek..r.end];
250 const copy_len = limit.minInt(buffer_contents.len);
251 try list.ensureUnusedCapacity(gpa, copy_len);
252 @memcpy(list.unusedCapacitySlice()[0..copy_len], buffer[0..copy_len]);
253 list.items.len += copy_len;
254 r.seek += copy_len;
255 if (copy_len == buffer_contents.len) {
256 r.seek = 0;
257 r.end = 0;
258 }
259 var remaining = limit.subtract(copy_len).?;
260 while (true) {
261 try list.ensureUnusedCapacity(gpa, 1);
262 const dest = remaining.slice(list.unusedCapacitySlice());
263 const additional_buffer: []u8 = if (@intFromEnum(remaining) == dest.len) buffer else &.{};
264 const n = readVec(r, &.{ dest, additional_buffer }) catch |err| switch (err) {
265 error.EndOfStream => break,
266 error.ReadFailed => return error.ReadFailed,
267 };
268 if (n > dest.len) {
269 r.end = n - dest.len;
270 list.items.len += dest.len;
72 return error.StreamTooLong;271 return error.StreamTooLong;
73 }272 }
273 list.items.len += n;
274 remaining = remaining.subtract(n).?;
275 }
276}
277
278/// Writes bytes from the internally tracked stream position to `data`.
279///
280/// Returns the number of bytes written, which will be at minimum `0` and
281/// at most the sum of each data slice length. The number of bytes read,
282/// including zero, does not indicate end of stream.
283///
284/// The reader's internal logical seek position moves forward in accordance
285/// with the number of bytes returned from this function.
286pub fn readVec(r: *Reader, data: []const []u8) Error!usize {
287 return readVecLimit(r, data, .unlimited);
288}
289
290/// Equivalent to `readVec` but reads at most `limit` bytes.
291///
292/// This ultimately will lower to a call to `stream`, but it must ensure
293/// that the buffer used has at least as much capacity, in case that function
294/// depends on a minimum buffer capacity. It also ensures that if the `stream`
295/// implementation calls `Writer.writableVector`, it will get this data slice
296/// along with the buffer at the end.
297pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {
298 comptime assert(@intFromEnum(Limit.unlimited) == std.math.maxInt(usize));
299 var remaining = @intFromEnum(limit);
300 for (data, 0..) |buf, i| {
301 const buffer_contents = r.buffer[r.seek..r.end];
302 const copy_len = @min(buffer_contents.len, buf.len, remaining);
303 @memcpy(buf[0..copy_len], buffer_contents[0..copy_len]);
304 r.seek += copy_len;
305 remaining -= copy_len;
306 if (remaining == 0) break;
307 if (buf.len - copy_len == 0) continue;
74308
75 if (bytes_read != dest_slice.len) {309 // All of `buffer` has been copied to `data`. We now set up a structure
76 array_list.shrinkAndFree(start_index);310 // that enables the `Writer.writableVector` API, while also ensuring
77 return;311 // API that directly operates on the `Writable.buffer` has its minimum
312 // buffer capacity requirements met.
313 r.seek = 0;
314 r.end = 0;
315 const first = buf[copy_len..];
316 const middle = data[i + 1 ..];
317 var wrapper: Writer.VectorWrapper = .{
318 .it = .{
319 .first = first,
320 .middle = middle,
321 .last = r.buffer,
322 },
323 .writer = .{
324 .buffer = if (first.len >= r.buffer.len) first else r.buffer,
325 .vtable = Writer.VectorWrapper.vtable,
326 },
327 };
328 var n = r.vtable.stream(r, &wrapper.writer, .limited(remaining)) catch |err| switch (err) {
329 error.WriteFailed => {
330 assert(!wrapper.used);
331 if (wrapper.writer.buffer.ptr == first.ptr) {
332 remaining -= wrapper.writer.end;
333 } else {
334 assert(wrapper.writer.end <= r.buffer.len);
335 r.end = wrapper.writer.end;
336 }
337 break;
338 },
339 else => |e| return e,
340 };
341 if (!wrapper.used) {
342 if (wrapper.writer.buffer.ptr == first.ptr) {
343 remaining -= n;
344 } else {
345 assert(n <= r.buffer.len);
346 r.end = n;
347 }
348 break;
349 }
350 if (n < first.len) {
351 remaining -= n;
352 break;
78 }353 }
354 remaining -= first.len;
355 n -= first.len;
356 for (middle) |mid| {
357 if (n < mid.len) {
358 remaining -= n;
359 break;
360 }
361 remaining -= mid.len;
362 n -= mid.len;
363 }
364 assert(n <= r.buffer.len);
365 r.end = n;
366 break;
367 }
368 return @intFromEnum(limit) - remaining;
369}
370
371pub fn buffered(r: *Reader) []u8 {
372 return r.buffer[r.seek..r.end];
373}
374
375pub fn bufferedLen(r: *const Reader) usize {
376 return r.end - r.seek;
377}
79378
80 // This will trigger ArrayList to expand superlinearly at whatever its growth rate is.379pub fn hashed(r: *Reader, hasher: anytype) Hashed(@TypeOf(hasher)) {
81 try array_list.ensureTotalCapacity(start_index + 1);380 return .{ .in = r, .hasher = hasher };
381}
382
383pub fn readVecAll(r: *Reader, data: [][]u8) Error!void {
384 var index: usize = 0;
385 var truncate: usize = 0;
386 while (index < data.len) {
387 {
388 const untruncated = data[index];
389 data[index] = untruncated[truncate..];
390 defer data[index] = untruncated;
391 truncate += try r.readVec(data[index..]);
392 }
393 while (index < data.len and truncate >= data[index].len) {
394 truncate -= data[index].len;
395 index += 1;
396 }
82 }397 }
83}398}
84399
85/// Allocates enough memory to hold all the contents of the stream. If the allocated400/// Returns the next `len` bytes from the stream, filling the buffer as
86/// memory would be greater than `max_size`, returns `error.StreamTooLong`.401/// necessary.
87/// Caller owns returned memory.402///
88/// If this function returns an error, the contents from the stream read so far are lost.403/// Invalidates previously returned values from `peek`.
89pub fn readAllAlloc(self: Self, allocator: mem.Allocator, max_size: usize) anyerror![]u8 {404///
90 var array_list = std.ArrayList(u8).init(allocator);405/// Asserts that the `Reader` was initialized with a buffer capacity at
91 defer array_list.deinit();406/// least as big as `len`.
92 try self.readAllArrayList(&array_list, max_size);407///
93 return try array_list.toOwnedSlice();408/// If there are fewer than `len` bytes left in the stream, `error.EndOfStream`
94}409/// is returned instead.
95410///
96/// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead.411/// See also:
97/// Replaces the `std.ArrayList` contents by reading from the stream until `delimiter` is found.412/// * `peek`
98/// Does not include the delimiter in the result.413/// * `toss`
99/// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the414pub fn peek(r: *Reader, n: usize) Error![]u8 {
100/// `std.ArrayList` is populated with `max_size` bytes from the stream.415 try r.fill(n);
101pub fn readUntilDelimiterArrayList(416 return r.buffer[r.seek..][0..n];
102 self: Self,417}
103 array_list: *std.ArrayList(u8),418
104 delimiter: u8,419/// Returns all the next buffered bytes, after filling the buffer to ensure it
105 max_size: usize,420/// contains at least `n` bytes.
106) anyerror!void {421///
107 array_list.shrinkRetainingCapacity(0);422/// Invalidates previously returned values from `peek` and `peekGreedy`.
108 try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size);423///
109}424/// Asserts that the `Reader` was initialized with a buffer capacity at
110425/// least as big as `n`.
111/// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead.426///
112/// Allocates enough memory to read until `delimiter`. If the allocated427/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
113/// memory would be greater than `max_size`, returns `error.StreamTooLong`.428/// is returned instead.
114/// Caller owns returned memory.429///
115/// If this function returns an error, the contents from the stream read so far are lost.430/// See also:
116pub fn readUntilDelimiterAlloc(431/// * `peek`
117 self: Self,432/// * `toss`
118 allocator: mem.Allocator,433pub fn peekGreedy(r: *Reader, n: usize) Error![]u8 {
119 delimiter: u8,434 try r.fill(n);
120 max_size: usize,435 return r.buffer[r.seek..r.end];
121) anyerror![]u8 {436}
122 var array_list = std.ArrayList(u8).init(allocator);437
123 defer array_list.deinit();438/// Skips the next `n` bytes from the stream, advancing the seek position. This
124 try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size);439/// is typically and safely used after `peek`.
125 return try array_list.toOwnedSlice();440///
126}441/// Asserts that the number of bytes buffered is at least as many as `n`.
127442///
128/// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead.443/// The "tossed" memory remains alive until a "peek" operation occurs.
129/// Reads from the stream until specified byte is found. If the buffer is not444///
130/// large enough to hold the entire contents, `error.StreamTooLong` is returned.445/// See also:
131/// If end-of-stream is found, `error.EndOfStream` is returned.446/// * `peek`.
132/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The447/// * `discard`.
133/// delimiter byte is written to the output buffer but is not included448pub fn toss(r: *Reader, n: usize) void {
134/// in the returned slice.449 r.seek += n;
135pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) anyerror![]u8 {450 assert(r.seek <= r.end);
136 var fbs = std.io.fixedBufferStream(buf);451}
137 try self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len);452
138 const output = fbs.getWritten();453/// Equivalent to `toss(r.bufferedLen())`.
139 buf[output.len] = delimiter; // emulating old behaviour454pub fn tossBuffered(r: *Reader) void {
140 return output;455 r.seek = 0;
141}456 r.end = 0;
142457}
143/// Deprecated: use `streamUntilDelimiter` with ArrayList's (or any other's) writer instead.458
144/// Allocates enough memory to read until `delimiter` or end-of-stream.459/// Equivalent to `peek` followed by `toss`.
145/// If the allocated memory would be greater than `max_size`, returns460///
146/// `error.StreamTooLong`. If end-of-stream is found, returns the rest461/// The data returned is invalidated by the next call to `take`, `peek`,
147/// of the stream. If this function is called again after that, returns462/// `fill`, and functions with those prefixes.
148/// null.463pub fn take(r: *Reader, n: usize) Error![]u8 {
149/// Caller owns returned memory.464 const result = try r.peek(n);
150/// If this function returns an error, the contents from the stream read so far are lost.465 r.toss(n);
151pub fn readUntilDelimiterOrEofAlloc(466 return result;
152 self: Self,467}
153 allocator: mem.Allocator,468
154 delimiter: u8,469/// Returns the next `n` bytes from the stream as an array, filling the buffer
155 max_size: usize,470/// as necessary and advancing the seek position `n` bytes.
156) anyerror!?[]u8 {471///
157 var array_list = std.ArrayList(u8).init(allocator);472/// Asserts that the `Reader` was initialized with a buffer capacity at
158 defer array_list.deinit();473/// least as big as `n`.
159 self.streamUntilDelimiter(array_list.writer(), delimiter, max_size) catch |err| switch (err) {474///
160 error.EndOfStream => if (array_list.items.len == 0) {475/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
161 return null;476/// is returned instead.
477///
478/// See also:
479/// * `take`
480pub fn takeArray(r: *Reader, comptime n: usize) Error!*[n]u8 {
481 return (try r.take(n))[0..n];
482}
483
484/// Returns the next `n` bytes from the stream as an array, filling the buffer
485/// as necessary, without advancing the seek position.
486///
487/// Asserts that the `Reader` was initialized with a buffer capacity at
488/// least as big as `n`.
489///
490/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`
491/// is returned instead.
492///
493/// See also:
494/// * `peek`
495/// * `takeArray`
496pub fn peekArray(r: *Reader, comptime n: usize) Error!*[n]u8 {
497 return (try r.peek(n))[0..n];
498}
499
500/// Skips the next `n` bytes from the stream, advancing the seek position.
501///
502/// Unlike `toss` which is infallible, in this function `n` can be any amount.
503///
504/// Returns `error.EndOfStream` if fewer than `n` bytes could be discarded.
505///
506/// See also:
507/// * `toss`
508/// * `discardRemaining`
509/// * `discardShort`
510/// * `discard`
511pub fn discardAll(r: *Reader, n: usize) Error!void {
512 if ((try r.discardShort(n)) != n) return error.EndOfStream;
513}
514
515pub fn discardAll64(r: *Reader, n: u64) Error!void {
516 var remaining: u64 = n;
517 while (remaining > 0) {
518 const limited_remaining = std.math.cast(usize, remaining) orelse std.math.maxInt(usize);
519 try discardAll(r, limited_remaining);
520 remaining -= limited_remaining;
521 }
522}
523
524/// Skips the next `n` bytes from the stream, advancing the seek position.
525///
526/// Unlike `toss` which is infallible, in this function `n` can be any amount.
527///
528/// Returns the number of bytes discarded, which is less than `n` if and only
529/// if the stream reached the end.
530///
531/// See also:
532/// * `discardAll`
533/// * `discardRemaining`
534/// * `discard`
535pub fn discardShort(r: *Reader, n: usize) ShortError!usize {
536 const proposed_seek = r.seek + n;
537 if (proposed_seek <= r.end) {
538 @branchHint(.likely);
539 r.seek = proposed_seek;
540 return n;
541 }
542 var remaining = n - (r.end - r.seek);
543 r.end = 0;
544 r.seek = 0;
545 while (true) {
546 const discard_len = r.vtable.discard(r, .limited(remaining)) catch |err| switch (err) {
547 error.EndOfStream => return n - remaining,
548 error.ReadFailed => return error.ReadFailed,
549 };
550 remaining -= discard_len;
551 if (remaining == 0) return n;
552 }
553}
554
555/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
556/// the seek position.
557///
558/// Invalidates previously returned values from `peek`.
559///
560/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
561/// returned instead.
562///
563/// See also:
564/// * `peek`
565/// * `readSliceShort`
566pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void {
567 const n = try readSliceShort(r, buffer);
568 if (n != buffer.len) return error.EndOfStream;
569}
570
571/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
572/// the seek position.
573///
574/// Invalidates previously returned values from `peek`.
575///
576/// Returns the number of bytes read, which is less than `buffer.len` if and
577/// only if the stream reached the end.
578///
579/// See also:
580/// * `readSliceAll`
581pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize {
582 const in_buffer = r.buffer[r.seek..r.end];
583 const copy_len = @min(buffer.len, in_buffer.len);
584 @memcpy(buffer[0..copy_len], in_buffer[0..copy_len]);
585 if (buffer.len - copy_len == 0) {
586 r.seek += copy_len;
587 return buffer.len;
588 }
589 var i: usize = copy_len;
590 r.end = 0;
591 r.seek = 0;
592 while (true) {
593 const remaining = buffer[i..];
594 var wrapper: Writer.VectorWrapper = .{
595 .it = .{
596 .first = remaining,
597 .last = r.buffer,
598 },
599 .writer = .{
600 .buffer = if (remaining.len >= r.buffer.len) remaining else r.buffer,
601 .vtable = Writer.VectorWrapper.vtable,
602 },
603 };
604 const n = r.vtable.stream(r, &wrapper.writer, .unlimited) catch |err| switch (err) {
605 error.WriteFailed => {
606 if (!wrapper.used) {
607 assert(r.seek == 0);
608 r.seek = remaining.len;
609 r.end = wrapper.writer.end;
610 @memcpy(remaining, r.buffer[0..remaining.len]);
611 }
612 return buffer.len;
613 },
614 error.EndOfStream => return i,
615 error.ReadFailed => return error.ReadFailed,
616 };
617 if (n < remaining.len) {
618 i += n;
619 continue;
620 }
621 r.end = n - remaining.len;
622 return buffer.len;
623 }
624}
625
626/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
627/// the seek position.
628///
629/// Invalidates previously returned values from `peek`.
630///
631/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
632/// returned instead.
633///
634/// The function is inline to avoid the dead code in case `endian` is
635/// comptime-known and matches host endianness.
636///
637/// See also:
638/// * `readSliceAll`
639/// * `readSliceEndianAlloc`
640pub inline fn readSliceEndian(
641 r: *Reader,
642 comptime Elem: type,
643 buffer: []Elem,
644 endian: std.builtin.Endian,
645) Error!void {
646 try readSliceAll(r, @ptrCast(buffer));
647 if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem);
648}
649
650pub const ReadAllocError = Error || Allocator.Error;
651
652/// The function is inline to avoid the dead code in case `endian` is
653/// comptime-known and matches host endianness.
654pub inline fn readSliceEndianAlloc(
655 r: *Reader,
656 allocator: Allocator,
657 comptime Elem: type,
658 len: usize,
659 endian: std.builtin.Endian,
660) ReadAllocError![]Elem {
661 const dest = try allocator.alloc(Elem, len);
662 errdefer allocator.free(dest);
663 try readSliceAll(r, @ptrCast(dest));
664 if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem);
665 return dest;
666}
667
668/// Shortcut for calling `readSliceAll` with a buffer provided by `allocator`.
669pub fn readAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
670 const dest = try allocator.alloc(u8, len);
671 errdefer allocator.free(dest);
672 try readSliceAll(r, dest);
673 return dest;
674}
675
676pub const DelimiterError = error{
677 /// See the `Reader` implementation for detailed diagnostics.
678 ReadFailed,
679 /// For "inclusive" functions, stream ended before the delimiter was found.
680 /// For "exclusive" functions, stream ended and there are no more bytes to
681 /// return.
682 EndOfStream,
683 /// The delimiter was not found within a number of bytes matching the
684 /// capacity of the `Reader`.
685 StreamTooLong,
686};
687
688/// Returns a slice of the next bytes of buffered data from the stream until
689/// `sentinel` is found, advancing the seek position.
690///
691/// Returned slice has a sentinel.
692///
693/// Invalidates previously returned values from `peek`.
694///
695/// See also:
696/// * `peekSentinel`
697/// * `takeDelimiterExclusive`
698/// * `takeDelimiterInclusive`
699pub fn takeSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
700 const result = try r.peekSentinel(sentinel);
701 r.toss(result.len + 1);
702 return result;
703}
704
705/// Returns a slice of the next bytes of buffered data from the stream until
706/// `sentinel` is found, without advancing the seek position.
707///
708/// Returned slice has a sentinel; end of stream does not count as a delimiter.
709///
710/// Invalidates previously returned values from `peek`.
711///
712/// See also:
713/// * `takeSentinel`
714/// * `peekDelimiterExclusive`
715/// * `peekDelimiterInclusive`
716pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
717 const result = try r.peekDelimiterInclusive(sentinel);
718 return result[0 .. result.len - 1 :sentinel];
719}
720
721/// Returns a slice of the next bytes of buffered data from the stream until
722/// `delimiter` is found, advancing the seek position.
723///
724/// Returned slice includes the delimiter as the last byte.
725///
726/// Invalidates previously returned values from `peek`.
727///
728/// See also:
729/// * `takeSentinel`
730/// * `takeDelimiterExclusive`
731/// * `peekDelimiterInclusive`
732pub fn takeDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
733 const result = try r.peekDelimiterInclusive(delimiter);
734 r.toss(result.len);
735 return result;
736}
737
738/// Returns a slice of the next bytes of buffered data from the stream until
739/// `delimiter` is found, without advancing the seek position.
740///
741/// Returned slice includes the delimiter as the last byte.
742///
743/// Invalidates previously returned values from `peek`.
744///
745/// See also:
746/// * `peekSentinel`
747/// * `peekDelimiterExclusive`
748/// * `takeDelimiterInclusive`
749pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
750 const buffer = r.buffer[0..r.end];
751 const seek = r.seek;
752 if (std.mem.indexOfScalarPos(u8, buffer, seek, delimiter)) |end| {
753 @branchHint(.likely);
754 return buffer[seek .. end + 1];
755 }
756 if (r.vtable.stream == &endingStream) {
757 // Protect the `@constCast` of `fixed`.
758 return error.EndOfStream;
759 }
760 r.rebase();
761 while (r.buffer.len - r.end != 0) {
762 const end_cap = r.buffer[r.end..];
763 var writer: Writer = .fixed(end_cap);
764 const n = r.vtable.stream(r, &writer, .limited(end_cap.len)) catch |err| switch (err) {
765 error.WriteFailed => unreachable,
766 else => |e| return e,
767 };
768 r.end += n;
769 if (std.mem.indexOfScalarPos(u8, end_cap[0..n], 0, delimiter)) |end| {
770 return r.buffer[0 .. r.end - n + end + 1];
771 }
772 }
773 return error.StreamTooLong;
774}
775
776/// Returns a slice of the next bytes of buffered data from the stream until
777/// `delimiter` is found, advancing the seek position.
778///
779/// Returned slice excludes the delimiter. End-of-stream is treated equivalent
780/// to a delimiter, unless it would result in a length 0 return value, in which
781/// case `error.EndOfStream` is returned instead.
782///
783/// If the delimiter is not found within a number of bytes matching the
784/// capacity of this `Reader`, `error.StreamTooLong` is returned. In
785/// such case, the stream state is unmodified as if this function was never
786/// called.
787///
788/// Invalidates previously returned values from `peek`.
789///
790/// See also:
791/// * `takeDelimiterInclusive`
792/// * `peekDelimiterExclusive`
793pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
794 const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
795 error.EndOfStream => {
796 const remaining = r.buffer[r.seek..r.end];
797 if (remaining.len == 0) return error.EndOfStream;
798 r.toss(remaining.len);
799 return remaining;
162 },800 },
163 else => |e| return e,801 else => |e| return e,
164 };802 };
165 return try array_list.toOwnedSlice();803 r.toss(result.len);
166}804 return result[0 .. result.len - 1];
167805}
168/// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead.806
169/// Reads from the stream until specified byte is found. If the buffer is not807/// Returns a slice of the next bytes of buffered data from the stream until
170/// large enough to hold the entire contents, `error.StreamTooLong` is returned.808/// `delimiter` is found, without advancing the seek position.
171/// If end-of-stream is found, returns the rest of the stream. If this809///
172/// function is called again after that, returns null.810/// Returned slice excludes the delimiter. End-of-stream is treated equivalent
173/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The811/// to a delimiter, unless it would result in a length 0 return value, in which
174/// delimiter byte is written to the output buffer but is not included812/// case `error.EndOfStream` is returned instead.
175/// in the returned slice.813///
176pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) anyerror!?[]u8 {814/// If the delimiter is not found within a number of bytes matching the
177 var fbs = std.io.fixedBufferStream(buf);815/// capacity of this `Reader`, `error.StreamTooLong` is returned. In
178 self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len) catch |err| switch (err) {816/// such case, the stream state is unmodified as if this function was never
179 error.EndOfStream => if (fbs.getWritten().len == 0) {817/// called.
180 return null;818///
819/// Invalidates previously returned values from `peek`.
820///
821/// See also:
822/// * `peekDelimiterInclusive`
823/// * `takeDelimiterExclusive`
824pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
825 const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
826 error.EndOfStream => {
827 const remaining = r.buffer[r.seek..r.end];
828 if (remaining.len == 0) return error.EndOfStream;
829 r.toss(remaining.len);
830 return remaining;
181 },831 },
832 else => |e| return e,
833 };
834 return result[0 .. result.len - 1];
835}
182836
837/// Appends to `w` contents by reading from the stream until `delimiter` is
838/// found. Does not write the delimiter itself.
839///
840/// Returns number of bytes streamed, which may be zero, or error.EndOfStream
841/// if the delimiter was not found.
842///
843/// See also:
844/// * `streamDelimiterEnding`
845/// * `streamDelimiterLimit`
846pub fn streamDelimiter(r: *Reader, w: *Writer, delimiter: u8) StreamError!usize {
847 const n = streamDelimiterLimit(r, w, delimiter, .unlimited) catch |err| switch (err) {
848 error.StreamTooLong => unreachable, // unlimited is passed
183 else => |e| return e,849 else => |e| return e,
184 };850 };
185 const output = fbs.getWritten();851 if (r.seek == r.end) return error.EndOfStream;
186 buf[output.len] = delimiter; // emulating old behaviour852 return n;
187 return output;
188}853}
189854
190/// Appends to the `writer` contents by reading from the stream until `delimiter` is found.855/// Appends to `w` contents by reading from the stream until `delimiter` is found.
191/// Does not write the delimiter itself.856/// Does not write the delimiter itself.
192/// If `optional_max_size` is not null and amount of written bytes exceeds `optional_max_size`,857///
193/// returns `error.StreamTooLong` and finishes appending.858/// Returns number of bytes streamed, which may be zero. End of stream can be
194/// If `optional_max_size` is null, appending is unbounded.859/// detected by checking if the next byte in the stream is the delimiter.
195pub fn streamUntilDelimiter(860///
196 self: Self,861/// See also:
197 writer: anytype,862/// * `streamDelimiter`
863/// * `streamDelimiterLimit`
864pub fn streamDelimiterEnding(
865 r: *Reader,
866 w: *Writer,
198 delimiter: u8,867 delimiter: u8,
199 optional_max_size: ?usize,868) StreamRemainingError!usize {
200) anyerror!void {869 return streamDelimiterLimit(r, w, delimiter, .unlimited) catch |err| switch (err) {
201 if (optional_max_size) |max_size| {870 error.StreamTooLong => unreachable, // unlimited is passed
202 for (0..max_size) |_| {871 else => |e| return e,
203 const byte: u8 = try self.readByte();872 };
204 if (byte == delimiter) return;873}
205 try writer.writeByte(byte);874
206 }875pub const StreamDelimiterLimitError = error{
207 return error.StreamTooLong;876 ReadFailed,
208 } else {877 WriteFailed,
209 while (true) {878 /// The delimiter was not found within the limit.
210 const byte: u8 = try self.readByte();879 StreamTooLong,
211 if (byte == delimiter) return;880};
212 try writer.writeByte(byte);881
882/// Appends to `w` contents by reading from the stream until `delimiter` is found.
883/// Does not write the delimiter itself.
884///
885/// Returns number of bytes streamed, which may be zero. End of stream can be
886/// detected by checking if the next byte in the stream is the delimiter.
887pub fn streamDelimiterLimit(
888 r: *Reader,
889 w: *Writer,
890 delimiter: u8,
891 limit: Limit,
892) StreamDelimiterLimitError!usize {
893 var remaining = @intFromEnum(limit);
894 while (remaining != 0) {
895 const available = Limit.limited(remaining).slice(r.peekGreedy(1) catch |err| switch (err) {
896 error.ReadFailed => return error.ReadFailed,
897 error.EndOfStream => return @intFromEnum(limit) - remaining,
898 });
899 if (std.mem.indexOfScalar(u8, available, delimiter)) |delimiter_index| {
900 try w.writeAll(available[0..delimiter_index]);
901 r.toss(delimiter_index);
902 remaining -= delimiter_index;
903 return @intFromEnum(limit) - remaining;
213 }904 }
214 // Can not throw `error.StreamTooLong` since there are no boundary.905 try w.writeAll(available);
906 r.toss(available.len);
907 remaining -= available.len;
215 }908 }
909 return error.StreamTooLong;
216}910}
217911
218/// Reads from the stream until specified byte is found, discarding all data,912/// Reads from the stream until specified byte is found, discarding all data,
219/// including the delimiter.913/// including the delimiter.
220/// If end-of-stream is found, this function succeeds.914///
221pub fn skipUntilDelimiterOrEof(self: Self, delimiter: u8) anyerror!void {915/// Returns number of bytes discarded, or `error.EndOfStream` if the delimiter
222 while (true) {916/// is not found.
223 const byte = self.readByte() catch |err| switch (err) {917///
224 error.EndOfStream => return,918/// See also:
919/// * `discardDelimiterExclusive`
920/// * `discardDelimiterLimit`
921pub fn discardDelimiterInclusive(r: *Reader, delimiter: u8) Error!usize {
922 const n = discardDelimiterLimit(r, delimiter, .unlimited) catch |err| switch (err) {
923 error.StreamTooLong => unreachable, // unlimited is passed
924 else => |e| return e,
925 };
926 if (r.seek == r.end) return error.EndOfStream;
927 assert(r.buffer[r.seek] == delimiter);
928 toss(r, 1);
929 return n + 1;
930}
931
932/// Reads from the stream until specified byte is found, discarding all data,
933/// excluding the delimiter.
934///
935/// Returns the number of bytes discarded.
936///
937/// Succeeds if stream ends before delimiter found. End of stream can be
938/// detected by checking if the delimiter is buffered.
939///
940/// See also:
941/// * `discardDelimiterInclusive`
942/// * `discardDelimiterLimit`
943pub fn discardDelimiterExclusive(r: *Reader, delimiter: u8) ShortError!usize {
944 return discardDelimiterLimit(r, delimiter, .unlimited) catch |err| switch (err) {
945 error.StreamTooLong => unreachable, // unlimited is passed
946 else => |e| return e,
947 };
948}
949
950pub const DiscardDelimiterLimitError = error{
951 ReadFailed,
952 /// The delimiter was not found within the limit.
953 StreamTooLong,
954};
955
956/// Reads from the stream until specified byte is found, discarding all data,
957/// excluding the delimiter.
958///
959/// Returns the number of bytes discarded.
960///
961/// Succeeds if stream ends before delimiter found. End of stream can be
962/// detected by checking if the delimiter is buffered.
963pub fn discardDelimiterLimit(r: *Reader, delimiter: u8, limit: Limit) DiscardDelimiterLimitError!usize {
964 var remaining = @intFromEnum(limit);
965 while (remaining != 0) {
966 const available = Limit.limited(remaining).slice(r.peekGreedy(1) catch |err| switch (err) {
967 error.ReadFailed => return error.ReadFailed,
968 error.EndOfStream => return @intFromEnum(limit) - remaining,
969 });
970 if (std.mem.indexOfScalar(u8, available, delimiter)) |delimiter_index| {
971 r.toss(delimiter_index);
972 remaining -= delimiter_index;
973 return @intFromEnum(limit) - remaining;
974 }
975 r.toss(available.len);
976 remaining -= available.len;
977 }
978 return error.StreamTooLong;
979}
980
981/// Fills the buffer such that it contains at least `n` bytes, without
982/// advancing the seek position.
983///
984/// Returns `error.EndOfStream` if and only if there are fewer than `n` bytes
985/// remaining.
986///
987/// Asserts buffer capacity is at least `n`.
988pub fn fill(r: *Reader, n: usize) Error!void {
989 assert(n <= r.buffer.len);
990 if (r.seek + n <= r.end) {
991 @branchHint(.likely);
992 return;
993 }
994 if (r.seek + n <= r.buffer.len) while (true) {
995 const end_cap = r.buffer[r.end..];
996 var writer: Writer = .fixed(end_cap);
997 r.end += r.vtable.stream(r, &writer, .limited(end_cap.len)) catch |err| switch (err) {
998 error.WriteFailed => unreachable,
225 else => |e| return e,999 else => |e| return e,
226 };1000 };
227 if (byte == delimiter) return;1001 if (r.seek + n <= r.end) return;
1002 };
1003 if (r.vtable.stream == &endingStream) {
1004 // Protect the `@constCast` of `fixed`.
1005 return error.EndOfStream;
1006 }
1007 rebaseCapacity(r, n);
1008 var writer: Writer = .{
1009 .buffer = r.buffer,
1010 .vtable = &.{ .drain = Writer.fixedDrain },
1011 };
1012 while (r.end < r.seek + n) {
1013 writer.end = r.end;
1014 r.end += r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) {
1015 error.WriteFailed => unreachable,
1016 error.ReadFailed, error.EndOfStream => |e| return e,
1017 };
228 }1018 }
229}1019}
2301020
231/// Reads 1 byte from the stream or returns `error.EndOfStream`.1021/// Without advancing the seek position, does exactly one underlying read, filling the buffer as
232pub fn readByte(self: Self) anyerror!u8 {1022/// much as possible. This may result in zero bytes added to the buffer, which is not an end of
233 var result: [1]u8 = undefined;1023/// stream condition. End of stream is communicated via returning `error.EndOfStream`.
234 const amt_read = try self.read(result[0..]);1024///
235 if (amt_read < 1) return error.EndOfStream;1025/// Asserts buffer capacity is at least 1.
236 return result[0];1026pub fn fillMore(r: *Reader) Error!void {
237}1027 rebaseCapacity(r, 1);
2381028 var writer: Writer = .{
239/// Same as `readByte` except the returned byte is signed.1029 .buffer = r.buffer,
240pub fn readByteSigned(self: Self) anyerror!i8 {1030 .end = r.end,
241 return @as(i8, @bitCast(try self.readByte()));1031 .vtable = &.{ .drain = Writer.fixedDrain },
242}1032 };
2431033 r.end += r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) {
244/// Reads exactly `num_bytes` bytes and returns as an array.1034 error.WriteFailed => unreachable,
245/// `num_bytes` must be comptime-known1035 else => |e| return e,
246pub fn readBytesNoEof(self: Self, comptime num_bytes: usize) anyerror![num_bytes]u8 {1036 };
247 var bytes: [num_bytes]u8 = undefined;1037}
248 try self.readNoEof(&bytes);1038
249 return bytes;1039/// Returns the next byte from the stream or returns `error.EndOfStream`.
250}1040///
2511041/// Does not advance the seek position.
252/// Reads bytes until `bounded.len` is equal to `num_bytes`,1042///
253/// or the stream ends.1043/// Asserts the buffer capacity is nonzero.
254///1044pub fn peekByte(r: *Reader) Error!u8 {
255/// * it is assumed that `num_bytes` will not exceed `bounded.capacity()`1045 const buffer = r.buffer[0..r.end];
256pub fn readIntoBoundedBytes(1046 const seek = r.seek;
257 self: Self,1047 if (seek < buffer.len) {
258 comptime num_bytes: usize,1048 @branchHint(.likely);
259 bounded: *std.BoundedArray(u8, num_bytes),1049 return buffer[seek];
260) anyerror!void {
261 while (bounded.len < num_bytes) {
262 // get at most the number of bytes free in the bounded array
263 const bytes_read = try self.read(bounded.unusedCapacitySlice());
264 if (bytes_read == 0) return;
265
266 // bytes_read will never be larger than @TypeOf(bounded.len)
267 // due to `self.read` being bounded by `bounded.unusedCapacitySlice()`
268 bounded.len += @as(@TypeOf(bounded.len), @intCast(bytes_read));
269 }1050 }
1051 try fill(r, 1);
1052 return r.buffer[r.seek];
270}1053}
2711054
272/// Reads at most `num_bytes` and returns as a bounded array.1055/// Reads 1 byte from the stream or returns `error.EndOfStream`.
273pub fn readBoundedBytes(self: Self, comptime num_bytes: usize) anyerror!std.BoundedArray(u8, num_bytes) {1056///
274 var result = std.BoundedArray(u8, num_bytes){};1057/// Asserts the buffer capacity is nonzero.
275 try self.readIntoBoundedBytes(num_bytes, &result);1058pub fn takeByte(r: *Reader) Error!u8 {
1059 const result = try peekByte(r);
1060 r.seek += 1;
276 return result;1061 return result;
277}1062}
2781063
279pub inline fn readInt(self: Self, comptime T: type, endian: std.builtin.Endian) anyerror!T {1064/// Same as `takeByte` except the returned byte is signed.
280 const bytes = try self.readBytesNoEof(@divExact(@typeInfo(T).int.bits, 8));1065pub fn takeByteSigned(r: *Reader) Error!i8 {
281 return mem.readInt(T, &bytes, endian);1066 return @bitCast(try r.takeByte());
282}1067}
2831068
284pub fn readVarInt(1069/// Asserts the buffer was initialized with a capacity at least `@bitSizeOf(T) / 8`.
285 self: Self,1070pub inline fn takeInt(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
286 comptime ReturnType: type,1071 const n = @divExact(@typeInfo(T).int.bits, 8);
287 endian: std.builtin.Endian,1072 return std.mem.readInt(T, try r.takeArray(n), endian);
288 size: usize,1073}
289) anyerror!ReturnType {
290 assert(size <= @sizeOf(ReturnType));
291 var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
292 const bytes = bytes_buf[0..size];
293 try self.readNoEof(bytes);
294 return mem.readVarInt(ReturnType, bytes, endian);
295}
296
297/// Optional parameters for `skipBytes`
298pub const SkipBytesOptions = struct {
299 buf_size: usize = 512,
300};
301
302// `num_bytes` is a `u64` to match `off_t`
303/// Reads `num_bytes` bytes from the stream and discards them
304pub fn skipBytes(self: Self, num_bytes: u64, comptime options: SkipBytesOptions) anyerror!void {
305 var buf: [options.buf_size]u8 = undefined;
306 var remaining = num_bytes;
3071074
308 while (remaining > 0) {1075/// Asserts the buffer was initialized with a capacity at least `n`.
309 const amt = @min(remaining, options.buf_size);1076pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n: usize) Error!Int {
310 try self.readNoEof(buf[0..amt]);1077 assert(n <= @sizeOf(Int));
311 remaining -= amt;1078 return std.mem.readVarInt(Int, try r.take(n), endian);
312 }
313}1079}
3141080
315/// Reads `slice.len` bytes from the stream and returns if they are the same as the passed slice1081/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
316pub fn isBytes(self: Self, slice: []const u8) anyerror!bool {1082///
317 var i: usize = 0;1083/// Advances the seek position.
318 var matches = true;1084///
319 while (i < slice.len) : (i += 1) {1085/// See also:
320 if (slice[i] != try self.readByte()) {1086/// * `peekStruct`
321 matches = false;1087/// * `takeStructEndian`
322 }1088pub fn takeStruct(r: *Reader, comptime T: type) Error!*align(1) T {
323 }1089 // Only extern and packed structs have defined in-memory layout.
324 return matches;1090 comptime assert(@typeInfo(T).@"struct".layout != .auto);
1091 return @ptrCast(try r.takeArray(@sizeOf(T)));
325}1092}
3261093
327pub fn readStruct(self: Self, comptime T: type) anyerror!T {1094/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
1095///
1096/// Does not advance the seek position.
1097///
1098/// See also:
1099/// * `takeStruct`
1100/// * `peekStructEndian`
1101pub fn peekStruct(r: *Reader, comptime T: type) Error!*align(1) T {
328 // Only extern and packed structs have defined in-memory layout.1102 // Only extern and packed structs have defined in-memory layout.
329 comptime assert(@typeInfo(T).@"struct".layout != .auto);1103 comptime assert(@typeInfo(T).@"struct".layout != .auto);
330 var res: [1]T = undefined;1104 return @ptrCast(try r.peekArray(@sizeOf(T)));
331 try self.readNoEof(mem.sliceAsBytes(res[0..]));
332 return res[0];
333}1105}
3341106
335pub fn readStructEndian(self: Self, comptime T: type, endian: std.builtin.Endian) anyerror!T {1107/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
336 var res = try self.readStruct(T);1108///
337 if (native_endian != endian) {1109/// This function is inline to avoid referencing `std.mem.byteSwapAllFields`
338 mem.byteSwapAllFields(T, &res);1110/// when `endian` is comptime-known and matches the host endianness.
339 }1111///
1112/// See also:
1113/// * `takeStruct`
1114/// * `peekStructEndian`
1115pub inline fn takeStructEndian(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
1116 var res = (try r.takeStruct(T)).*;
1117 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
340 return res;1118 return res;
341}1119}
3421120
343/// Reads an integer with the same size as the given enum's tag type. If the integer matches1121/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
344/// an enum tag, casts the integer to the enum tag and returns it. Otherwise, returns an `error.InvalidValue`.1122///
345/// TODO optimization taking advantage of most fields being in order1123/// This function is inline to avoid referencing `std.mem.byteSwapAllFields`
346pub fn readEnum(self: Self, comptime Enum: type, endian: std.builtin.Endian) anyerror!Enum {1124/// when `endian` is comptime-known and matches the host endianness.
347 const E = error{1125///
348 /// An integer was read, but it did not match any of the tags in the supplied enum.1126/// See also:
349 InvalidValue,1127/// * `takeStructEndian`
1128/// * `peekStruct`
1129pub inline fn peekStructEndian(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
1130 var res = (try r.peekStruct(T)).*;
1131 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
1132 return res;
1133}
1134
1135pub const TakeEnumError = Error || error{InvalidEnumTag};
1136
1137/// Reads an integer with the same size as the given enum's tag type. If the
1138/// integer matches an enum tag, casts the integer to the enum tag and returns
1139/// it. Otherwise, returns `error.InvalidEnumTag`.
1140///
1141/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
1142pub fn takeEnum(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) TakeEnumError!Enum {
1143 const Tag = @typeInfo(Enum).@"enum".tag_type;
1144 const int = try r.takeInt(Tag, endian);
1145 return std.meta.intToEnum(Enum, int);
1146}
1147
1148/// Reads an integer with the same size as the given nonexhaustive enum's tag type.
1149///
1150/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
1151pub fn takeEnumNonexhaustive(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) Error!Enum {
1152 const info = @typeInfo(Enum).@"enum";
1153 comptime assert(!info.is_exhaustive);
1154 comptime assert(@bitSizeOf(info.tag_type) == @sizeOf(info.tag_type) * 8);
1155 return takeEnum(r, Enum, endian) catch |err| switch (err) {
1156 error.InvalidEnumTag => unreachable,
1157 else => |e| return e,
350 };1158 };
351 const type_info = @typeInfo(Enum).@"enum";1159}
352 const tag = try self.readInt(type_info.tag_type, endian);
3531160
354 inline for (std.meta.fields(Enum)) |field| {1161pub const TakeLeb128Error = Error || error{Overflow};
355 if (tag == field.value) {1162
356 return @field(Enum, field.name);1163/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit.
357 }1164pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
1165 const result_info = @typeInfo(Result).int;
1166 return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Type(.{ .int = .{
1167 .signedness = result_info.signedness,
1168 .bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7),
1169 } }))) orelse error.Overflow;
1170}
1171
1172pub fn expandTotalCapacity(r: *Reader, allocator: Allocator, n: usize) Allocator.Error!void {
1173 if (n <= r.buffer.len) return;
1174 if (r.seek > 0) rebase(r);
1175 var list: ArrayList(u8) = .{
1176 .items = r.buffer[0..r.end],
1177 .capacity = r.buffer.len,
1178 };
1179 defer r.buffer = list.allocatedSlice();
1180 try list.ensureTotalCapacity(allocator, n);
1181}
1182
1183pub const FillAllocError = Error || Allocator.Error;
1184
1185pub fn fillAlloc(r: *Reader, allocator: Allocator, n: usize) FillAllocError!void {
1186 try expandTotalCapacity(r, allocator, n);
1187 return fill(r, n);
1188}
1189
1190/// Returns a slice into the unused capacity of `buffer` with at least
1191/// `min_len` bytes, extending `buffer` by resizing it with `gpa` as necessary.
1192///
1193/// After calling this function, typically the caller will follow up with a
1194/// call to `advanceBufferEnd` to report the actual number of bytes buffered.
1195pub fn writableSliceGreedyAlloc(r: *Reader, allocator: Allocator, min_len: usize) Allocator.Error![]u8 {
1196 {
1197 const unused = r.buffer[r.end..];
1198 if (unused.len >= min_len) return unused;
1199 }
1200 if (r.seek > 0) rebase(r);
1201 {
1202 var list: ArrayList(u8) = .{
1203 .items = r.buffer[0..r.end],
1204 .capacity = r.buffer.len,
1205 };
1206 defer r.buffer = list.allocatedSlice();
1207 try list.ensureUnusedCapacity(allocator, min_len);
358 }1208 }
1209 const unused = r.buffer[r.end..];
1210 assert(unused.len >= min_len);
1211 return unused;
1212}
3591213
360 return E.InvalidValue;1214/// After writing directly into the unused capacity of `buffer`, this function
1215/// updates `end` so that users of `Reader` can receive the data.
1216pub fn advanceBufferEnd(r: *Reader, n: usize) void {
1217 assert(n <= r.buffer.len - r.end);
1218 r.end += n;
361}1219}
3621220
363/// Reads the stream until the end, ignoring all the data.1221fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
364/// Returns the number of bytes discarded.1222 const result_info = @typeInfo(Result).int;
365pub fn discard(self: Self) anyerror!u64 {1223 comptime assert(result_info.bits % 7 == 0);
366 var trash: [4096]u8 = undefined;1224 var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits;
367 var index: u64 = 0;1225 const UnsignedResult = @Type(.{ .int = .{
1226 .signedness = .unsigned,
1227 .bits = result_info.bits,
1228 } });
1229 var result: UnsignedResult = 0;
1230 var fits = true;
368 while (true) {1231 while (true) {
369 const n = try self.read(&trash);1232 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try r.peekGreedy(1));
370 if (n == 0) return index;1233 for (buffer, 1..) |byte, len| {
371 index += n;1234 if (remaining_bits > 0) {
1235 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) |
1236 if (result_info.bits > 7) @shrExact(result, 7) else 0;
1237 remaining_bits -= 7;
1238 } else if (fits) fits = switch (result_info.signedness) {
1239 .signed => @as(i7, @bitCast(byte.bits)) ==
1240 @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),
1241 .unsigned => byte.bits == 0,
1242 };
1243 if (byte.more) continue;
1244 r.toss(len);
1245 return if (fits) @as(Result, @bitCast(result)) >> remaining_bits else error.Overflow;
1246 }
1247 r.toss(buffer.len);
372 }1248 }
373}1249}
3741250
375const std = @import("../std.zig");1251/// Left-aligns data such that `r.seek` becomes zero.
376const Self = @This();1252pub fn rebase(r: *Reader) void {
377const math = std.math;1253 if (r.seek == 0) return;
378const assert = std.debug.assert;1254 const data = r.buffer[r.seek..r.end];
379const mem = std.mem;1255 @memmove(r.buffer[0..data.len], data);
380const testing = std.testing;1256 r.seek = 0;
381const native_endian = @import("builtin").target.cpu.arch.endian();1257 r.end = data.len;
382const Alignment = std.mem.Alignment;1258}
1259
1260/// Ensures `capacity` more data can be buffered without rebasing, by rebasing
1261/// if necessary.
1262///
1263/// Asserts `capacity` is within the buffer capacity.
1264pub fn rebaseCapacity(r: *Reader, capacity: usize) void {
1265 if (r.end > r.buffer.len - capacity) rebase(r);
1266}
1267
1268/// Advances the stream and decreases the size of the storage buffer by `n`,
1269/// returning the range of bytes no longer accessible by `r`.
1270///
1271/// This action can be undone by `restitute`.
1272///
1273/// Asserts there are at least `n` buffered bytes already.
1274///
1275/// Asserts that `r.seek` is zero, i.e. the buffer is in a rebased state.
1276pub fn steal(r: *Reader, n: usize) []u8 {
1277 assert(r.seek == 0);
1278 assert(n <= r.end);
1279 const stolen = r.buffer[0..n];
1280 r.buffer = r.buffer[n..];
1281 r.end -= n;
1282 return stolen;
1283}
1284
1285/// Expands the storage buffer, undoing the effects of `steal`
1286/// Assumes that `n` does not exceed the total number of stolen bytes.
1287pub fn restitute(r: *Reader, n: usize) void {
1288 r.buffer = (r.buffer.ptr - n)[0 .. r.buffer.len + n];
1289 r.end += n;
1290 r.seek += n;
1291}
3831292
384test {1293test fixed {
385 _ = @import("Reader/test.zig");1294 var r: Reader = .fixed("a\x02");
1295 try testing.expect((try r.takeByte()) == 'a');
1296 try testing.expect((try r.takeEnum(enum(u8) {
1297 a = 0,
1298 b = 99,
1299 c = 2,
1300 d = 3,
1301 }, builtin.cpu.arch.endian())) == .c);
1302 try testing.expectError(error.EndOfStream, r.takeByte());
1303}
1304
1305test peek {
1306 var r: Reader = .fixed("abc");
1307 try testing.expectEqualStrings("ab", try r.peek(2));
1308 try testing.expectEqualStrings("a", try r.peek(1));
1309}
1310
1311test peekGreedy {
1312 var r: Reader = .fixed("abc");
1313 try testing.expectEqualStrings("abc", try r.peekGreedy(1));
1314}
1315
1316test toss {
1317 var r: Reader = .fixed("abc");
1318 r.toss(1);
1319 try testing.expectEqualStrings("bc", r.buffered());
1320}
1321
1322test take {
1323 var r: Reader = .fixed("abc");
1324 try testing.expectEqualStrings("ab", try r.take(2));
1325 try testing.expectEqualStrings("c", try r.take(1));
1326}
1327
1328test takeArray {
1329 var r: Reader = .fixed("abc");
1330 try testing.expectEqualStrings("ab", try r.takeArray(2));
1331 try testing.expectEqualStrings("c", try r.takeArray(1));
1332}
1333
1334test peekArray {
1335 var r: Reader = .fixed("abc");
1336 try testing.expectEqualStrings("ab", try r.peekArray(2));
1337 try testing.expectEqualStrings("a", try r.peekArray(1));
1338}
1339
1340test discardAll {
1341 var r: Reader = .fixed("foobar");
1342 try r.discardAll(3);
1343 try testing.expectEqualStrings("bar", try r.take(3));
1344 try r.discardAll(0);
1345 try testing.expectError(error.EndOfStream, r.discardAll(1));
1346}
1347
1348test discardRemaining {
1349 var r: Reader = .fixed("foobar");
1350 r.toss(1);
1351 try testing.expectEqual(5, try r.discardRemaining());
1352 try testing.expectEqual(0, try r.discardRemaining());
1353}
1354
1355test stream {
1356 var out_buffer: [10]u8 = undefined;
1357 var r: Reader = .fixed("foobar");
1358 var w: Writer = .fixed(&out_buffer);
1359 // Short streams are possible with this function but not with fixed.
1360 try testing.expectEqual(2, try r.stream(&w, .limited(2)));
1361 try testing.expectEqualStrings("fo", w.buffered());
1362 try testing.expectEqual(4, try r.stream(&w, .unlimited));
1363 try testing.expectEqualStrings("foobar", w.buffered());
1364}
1365
1366test takeSentinel {
1367 var r: Reader = .fixed("ab\nc");
1368 try testing.expectEqualStrings("ab", try r.takeSentinel('\n'));
1369 try testing.expectError(error.EndOfStream, r.takeSentinel('\n'));
1370 try testing.expectEqualStrings("c", try r.peek(1));
1371}
1372
1373test peekSentinel {
1374 var r: Reader = .fixed("ab\nc");
1375 try testing.expectEqualStrings("ab", try r.peekSentinel('\n'));
1376 try testing.expectEqualStrings("ab", try r.peekSentinel('\n'));
1377}
1378
1379test takeDelimiterInclusive {
1380 var r: Reader = .fixed("ab\nc");
1381 try testing.expectEqualStrings("ab\n", try r.takeDelimiterInclusive('\n'));
1382 try testing.expectError(error.EndOfStream, r.takeDelimiterInclusive('\n'));
1383}
1384
1385test peekDelimiterInclusive {
1386 var r: Reader = .fixed("ab\nc");
1387 try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n'));
1388 try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n'));
1389 r.toss(3);
1390 try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n'));
1391}
1392
1393test takeDelimiterExclusive {
1394 var r: Reader = .fixed("ab\nc");
1395 try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n'));
1396 try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n'));
1397 try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n'));
1398}
1399
1400test peekDelimiterExclusive {
1401 var r: Reader = .fixed("ab\nc");
1402 try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n'));
1403 try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n'));
1404 r.toss(3);
1405 try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n'));
1406}
1407
1408test streamDelimiter {
1409 var out_buffer: [10]u8 = undefined;
1410 var r: Reader = .fixed("foo\nbars");
1411 var w: Writer = .fixed(&out_buffer);
1412 try testing.expectEqual(3, try r.streamDelimiter(&w, '\n'));
1413 try testing.expectEqualStrings("foo", w.buffered());
1414 try testing.expectEqual(0, try r.streamDelimiter(&w, '\n'));
1415 r.toss(1);
1416 try testing.expectError(error.EndOfStream, r.streamDelimiter(&w, '\n'));
1417}
1418
1419test streamDelimiterEnding {
1420 var out_buffer: [10]u8 = undefined;
1421 var r: Reader = .fixed("foo\nbars");
1422 var w: Writer = .fixed(&out_buffer);
1423 try testing.expectEqual(3, try r.streamDelimiterEnding(&w, '\n'));
1424 try testing.expectEqualStrings("foo", w.buffered());
1425 r.toss(1);
1426 try testing.expectEqual(4, try r.streamDelimiterEnding(&w, '\n'));
1427 try testing.expectEqualStrings("foobars", w.buffered());
1428 try testing.expectEqual(0, try r.streamDelimiterEnding(&w, '\n'));
1429 try testing.expectEqual(0, try r.streamDelimiterEnding(&w, '\n'));
1430}
1431
1432test streamDelimiterLimit {
1433 var out_buffer: [10]u8 = undefined;
1434 var r: Reader = .fixed("foo\nbars");
1435 var w: Writer = .fixed(&out_buffer);
1436 try testing.expectError(error.StreamTooLong, r.streamDelimiterLimit(&w, '\n', .limited(2)));
1437 try testing.expectEqual(1, try r.streamDelimiterLimit(&w, '\n', .limited(3)));
1438 try testing.expectEqualStrings("\n", try r.take(1));
1439 try testing.expectEqual(4, try r.streamDelimiterLimit(&w, '\n', .unlimited));
1440 try testing.expectEqualStrings("foobars", w.buffered());
1441}
1442
1443test discardDelimiterExclusive {
1444 var r: Reader = .fixed("foob\nar");
1445 try testing.expectEqual(4, try r.discardDelimiterExclusive('\n'));
1446 try testing.expectEqualStrings("\n", try r.take(1));
1447 try testing.expectEqual(2, try r.discardDelimiterExclusive('\n'));
1448 try testing.expectEqual(0, try r.discardDelimiterExclusive('\n'));
1449}
1450
1451test discardDelimiterInclusive {
1452 var r: Reader = .fixed("foob\nar");
1453 try testing.expectEqual(5, try r.discardDelimiterInclusive('\n'));
1454 try testing.expectError(error.EndOfStream, r.discardDelimiterInclusive('\n'));
1455}
1456
1457test discardDelimiterLimit {
1458 var r: Reader = .fixed("foob\nar");
1459 try testing.expectError(error.StreamTooLong, r.discardDelimiterLimit('\n', .limited(4)));
1460 try testing.expectEqual(0, try r.discardDelimiterLimit('\n', .limited(2)));
1461 try testing.expectEqualStrings("\n", try r.take(1));
1462 try testing.expectEqual(2, try r.discardDelimiterLimit('\n', .unlimited));
1463 try testing.expectEqual(0, try r.discardDelimiterLimit('\n', .unlimited));
1464}
1465
1466test fill {
1467 var r: Reader = .fixed("abc");
1468 try r.fill(1);
1469 try r.fill(3);
1470}
1471
1472test takeByte {
1473 var r: Reader = .fixed("ab");
1474 try testing.expectEqual('a', try r.takeByte());
1475 try testing.expectEqual('b', try r.takeByte());
1476 try testing.expectError(error.EndOfStream, r.takeByte());
1477}
1478
1479test takeByteSigned {
1480 var r: Reader = .fixed(&.{ 255, 5 });
1481 try testing.expectEqual(-1, try r.takeByteSigned());
1482 try testing.expectEqual(5, try r.takeByteSigned());
1483 try testing.expectError(error.EndOfStream, r.takeByteSigned());
1484}
1485
1486test takeInt {
1487 var r: Reader = .fixed(&.{ 0x12, 0x34, 0x56 });
1488 try testing.expectEqual(0x1234, try r.takeInt(u16, .big));
1489 try testing.expectError(error.EndOfStream, r.takeInt(u16, .little));
1490}
1491
1492test takeVarInt {
1493 var r: Reader = .fixed(&.{ 0x12, 0x34, 0x56 });
1494 try testing.expectEqual(0x123456, try r.takeVarInt(u64, .big, 3));
1495 try testing.expectError(error.EndOfStream, r.takeVarInt(u16, .little, 1));
1496}
1497
1498test takeStruct {
1499 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
1500 const S = extern struct { a: u8, b: u16 };
1501 switch (native_endian) {
1502 .little => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.takeStruct(S)).*),
1503 .big => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.takeStruct(S)).*),
1504 }
1505 try testing.expectError(error.EndOfStream, r.takeStruct(S));
1506}
1507
1508test peekStruct {
1509 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
1510 const S = extern struct { a: u8, b: u16 };
1511 switch (native_endian) {
1512 .little => {
1513 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStruct(S)).*);
1514 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStruct(S)).*);
1515 },
1516 .big => {
1517 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStruct(S)).*);
1518 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStruct(S)).*);
1519 },
1520 }
1521}
1522
1523test takeStructEndian {
1524 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
1525 const S = extern struct { a: u8, b: u16 };
1526 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), try r.takeStructEndian(S, .big));
1527 try testing.expectError(error.EndOfStream, r.takeStructEndian(S, .little));
1528}
1529
1530test peekStructEndian {
1531 var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
1532 const S = extern struct { a: u8, b: u16 };
1533 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), try r.peekStructEndian(S, .big));
1534 try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), try r.peekStructEndian(S, .little));
1535}
1536
1537test takeEnum {
1538 var r: Reader = .fixed(&.{ 2, 0, 1 });
1539 const E1 = enum(u8) { a, b, c };
1540 const E2 = enum(u16) { _ };
1541 try testing.expectEqual(E1.c, try r.takeEnum(E1, .little));
1542 try testing.expectEqual(@as(E2, @enumFromInt(0x0001)), try r.takeEnum(E2, .big));
1543}
1544
1545test takeLeb128 {
1546 var r: Reader = .fixed("\xc7\x9f\x7f\x80");
1547 try testing.expectEqual(-12345, try r.takeLeb128(i64));
1548 try testing.expectEqual(0x80, try r.peekByte());
1549 try testing.expectError(error.EndOfStream, r.takeLeb128(i64));
1550}
1551
1552test readSliceShort {
1553 var r: Reader = .fixed("HelloFren");
1554 var buf: [5]u8 = undefined;
1555 try testing.expectEqual(5, try r.readSliceShort(&buf));
1556 try testing.expectEqualStrings("Hello", buf[0..5]);
1557 try testing.expectEqual(4, try r.readSliceShort(&buf));
1558 try testing.expectEqualStrings("Fren", buf[0..4]);
1559 try testing.expectEqual(0, try r.readSliceShort(&buf));
1560}
1561
1562test readVec {
1563 var r: Reader = .fixed(std.ascii.letters);
1564 var flat_buffer: [52]u8 = undefined;
1565 var bufs: [2][]u8 = .{
1566 flat_buffer[0..26],
1567 flat_buffer[26..],
1568 };
1569 // Short reads are possible with this function but not with fixed.
1570 try testing.expectEqual(26 * 2, try r.readVec(&bufs));
1571 try testing.expectEqualStrings(std.ascii.letters[0..26], bufs[0]);
1572 try testing.expectEqualStrings(std.ascii.letters[26..], bufs[1]);
1573}
1574
1575test readVecLimit {
1576 var r: Reader = .fixed(std.ascii.letters);
1577 var flat_buffer: [52]u8 = undefined;
1578 var bufs: [2][]u8 = .{
1579 flat_buffer[0..26],
1580 flat_buffer[26..],
1581 };
1582 // Short reads are possible with this function but not with fixed.
1583 try testing.expectEqual(50, try r.readVecLimit(&bufs, .limited(50)));
1584 try testing.expectEqualStrings(std.ascii.letters[0..26], bufs[0]);
1585 try testing.expectEqualStrings(std.ascii.letters[26..50], bufs[1][0..24]);
1586}
1587
1588test "expected error.EndOfStream" {
1589 // Unit test inspired by https://github.com/ziglang/zig/issues/17733
1590 var buffer: [3]u8 = undefined;
1591 var r: std.io.Reader = .fixed(&buffer);
1592 r.end = 0; // capacity 3, but empty
1593 try std.testing.expectError(error.EndOfStream, r.takeEnum(enum(u8) { a, b }, .little));
1594 try std.testing.expectError(error.EndOfStream, r.take(3));
1595}
1596
1597fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1598 _ = r;
1599 _ = w;
1600 _ = limit;
1601 return error.EndOfStream;
1602}
1603
1604fn endingDiscard(r: *Reader, limit: Limit) Error!usize {
1605 _ = r;
1606 _ = limit;
1607 return error.EndOfStream;
1608}
1609
1610fn failingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1611 _ = r;
1612 _ = w;
1613 _ = limit;
1614 return error.ReadFailed;
1615}
1616
1617fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
1618 _ = r;
1619 _ = limit;
1620 return error.ReadFailed;
1621}
1622
1623test "readAlloc when the backing reader provides one byte at a time" {
1624 const OneByteReader = struct {
1625 str: []const u8,
1626 i: usize,
1627 reader: Reader,
1628
1629 fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1630 assert(@intFromEnum(limit) >= 1);
1631 const self: *@This() = @fieldParentPtr("reader", r);
1632 if (self.str.len - self.i == 0) return error.EndOfStream;
1633 try w.writeByte(self.str[self.i]);
1634 self.i += 1;
1635 return 1;
1636 }
1637 };
1638 const str = "This is a test";
1639 var one_byte_stream: OneByteReader = .{
1640 .str = str,
1641 .i = 0,
1642 .reader = .{
1643 .buffer = &.{},
1644 .vtable = &.{ .stream = OneByteReader.stream },
1645 .seek = 0,
1646 .end = 0,
1647 },
1648 };
1649 const res = try one_byte_stream.reader.allocRemaining(std.testing.allocator, .unlimited);
1650 defer std.testing.allocator.free(res);
1651 try std.testing.expectEqualStrings(str, res);
1652}
1653
1654test "takeDelimiterInclusive when it rebases" {
1655 const written_line = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
1656 var buffer: [128]u8 = undefined;
1657 var tr: std.testing.Reader = .init(&buffer, &.{
1658 .{ .buffer = written_line },
1659 .{ .buffer = written_line },
1660 .{ .buffer = written_line },
1661 .{ .buffer = written_line },
1662 .{ .buffer = written_line },
1663 .{ .buffer = written_line },
1664 });
1665 const r = &tr.interface;
1666 for (0..6) |_| {
1667 try std.testing.expectEqualStrings(written_line, try r.takeDelimiterInclusive('\n'));
1668 }
1669}
1670
1671/// Provides a `Reader` implementation by passing data from an underlying
1672/// reader through `Hasher.update`.
1673///
1674/// The underlying reader is best unbuffered.
1675///
1676/// This implementation makes suboptimal buffering decisions due to being
1677/// generic. A better solution will involve creating a reader for each hash
1678/// function, where the discard buffer can be tailored to the hash
1679/// implementation details.
1680pub fn Hashed(comptime Hasher: type) type {
1681 return struct {
1682 in: *Reader,
1683 hasher: Hasher,
1684 interface: Reader,
1685
1686 pub fn init(in: *Reader, hasher: Hasher, buffer: []u8) @This() {
1687 return .{
1688 .in = in,
1689 .hasher = hasher,
1690 .interface = .{
1691 .vtable = &.{
1692 .read = @This().read,
1693 .discard = @This().discard,
1694 },
1695 .buffer = buffer,
1696 .end = 0,
1697 .seek = 0,
1698 },
1699 };
1700 }
1701
1702 fn read(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1703 const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1704 const data = w.writableVector(limit);
1705 const n = try this.in.readVec(data);
1706 const result = w.advanceVector(n);
1707 var remaining: usize = n;
1708 for (data) |slice| {
1709 if (remaining < slice.len) {
1710 this.hasher.update(slice[0..remaining]);
1711 return result;
1712 } else {
1713 remaining -= slice.len;
1714 this.hasher.update(slice);
1715 }
1716 }
1717 assert(remaining == 0);
1718 return result;
1719 }
1720
1721 fn discard(r: *Reader, limit: Limit) Error!usize {
1722 const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1723 var w = this.hasher.writer(&.{});
1724 const n = this.in.stream(&w, limit) catch |err| switch (err) {
1725 error.WriteFailed => unreachable,
1726 else => |e| return e,
1727 };
1728 return n;
1729 }
1730 };
386}1731}
lib/std/io/Reader/Limited.zig created+42
...@@ -0,0 +1,42 @@
1const Limited = @This();
2
3const std = @import("../../std.zig");
4const Reader = std.io.Reader;
5const Writer = std.io.Writer;
6const Limit = std.io.Limit;
7
8unlimited: *Reader,
9remaining: Limit,
10interface: Reader,
11
12pub fn init(reader: *Reader, limit: Limit, buffer: []u8) Limited {
13 return .{
14 .unlimited = reader,
15 .remaining = limit,
16 .interface = .{
17 .vtable = &.{
18 .stream = stream,
19 .discard = discard,
20 },
21 .buffer = buffer,
22 .seek = 0,
23 .end = 0,
24 },
25 };
26}
27
28fn stream(context: ?*anyopaque, w: *Writer, limit: Limit) Reader.StreamError!usize {
29 const l: *Limited = @alignCast(@ptrCast(context));
30 const combined_limit = limit.min(l.remaining);
31 const n = try l.unlimited_reader.read(w, combined_limit);
32 l.remaining = l.remaining.subtract(n).?;
33 return n;
34}
35
36fn discard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {
37 const l: *Limited = @alignCast(@ptrCast(context));
38 const combined_limit = limit.min(l.remaining);
39 const n = try l.unlimited_reader.discard(combined_limit);
40 l.remaining = l.remaining.subtract(n).?;
41 return n;
42}
lib/std/io/Writer.zig+2449-46
...@@ -1,83 +1,2486 @@...@@ -1,83 +1,2486 @@
1const builtin = @import("builtin");
2const native_endian = builtin.target.cpu.arch.endian();
3
4const Writer = @This();
1const std = @import("../std.zig");5const std = @import("../std.zig");
2const assert = std.debug.assert;6const assert = std.debug.assert;
3const mem = std.mem;7const Limit = std.io.Limit;
4const native_endian = @import("builtin").target.cpu.arch.endian();8const File = std.fs.File;
9const testing = std.testing;
10const Allocator = std.mem.Allocator;
11
12vtable: *const VTable,
13/// If this has length zero, the writer is unbuffered, and `flush` is a no-op.
14buffer: []u8,
15/// In `buffer` before this are buffered bytes, after this is `undefined`.
16end: usize = 0,
17
18pub const VTable = struct {
19 /// Sends bytes to the logical sink. A write will only be sent here if it
20 /// could not fit into `buffer`, or during a `flush` operation.
21 ///
22 /// `buffer[0..end]` is consumed first, followed by each slice of `data` in
23 /// order. Elements of `data` may alias each other but may not alias
24 /// `buffer`.
25 ///
26 /// This function modifies `Writer.end` and `Writer.buffer` in an
27 /// implementation-defined manner.
28 ///
29 /// `data.len` must be nonzero.
30 ///
31 /// The last element of `data` is repeated as necessary so that it is
32 /// written `splat` number of times, which may be zero.
33 ///
34 /// This function may not be called if the data to be written could have
35 /// been stored in `buffer` instead, including when the amount of data to
36 /// be written is zero and the buffer capacity is zero.
37 ///
38 /// Number of bytes consumed from `data` is returned, excluding bytes from
39 /// `buffer`.
40 ///
41 /// Number of bytes returned may be zero, which does not indicate stream
42 /// end. A subsequent call may return nonzero, or signal end of stream via
43 /// `error.WriteFailed`.
44 drain: *const fn (w: *Writer, data: []const []const u8, splat: usize) Error!usize,
45
46 /// Copies contents from an open file to the logical sink. `buffer[0..end]`
47 /// is consumed first, followed by `limit` bytes from `file_reader`.
48 ///
49 /// Number of bytes logically written is returned. This excludes bytes from
50 /// `buffer` because they have already been logically written. Number of
51 /// bytes consumed from `buffer` are tracked by modifying `end`.
52 ///
53 /// Number of bytes returned may be zero, which does not indicate stream
54 /// end. A subsequent call may return nonzero, or signal end of stream via
55 /// `error.WriteFailed`. Caller may check `file_reader` state
56 /// (`File.Reader.atEnd`) to disambiguate between a zero-length read or
57 /// write, and whether the file reached the end.
58 ///
59 /// `error.Unimplemented` indicates the callee cannot offer a more
60 /// efficient implementation than the caller performing its own reads.
61 sendFile: *const fn (
62 w: *Writer,
63 file_reader: *File.Reader,
64 /// Maximum amount of bytes to read from the file. Implementations may
65 /// assume that the file size does not exceed this amount. Data from
66 /// `buffer` does not count towards this limit.
67 limit: Limit,
68 ) FileError!usize = unimplementedSendFile,
69
70 /// Consumes all remaining buffer.
71 ///
72 /// The default flush implementation calls drain repeatedly until `end` is
73 /// zero, however it is legal for implementations to manage `end`
74 /// differently. For instance, `Allocating` flush is a no-op.
75 ///
76 /// There may be subsequent calls to `drain` and `sendFile` after a `flush`
77 /// operation.
78 flush: *const fn (w: *Writer) Error!void = defaultFlush,
79};
80
81pub const Error = error{
82 /// See the `Writer` implementation for detailed diagnostics.
83 WriteFailed,
84};
585
6context: *const anyopaque,86pub const FileAllError = error{
7writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize,87 /// Detailed diagnostics are found on the `File.Reader` struct.
88 ReadFailed,
89 /// See the `Writer` implementation for detailed diagnostics.
90 WriteFailed,
91};
892
9const Self = @This();93pub const FileReadingError = error{
10pub const Error = anyerror;94 /// Detailed diagnostics are found on the `File.Reader` struct.
95 ReadFailed,
96 /// See the `Writer` implementation for detailed diagnostics.
97 WriteFailed,
98 /// Reached the end of the file being read.
99 EndOfStream,
100};
11101
12pub fn write(self: Self, bytes: []const u8) anyerror!usize {102pub const FileError = error{
13 return self.writeFn(self.context, bytes);103 /// Detailed diagnostics are found on the `File.Reader` struct.
104 ReadFailed,
105 /// See the `Writer` implementation for detailed diagnostics.
106 WriteFailed,
107 /// Reached the end of the file being read.
108 EndOfStream,
109 /// Indicates the caller should do its own file reading; the callee cannot
110 /// offer a more efficient implementation.
111 Unimplemented,
112};
113
114/// Writes to `buffer` and returns `error.WriteFailed` when it is full.
115pub fn fixed(buffer: []u8) Writer {
116 return .{
117 .vtable = &.{ .drain = fixedDrain },
118 .buffer = buffer,
119 };
14}120}
15121
16pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {122pub fn hashed(w: *Writer, hasher: anytype, buffer: []u8) Hashed(@TypeOf(hasher)) {
17 var index: usize = 0;123 return .initHasher(w, hasher, buffer);
18 while (index != bytes.len) {124}
19 index += try self.write(bytes[index..]);125
126pub const failing: Writer = .{
127 .vtable = &.{
128 .drain = failingDrain,
129 .sendFile = failingSendFile,
130 },
131};
132
133/// Returns the contents not yet drained.
134pub fn buffered(w: *const Writer) []u8 {
135 return w.buffer[0..w.end];
136}
137
138pub fn countSplat(data: []const []const u8, splat: usize) usize {
139 var total: usize = 0;
140 for (data[0 .. data.len - 1]) |buf| total += buf.len;
141 total += data[data.len - 1].len * splat;
142 return total;
143}
144
145pub fn countSendFileLowerBound(n: usize, file_reader: *File.Reader, limit: Limit) ?usize {
146 const total: u64 = @min(@intFromEnum(limit), file_reader.getSize() catch return null);
147 return std.math.lossyCast(usize, total + n);
148}
149
150/// If the total number of bytes of `data` fits inside `unusedCapacitySlice`,
151/// this function is guaranteed to not fail, not call into `VTable`, and return
152/// the total bytes inside `data`.
153pub fn writeVec(w: *Writer, data: []const []const u8) Error!usize {
154 return writeSplat(w, data, 1);
155}
156
157/// If the number of bytes to write based on `data` and `splat` fits inside
158/// `unusedCapacitySlice`, this function is guaranteed to not fail, not call
159/// into `VTable`, and return the full number of bytes.
160pub fn writeSplat(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
161 assert(data.len > 0);
162 const buffer = w.buffer;
163 const count = countSplat(data, splat);
164 if (w.end + count > buffer.len) return w.vtable.drain(w, data, splat);
165 for (data[0 .. data.len - 1]) |bytes| {
166 @memcpy(buffer[w.end..][0..bytes.len], bytes);
167 w.end += bytes.len;
168 }
169 const pattern = data[data.len - 1];
170 switch (pattern.len) {
171 0 => {},
172 1 => {
173 @memset(buffer[w.end..][0..splat], pattern[0]);
174 w.end += splat;
175 },
176 else => for (0..splat) |_| {
177 @memcpy(buffer[w.end..][0..pattern.len], pattern);
178 w.end += pattern.len;
179 },
180 }
181 return count;
182}
183
184/// Returns how many bytes were consumed from `header` and `data`.
185pub fn writeSplatHeader(
186 w: *Writer,
187 header: []const u8,
188 data: []const []const u8,
189 splat: usize,
190) Error!usize {
191 const new_end = w.end + header.len;
192 if (new_end <= w.buffer.len) {
193 @memcpy(w.buffer[w.end..][0..header.len], header);
194 w.end = new_end;
195 return header.len + try writeSplat(w, data, splat);
20 }196 }
197 var vecs: [8][]const u8 = undefined; // Arbitrarily chosen size.
198 var i: usize = 1;
199 vecs[0] = header;
200 for (data[0 .. data.len - 1]) |buf| {
201 if (buf.len == 0) continue;
202 vecs[i] = buf;
203 i += 1;
204 if (vecs.len - i == 0) break;
205 }
206 const pattern = data[data.len - 1];
207 const new_splat = s: {
208 if (pattern.len == 0 or vecs.len - i == 0) break :s 1;
209 vecs[i] = pattern;
210 i += 1;
211 break :s splat;
212 };
213 return w.vtable.drain(w, vecs[0..i], new_splat);
21}214}
22215
23pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {216test "writeSplatHeader splatting avoids buffer aliasing temptation" {
24 return std.fmt.format(self, format, args);217 const initial_buf = try testing.allocator.alloc(u8, 8);
218 var aw: std.io.Writer.Allocating = .initOwnedSlice(testing.allocator, initial_buf);
219 defer aw.deinit();
220 // This test assumes 8 vector buffer in this function.
221 const n = try aw.writer.writeSplatHeader("header which is longer than buf ", &.{
222 "1", "2", "3", "4", "5", "6", "foo", "bar", "foo",
223 }, 3);
224 try testing.expectEqual(41, n);
225 try testing.expectEqualStrings(
226 "header which is longer than buf 123456foo",
227 aw.writer.buffered(),
228 );
25}229}
26230
27pub fn writeByte(self: Self, byte: u8) anyerror!void {231/// Drains all remaining buffered data.
28 const array = [1]u8{byte};232pub fn flush(w: *Writer) Error!void {
29 return self.writeAll(&array);233 return w.vtable.flush(w);
30}234}
31235
32pub fn writeByteNTimes(self: Self, byte: u8, n: usize) anyerror!void {236/// Repeatedly calls `VTable.drain` until `end` is zero.
33 var bytes: [256]u8 = undefined;237pub fn defaultFlush(w: *Writer) Error!void {
34 @memset(bytes[0..], byte);238 const drainFn = w.vtable.drain;
239 while (w.end != 0) _ = try drainFn(w, &.{""}, 1);
240}
35241
36 var remaining: usize = n;242/// Does nothing.
37 while (remaining > 0) {243pub fn noopFlush(w: *Writer) Error!void {
38 const to_write = @min(remaining, bytes.len);244 _ = w;
39 try self.writeAll(bytes[0..to_write]);245}
40 remaining -= to_write;246
247/// Calls `VTable.drain` but hides the last `preserve_length` bytes from the
248/// implementation, keeping them buffered.
249pub fn drainPreserve(w: *Writer, preserve_length: usize) Error!void {
250 const temp_end = w.end -| preserve_length;
251 const preserved = w.buffer[temp_end..w.end];
252 w.end = temp_end;
253 defer w.end += preserved.len;
254 assert(0 == try w.vtable.drain(w, &.{""}, 1));
255 assert(w.end <= temp_end + preserved.len);
256 @memmove(w.buffer[w.end..][0..preserved.len], preserved);
257}
258
259pub fn unusedCapacitySlice(w: *const Writer) []u8 {
260 return w.buffer[w.end..];
261}
262
263pub fn unusedCapacityLen(w: *const Writer) usize {
264 return w.buffer.len - w.end;
265}
266
267/// Asserts the provided buffer has total capacity enough for `len`.
268///
269/// Advances the buffer end position by `len`.
270pub fn writableArray(w: *Writer, comptime len: usize) Error!*[len]u8 {
271 const big_slice = try w.writableSliceGreedy(len);
272 advance(w, len);
273 return big_slice[0..len];
274}
275
276/// Asserts the provided buffer has total capacity enough for `len`.
277///
278/// Advances the buffer end position by `len`.
279pub fn writableSlice(w: *Writer, len: usize) Error![]u8 {
280 const big_slice = try w.writableSliceGreedy(len);
281 advance(w, len);
282 return big_slice[0..len];
283}
284
285/// Asserts the provided buffer has total capacity enough for `minimum_length`.
286///
287/// Does not `advance` the buffer end position.
288///
289/// If `minimum_length` is zero, this is equivalent to `unusedCapacitySlice`.
290pub fn writableSliceGreedy(w: *Writer, minimum_length: usize) Error![]u8 {
291 assert(w.buffer.len >= minimum_length);
292 while (w.buffer.len - w.end < minimum_length) {
293 assert(0 == try w.vtable.drain(w, &.{""}, 1));
294 } else {
295 @branchHint(.likely);
296 return w.buffer[w.end..];
41 }297 }
42}298}
43299
44pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) anyerror!void {300/// Asserts the provided buffer has total capacity enough for `minimum_length`
301/// and `preserve_length` combined.
302///
303/// Does not `advance` the buffer end position.
304///
305/// When draining the buffer, ensures that at least `preserve_length` bytes
306/// remain buffered.
307///
308/// If `preserve_length` is zero, this is equivalent to `writableSliceGreedy`.
309pub fn writableSliceGreedyPreserve(w: *Writer, preserve_length: usize, minimum_length: usize) Error![]u8 {
310 assert(w.buffer.len >= preserve_length + minimum_length);
311 while (w.buffer.len - w.end < minimum_length) {
312 try drainPreserve(w, preserve_length);
313 } else {
314 @branchHint(.likely);
315 return w.buffer[w.end..];
316 }
317}
318
319pub const WritableVectorIterator = struct {
320 first: []u8,
321 middle: []const []u8 = &.{},
322 last: []u8 = &.{},
323 index: usize = 0,
324
325 pub fn next(it: *WritableVectorIterator) ?[]u8 {
326 while (true) {
327 const i = it.index;
328 it.index += 1;
329 if (i == 0) {
330 if (it.first.len == 0) continue;
331 return it.first;
332 }
333 const middle_index = i - 1;
334 if (middle_index < it.middle.len) {
335 const middle = it.middle[middle_index];
336 if (middle.len == 0) continue;
337 return middle;
338 }
339 if (middle_index == it.middle.len) {
340 if (it.last.len == 0) continue;
341 return it.last;
342 }
343 return null;
344 }
345 }
346};
347
348pub const VectorWrapper = struct {
349 writer: Writer,
350 it: WritableVectorIterator,
351 /// Tracks whether the "writable vector" API was used.
352 used: bool = false,
353 pub const vtable: *const VTable = &unique_vtable_allocation;
354 /// This is intended to be constant but it must be a unique address for
355 /// `@fieldParentPtr` to work.
356 var unique_vtable_allocation: VTable = .{ .drain = fixedDrain };
357};
358
359pub fn writableVectorIterator(w: *Writer) Error!WritableVectorIterator {
360 if (w.vtable == VectorWrapper.vtable) {
361 const wrapper: *VectorWrapper = @fieldParentPtr("writer", w);
362 wrapper.used = true;
363 return wrapper.it;
364 }
365 return .{ .first = try writableSliceGreedy(w, 1) };
366}
367
368pub fn writableVectorPosix(w: *Writer, buffer: []std.posix.iovec, limit: Limit) Error![]std.posix.iovec {
369 var it = try writableVectorIterator(w);
45 var i: usize = 0;370 var i: usize = 0;
46 while (i < n) : (i += 1) {371 var remaining = limit;
47 try self.writeAll(bytes);372 while (it.next()) |full_buffer| {
373 if (!remaining.nonzero()) break;
374 if (buffer.len - i == 0) break;
375 const buf = remaining.slice(full_buffer);
376 if (buf.len == 0) continue;
377 buffer[i] = .{ .base = buf.ptr, .len = buf.len };
378 i += 1;
379 remaining = remaining.subtract(buf.len).?;
380 }
381 return buffer[0..i];
382}
383
384pub fn ensureUnusedCapacity(w: *Writer, n: usize) Error!void {
385 _ = try writableSliceGreedy(w, n);
386}
387
388pub fn undo(w: *Writer, n: usize) void {
389 w.end -= n;
390}
391
392/// After calling `writableSliceGreedy`, this function tracks how many bytes
393/// were written to it.
394///
395/// This is not needed when using `writableSlice` or `writableArray`.
396pub fn advance(w: *Writer, n: usize) void {
397 const new_end = w.end + n;
398 assert(new_end <= w.buffer.len);
399 w.end = new_end;
400}
401
402/// After calling `writableVector`, this function tracks how many bytes were
403/// written to it.
404pub fn advanceVector(w: *Writer, n: usize) usize {
405 return consume(w, n);
406}
407
408/// The `data` parameter is mutable because this function needs to mutate the
409/// fields in order to handle partial writes from `VTable.writeSplat`.
410pub fn writeVecAll(w: *Writer, data: [][]const u8) Error!void {
411 var index: usize = 0;
412 var truncate: usize = 0;
413 while (index < data.len) {
414 {
415 const untruncated = data[index];
416 data[index] = untruncated[truncate..];
417 defer data[index] = untruncated;
418 truncate += try w.writeVec(data[index..]);
419 }
420 while (index < data.len and truncate >= data[index].len) {
421 truncate -= data[index].len;
422 index += 1;
423 }
424 }
425}
426
427/// The `data` parameter is mutable because this function needs to mutate the
428/// fields in order to handle partial writes from `VTable.writeSplat`.
429pub fn writeSplatAll(w: *Writer, data: [][]const u8, splat: usize) Error!void {
430 var index: usize = 0;
431 var truncate: usize = 0;
432 var remaining_splat = splat;
433 while (index + 1 < data.len) {
434 {
435 const untruncated = data[index];
436 data[index] = untruncated[truncate..];
437 defer data[index] = untruncated;
438 truncate += try w.writeSplat(data[index..], remaining_splat);
439 }
440 while (truncate >= data[index].len) {
441 if (index + 1 < data.len) {
442 truncate -= data[index].len;
443 index += 1;
444 } else {
445 const last = data[data.len - 1];
446 remaining_splat -= @divExact(truncate, last.len);
447 while (remaining_splat > 0) {
448 const n = try w.writeSplat(data[data.len - 1 ..][0..1], remaining_splat);
449 remaining_splat -= @divExact(n, last.len);
450 }
451 return;
452 }
453 }
454 }
455}
456
457pub fn write(w: *Writer, bytes: []const u8) Error!usize {
458 if (w.end + bytes.len <= w.buffer.len) {
459 @branchHint(.likely);
460 @memcpy(w.buffer[w.end..][0..bytes.len], bytes);
461 w.end += bytes.len;
462 return bytes.len;
463 }
464 return w.vtable.drain(w, &.{bytes}, 1);
465}
466
467/// Asserts `buffer` capacity exceeds `preserve_length`.
468pub fn writePreserve(w: *Writer, preserve_length: usize, bytes: []const u8) Error!usize {
469 assert(preserve_length <= w.buffer.len);
470 if (w.end + bytes.len <= w.buffer.len) {
471 @branchHint(.likely);
472 @memcpy(w.buffer[w.end..][0..bytes.len], bytes);
473 w.end += bytes.len;
474 return bytes.len;
475 }
476 const temp_end = w.end -| preserve_length;
477 const preserved = w.buffer[temp_end..w.end];
478 w.end = temp_end;
479 defer w.end += preserved.len;
480 const n = try w.vtable.drain(w, &.{bytes}, 1);
481 assert(w.end <= temp_end + preserved.len);
482 @memmove(w.buffer[w.end..][0..preserved.len], preserved);
483 return n;
484}
485
486/// Calls `drain` as many times as necessary such that all of `bytes` are
487/// transferred.
488pub fn writeAll(w: *Writer, bytes: []const u8) Error!void {
489 var index: usize = 0;
490 while (index < bytes.len) index += try w.write(bytes[index..]);
491}
492
493/// Calls `drain` as many times as necessary such that all of `bytes` are
494/// transferred.
495///
496/// When draining the buffer, ensures that at least `preserve_length` bytes
497/// remain buffered.
498///
499/// Asserts `buffer` capacity exceeds `preserve_length`.
500pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) Error!void {
501 var index: usize = 0;
502 while (index < bytes.len) index += try w.writePreserve(preserve_length, bytes[index..]);
503}
504
505/// Renders fmt string with args, calling `writer` with slices of bytes.
506/// If `writer` returns an error, the error is returned from `format` and
507/// `writer` is not called again.
508///
509/// The format string must be comptime-known and may contain placeholders following
510/// this format:
511/// `{[argument][specifier]:[fill][alignment][width].[precision]}`
512///
513/// Above, each word including its surrounding [ and ] is a parameter which you have to replace with something:
514///
515/// - *argument* is either the numeric index or the field name of the argument that should be inserted
516/// - when using a field name, you are required to enclose the field name (an identifier) in square
517/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}
518/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
519/// - *fill* is a single byte which is used to pad formatted numbers.
520/// - *alignment* is one of the three bytes '<', '^', or '>' to make numbers
521/// left, center, or right-aligned, respectively.
522/// - Not all specifiers support alignment.
523/// - Alignment is not Unicode-aware; appropriate only when used with raw bytes or ASCII.
524/// - *width* is the total width of the field in bytes. This only applies to number formatting.
525/// - *precision* specifies how many decimals a formatted number should have.
526///
527/// Note that most of the parameters are optional and may be omitted. Also you
528/// can leave out separators like `:` and `.` when all parameters after the
529/// separator are omitted.
530///
531/// Only exception is the *fill* parameter. If a non-zero *fill* character is
532/// required at the same time as *width* is specified, one has to specify
533/// *alignment* as well, as otherwise the digit following `:` is interpreted as
534/// *width*, not *fill*.
535///
536/// The *specifier* has several options for types:
537/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes
538/// - `s`:
539/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
540/// - for slices of u8, print the entire slice as a string without zero-termination
541/// - `t`:
542/// - for enums and tagged unions: prints the tag name
543/// - for error sets: prints the error name
544/// - `b64`: output string as standard base64
545/// - `e`: output floating point value in scientific notation
546/// - `d`: output numeric value in decimal notation
547/// - `b`: output integer value in binary notation
548/// - `o`: output integer value in octal notation
549/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
550/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.
551/// - `D`: output nanoseconds as duration
552/// - `B`: output bytes in SI units (decimal)
553/// - `Bi`: output bytes in IEC units (binary)
554/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value.
555/// - `!`: 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.
556/// - `*`: output the address of the value instead of the value itself.
557/// - `any`: output a value of any type using its default format.
558/// - `f`: delegates to a method on the type named "format" with the signature `fn (*Writer, args: anytype) Writer.Error!void`.
559///
560/// A user type may be a `struct`, `vector`, `union` or `enum` type.
561///
562/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
563pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
564 const ArgsType = @TypeOf(args);
565 const args_type_info = @typeInfo(ArgsType);
566 if (args_type_info != .@"struct") {
567 @compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType));
568 }
569
570 const fields_info = args_type_info.@"struct".fields;
571 const max_format_args = @typeInfo(std.fmt.ArgSetType).int.bits;
572 if (fields_info.len > max_format_args) {
573 @compileError("32 arguments max are supported per format call");
574 }
575
576 @setEvalBranchQuota(fmt.len * 1000);
577 comptime var arg_state: std.fmt.ArgState = .{ .args_len = fields_info.len };
578 comptime var i = 0;
579 comptime var literal: []const u8 = "";
580 inline while (true) {
581 const start_index = i;
582
583 inline while (i < fmt.len) : (i += 1) {
584 switch (fmt[i]) {
585 '{', '}' => break,
586 else => {},
587 }
588 }
589
590 comptime var end_index = i;
591 comptime var unescape_brace = false;
592
593 // Handle {{ and }}, those are un-escaped as single braces
594 if (i + 1 < fmt.len and fmt[i + 1] == fmt[i]) {
595 unescape_brace = true;
596 // Make the first brace part of the literal...
597 end_index += 1;
598 // ...and skip both
599 i += 2;
600 }
601
602 literal = literal ++ fmt[start_index..end_index];
603
604 // We've already skipped the other brace, restart the loop
605 if (unescape_brace) continue;
606
607 // Write out the literal
608 if (literal.len != 0) {
609 try w.writeAll(literal);
610 literal = "";
611 }
612
613 if (i >= fmt.len) break;
614
615 if (fmt[i] == '}') {
616 @compileError("missing opening {");
617 }
618
619 // Get past the {
620 comptime assert(fmt[i] == '{');
621 i += 1;
622
623 const fmt_begin = i;
624 // Find the closing brace
625 inline while (i < fmt.len and fmt[i] != '}') : (i += 1) {}
626 const fmt_end = i;
627
628 if (i >= fmt.len) {
629 @compileError("missing closing }");
630 }
631
632 // Get past the }
633 comptime assert(fmt[i] == '}');
634 i += 1;
635
636 const placeholder_array = fmt[fmt_begin..fmt_end].*;
637 const placeholder = comptime std.fmt.Placeholder.parse(&placeholder_array);
638 const arg_pos = comptime switch (placeholder.arg) {
639 .none => null,
640 .number => |pos| pos,
641 .named => |arg_name| std.meta.fieldIndex(ArgsType, arg_name) orelse
642 @compileError("no argument with name '" ++ arg_name ++ "'"),
643 };
644
645 const width = switch (placeholder.width) {
646 .none => null,
647 .number => |v| v,
648 .named => |arg_name| blk: {
649 const arg_i = comptime std.meta.fieldIndex(ArgsType, arg_name) orelse
650 @compileError("no argument with name '" ++ arg_name ++ "'");
651 _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments");
652 break :blk @field(args, arg_name);
653 },
654 };
655
656 const precision = switch (placeholder.precision) {
657 .none => null,
658 .number => |v| v,
659 .named => |arg_name| blk: {
660 const arg_i = comptime std.meta.fieldIndex(ArgsType, arg_name) orelse
661 @compileError("no argument with name '" ++ arg_name ++ "'");
662 _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments");
663 break :blk @field(args, arg_name);
664 },
665 };
666
667 const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse
668 @compileError("too few arguments");
669
670 try w.printValue(
671 placeholder.specifier_arg,
672 .{
673 .fill = placeholder.fill,
674 .alignment = placeholder.alignment,
675 .width = width,
676 .precision = precision,
677 },
678 @field(args, fields_info[arg_to_print].name),
679 std.options.fmt_max_depth,
680 );
681 }
682
683 if (comptime arg_state.hasUnusedArgs()) {
684 const missing_count = arg_state.args_len - @popCount(arg_state.used_args);
685 switch (missing_count) {
686 0 => unreachable,
687 1 => @compileError("unused argument in '" ++ fmt ++ "'"),
688 else => @compileError(std.fmt.comptimePrint("{d}", .{missing_count}) ++ " unused arguments in '" ++ fmt ++ "'"),
689 }
690 }
691}
692
693/// Calls `drain` as many times as necessary such that `byte` is transferred.
694pub fn writeByte(w: *Writer, byte: u8) Error!void {
695 while (w.buffer.len - w.end == 0) {
696 const n = try w.vtable.drain(w, &.{&.{byte}}, 1);
697 if (n > 0) return;
698 } else {
699 @branchHint(.likely);
700 w.buffer[w.end] = byte;
701 w.end += 1;
702 }
703}
704
705/// When draining the buffer, ensures that at least `preserve_length` bytes
706/// remain buffered.
707pub fn writeBytePreserve(w: *Writer, preserve_length: usize, byte: u8) Error!void {
708 while (w.buffer.len - w.end == 0) {
709 try drainPreserve(w, preserve_length);
710 } else {
711 @branchHint(.likely);
712 w.buffer[w.end] = byte;
713 w.end += 1;
714 }
715}
716
717/// Writes the same byte many times, performing the underlying write call as
718/// many times as necessary.
719pub fn splatByteAll(w: *Writer, byte: u8, n: usize) Error!void {
720 var remaining: usize = n;
721 while (remaining > 0) remaining -= try w.splatByte(byte, remaining);
722}
723
724/// Writes the same byte many times, allowing short writes.
725///
726/// Does maximum of one underlying `VTable.drain`.
727pub fn splatByte(w: *Writer, byte: u8, n: usize) Error!usize {
728 return writeSplat(w, &.{&.{byte}}, n);
729}
730
731/// Writes the same slice many times, performing the underlying write call as
732/// many times as necessary.
733pub fn splatBytesAll(w: *Writer, bytes: []const u8, splat: usize) Error!void {
734 var remaining_bytes: usize = bytes.len * splat;
735 remaining_bytes -= try w.splatBytes(bytes, splat);
736 while (remaining_bytes > 0) {
737 const leftover = remaining_bytes % bytes.len;
738 const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover ..], bytes };
739 remaining_bytes -= try w.splatBytes(&buffers, splat);
48 }740 }
49}741}
50742
51pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) anyerror!void {743/// Writes the same slice many times, allowing short writes.
744///
745/// Does maximum of one underlying `VTable.writeSplat`.
746pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize {
747 return writeSplat(w, &.{bytes}, n);
748}
749
750/// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes.
751pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void {
52 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;752 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
53 mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);753 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
54 return self.writeAll(&bytes);754 return w.writeAll(&bytes);
55}755}
56756
57pub fn writeStruct(self: Self, value: anytype) anyerror!void {757pub fn writeStruct(w: *Writer, value: anytype) Error!void {
58 // Only extern and packed structs have defined in-memory layout.758 // Only extern and packed structs have defined in-memory layout.
59 comptime assert(@typeInfo(@TypeOf(value)).@"struct".layout != .auto);759 comptime assert(@typeInfo(@TypeOf(value)).@"struct".layout != .auto);
60 return self.writeAll(mem.asBytes(&value));760 return w.writeAll(std.mem.asBytes(&value));
761}
762
763/// The function is inline to avoid the dead code in case `endian` is
764/// comptime-known and matches host endianness.
765/// TODO: make sure this value is not a reference type
766pub inline fn writeStructEndian(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void {
767 switch (@typeInfo(@TypeOf(value))) {
768 .@"struct" => |info| switch (info.layout) {
769 .auto => @compileError("ill-defined memory layout"),
770 .@"extern" => {
771 if (native_endian == endian) {
772 return w.writeStruct(value);
773 } else {
774 var copy = value;
775 std.mem.byteSwapAllFields(@TypeOf(value), &copy);
776 return w.writeStruct(copy);
777 }
778 },
779 .@"packed" => {
780 return writeInt(w, info.backing_integer.?, @bitCast(value), endian);
781 },
782 },
783 else => @compileError("not a struct"),
784 }
61}785}
62786
63pub fn writeStructEndian(self: Self, value: anytype, endian: std.builtin.Endian) anyerror!void {787pub inline fn writeSliceEndian(
64 // TODO: make sure this value is not a reference type788 w: *Writer,
789 Elem: type,
790 slice: []const Elem,
791 endian: std.builtin.Endian,
792) Error!void {
65 if (native_endian == endian) {793 if (native_endian == endian) {
66 return self.writeStruct(value);794 return writeAll(w, @ptrCast(slice));
795 } else {
796 return w.writeArraySwap(w, Elem, slice);
797 }
798}
799
800/// Unlike `writeSplat` and `writeVec`, this function will call into `VTable`
801/// even if there is enough buffer capacity for the file contents.
802///
803/// Although it would be possible to eliminate `error.Unimplemented` from the
804/// error set by reading directly into the buffer in such case, this is not
805/// done because it is more efficient to do it higher up the call stack so that
806/// the error does not occur with each write.
807///
808/// See `sendFileReading` for an alternative that does not have
809/// `error.Unimplemented` in the error set.
810pub fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
811 return w.vtable.sendFile(w, file_reader, limit);
812}
813
814/// Returns how many bytes from `header` and `file_reader` were consumed.
815pub fn sendFileHeader(
816 w: *Writer,
817 header: []const u8,
818 file_reader: *File.Reader,
819 limit: Limit,
820) FileError!usize {
821 const new_end = w.end + header.len;
822 if (new_end <= w.buffer.len) {
823 @memcpy(w.buffer[w.end..][0..header.len], header);
824 w.end = new_end;
825 return header.len + try w.vtable.sendFile(w, file_reader, limit);
826 }
827 const buffered_contents = limit.slice(file_reader.interface.buffered());
828 const n = try w.vtable.drain(w, &.{ header, buffered_contents }, 1);
829 file_reader.interface.toss(n - header.len);
830 return n;
831}
832
833/// Asserts nonzero buffer capacity.
834pub fn sendFileReading(w: *Writer, file_reader: *File.Reader, limit: Limit) FileReadingError!usize {
835 const dest = limit.slice(try w.writableSliceGreedy(1));
836 const n = try file_reader.read(dest);
837 w.advance(n);
838 return n;
839}
840
841/// Number of bytes logically written is returned. This excludes bytes from
842/// `buffer` because they have already been logically written.
843pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllError!usize {
844 var remaining = @intFromEnum(limit);
845 while (remaining > 0) {
846 const n = sendFile(w, file_reader, .limited(remaining)) catch |err| switch (err) {
847 error.EndOfStream => break,
848 error.Unimplemented => {
849 file_reader.mode = file_reader.mode.toReading();
850 remaining -= try w.sendFileReadingAll(file_reader, .limited(remaining));
851 break;
852 },
853 else => |e| return e,
854 };
855 remaining -= n;
856 }
857 return @intFromEnum(limit) - remaining;
858}
859
860/// Equivalent to `sendFileAll` but uses direct `pread` and `read` calls on
861/// `file` rather than `sendFile`. This is generally used as a fallback when
862/// the underlying implementation returns `error.Unimplemented`, which is why
863/// that error code does not appear in this function's error set.
864///
865/// Asserts nonzero buffer capacity.
866pub fn sendFileReadingAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllError!usize {
867 var remaining = @intFromEnum(limit);
868 while (remaining > 0) {
869 remaining -= sendFileReading(w, file_reader, .limited(remaining)) catch |err| switch (err) {
870 error.EndOfStream => break,
871 else => |e| return e,
872 };
873 }
874 return @intFromEnum(limit) - remaining;
875}
876
877pub fn alignBuffer(
878 w: *Writer,
879 buffer: []const u8,
880 width: usize,
881 alignment: std.fmt.Alignment,
882 fill: u8,
883) Error!void {
884 const padding = if (buffer.len < width) width - buffer.len else 0;
885 if (padding == 0) {
886 @branchHint(.likely);
887 return w.writeAll(buffer);
888 }
889 switch (alignment) {
890 .left => {
891 try w.writeAll(buffer);
892 try w.splatByteAll(fill, padding);
893 },
894 .center => {
895 const left_padding = padding / 2;
896 const right_padding = (padding + 1) / 2;
897 try w.splatByteAll(fill, left_padding);
898 try w.writeAll(buffer);
899 try w.splatByteAll(fill, right_padding);
900 },
901 .right => {
902 try w.splatByteAll(fill, padding);
903 try w.writeAll(buffer);
904 },
905 }
906}
907
908pub fn alignBufferOptions(w: *Writer, buffer: []const u8, options: std.fmt.Options) Error!void {
909 return w.alignBuffer(buffer, options.width orelse buffer.len, options.alignment, options.fill);
910}
911
912pub fn printAddress(w: *Writer, value: anytype) Error!void {
913 const T = @TypeOf(value);
914 switch (@typeInfo(T)) {
915 .pointer => |info| {
916 try w.writeAll(@typeName(info.child) ++ "@");
917 const int = if (info.size == .slice) @intFromPtr(value.ptr) else @intFromPtr(value);
918 return w.printInt(int, 16, .lower, .{});
919 },
920 .optional => |info| {
921 if (@typeInfo(info.child) == .pointer) {
922 try w.writeAll(@typeName(info.child) ++ "@");
923 try w.printInt(@intFromPtr(value), 16, .lower, .{});
924 return;
925 }
926 },
927 else => {},
928 }
929
930 @compileError("cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
931}
932
933pub fn printValue(
934 w: *Writer,
935 comptime fmt: []const u8,
936 options: std.fmt.Options,
937 value: anytype,
938 max_depth: usize,
939) Error!void {
940 const T = @TypeOf(value);
941
942 switch (fmt.len) {
943 1 => switch (fmt[0]) {
944 '*' => return w.printAddress(value),
945 'f' => return value.format(w),
946 'd' => switch (@typeInfo(T)) {
947 .float, .comptime_float => return printFloat(w, value, options.toNumber(.decimal, .lower)),
948 .int, .comptime_int => return printInt(w, value, 10, .lower, options),
949 .@"struct" => return value.formatNumber(w, options.toNumber(.decimal, .lower)),
950 .@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options),
951 .vector => return printVector(w, fmt, options, value, max_depth),
952 else => invalidFmtError(fmt, value),
953 },
954 'c' => return w.printAsciiChar(value, options),
955 'u' => return w.printUnicodeCodepoint(value),
956 'b' => switch (@typeInfo(T)) {
957 .int, .comptime_int => return printInt(w, value, 2, .lower, options),
958 .@"enum" => return printInt(w, @intFromEnum(value), 2, .lower, options),
959 .@"struct" => return value.formatNumber(w, options.toNumber(.binary, .lower)),
960 .vector => return printVector(w, fmt, options, value, max_depth),
961 else => invalidFmtError(fmt, value),
962 },
963 'o' => switch (@typeInfo(T)) {
964 .int, .comptime_int => return printInt(w, value, 8, .lower, options),
965 .@"enum" => return printInt(w, @intFromEnum(value), 8, .lower, options),
966 .@"struct" => return value.formatNumber(w, options.toNumber(.octal, .lower)),
967 .vector => return printVector(w, fmt, options, value, max_depth),
968 else => invalidFmtError(fmt, value),
969 },
970 'x' => switch (@typeInfo(T)) {
971 .float, .comptime_float => return printFloatHexOptions(w, value, options.toNumber(.hex, .lower)),
972 .int, .comptime_int => return printInt(w, value, 16, .lower, options),
973 .@"enum" => return printInt(w, @intFromEnum(value), 16, .lower, options),
974 .@"struct" => return value.formatNumber(w, options.toNumber(.hex, .lower)),
975 .pointer => |info| switch (info.size) {
976 .one, .slice => {
977 const slice: []const u8 = value;
978 optionsForbidden(options);
979 return printHex(w, slice, .lower);
980 },
981 .many, .c => {
982 const slice: [:0]const u8 = std.mem.span(value);
983 optionsForbidden(options);
984 return printHex(w, slice, .lower);
985 },
986 },
987 .array => {
988 const slice: []const u8 = &value;
989 optionsForbidden(options);
990 return printHex(w, slice, .lower);
991 },
992 .vector => return printVector(w, fmt, options, value, max_depth),
993 else => invalidFmtError(fmt, value),
994 },
995 'X' => switch (@typeInfo(T)) {
996 .float, .comptime_float => return printFloatHexOptions(w, value, options.toNumber(.hex, .lower)),
997 .int, .comptime_int => return printInt(w, value, 16, .upper, options),
998 .@"enum" => return printInt(w, @intFromEnum(value), 16, .upper, options),
999 .@"struct" => return value.formatNumber(w, options.toNumber(.hex, .upper)),
1000 .pointer => |info| switch (info.size) {
1001 .one, .slice => {
1002 const slice: []const u8 = value;
1003 optionsForbidden(options);
1004 return printHex(w, slice, .upper);
1005 },
1006 .many, .c => {
1007 const slice: [:0]const u8 = std.mem.span(value);
1008 optionsForbidden(options);
1009 return printHex(w, slice, .upper);
1010 },
1011 },
1012 .array => {
1013 const slice: []const u8 = &value;
1014 optionsForbidden(options);
1015 return printHex(w, slice, .upper);
1016 },
1017 .vector => return printVector(w, fmt, options, value, max_depth),
1018 else => invalidFmtError(fmt, value),
1019 },
1020 's' => switch (@typeInfo(T)) {
1021 .pointer => |info| switch (info.size) {
1022 .one, .slice => {
1023 const slice: []const u8 = value;
1024 return w.alignBufferOptions(slice, options);
1025 },
1026 .many, .c => {
1027 const slice: [:0]const u8 = std.mem.span(value);
1028 return w.alignBufferOptions(slice, options);
1029 },
1030 },
1031 .array => {
1032 const slice: []const u8 = &value;
1033 return w.alignBufferOptions(slice, options);
1034 },
1035 else => invalidFmtError(fmt, value),
1036 },
1037 'B' => switch (@typeInfo(T)) {
1038 .int, .comptime_int => return w.printByteSize(value, .decimal, options),
1039 .@"struct" => return value.formatByteSize(w, .decimal),
1040 else => invalidFmtError(fmt, value),
1041 },
1042 'D' => switch (@typeInfo(T)) {
1043 .int, .comptime_int => return w.printDuration(value, options),
1044 .@"struct" => return value.formatDuration(w),
1045 else => invalidFmtError(fmt, value),
1046 },
1047 'e' => switch (@typeInfo(T)) {
1048 .float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .lower)),
1049 .@"struct" => return value.formatNumber(w, options.toNumber(.scientific, .lower)),
1050 else => invalidFmtError(fmt, value),
1051 },
1052 'E' => switch (@typeInfo(T)) {
1053 .float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .upper)),
1054 .@"struct" => return value.formatNumber(w, options.toNumber(.scientific, .upper)),
1055 else => invalidFmtError(fmt, value),
1056 },
1057 't' => switch (@typeInfo(T)) {
1058 .error_set => return w.writeAll(@errorName(value)),
1059 .@"enum", .@"union" => return w.writeAll(@tagName(value)),
1060 else => invalidFmtError(fmt, value),
1061 },
1062 else => {},
1063 },
1064 2 => switch (fmt[0]) {
1065 'B' => switch (fmt[1]) {
1066 'i' => switch (@typeInfo(T)) {
1067 .int, .comptime_int => return w.printByteSize(value, .binary, options),
1068 .@"struct" => return value.formatByteSize(w, .binary),
1069 else => invalidFmtError(fmt, value),
1070 },
1071 else => {},
1072 },
1073 else => {},
1074 },
1075 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') switch (@typeInfo(T)) {
1076 .pointer => |info| switch (info.size) {
1077 .one, .slice => {
1078 const slice: []const u8 = value;
1079 optionsForbidden(options);
1080 return w.printBase64(slice);
1081 },
1082 .many, .c => {
1083 const slice: [:0]const u8 = std.mem.span(value);
1084 optionsForbidden(options);
1085 return w.printBase64(slice);
1086 },
1087 },
1088 .array => {
1089 const slice: []const u8 = &value;
1090 optionsForbidden(options);
1091 return w.printBase64(slice);
1092 },
1093 else => invalidFmtError(fmt, value),
1094 },
1095 else => {},
1096 }
1097
1098 const is_any = comptime std.mem.eql(u8, fmt, ANY);
1099 if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) {
1100 // after 0.15.0 is tagged, delete this compile error and its condition
1101 @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
1102 }
1103
1104 switch (@typeInfo(T)) {
1105 .float, .comptime_float => {
1106 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1107 return printFloat(w, value, options.toNumber(.decimal, .lower));
1108 },
1109 .int, .comptime_int => {
1110 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1111 return printInt(w, value, 10, .lower, options);
1112 },
1113 .bool => {
1114 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1115 const string: []const u8 = if (value) "true" else "false";
1116 return w.alignBufferOptions(string, options);
1117 },
1118 .void => {
1119 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1120 return w.alignBufferOptions("void", options);
1121 },
1122 .optional => {
1123 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?')
1124 stripOptionalOrErrorUnionSpec(fmt)
1125 else if (is_any)
1126 ANY
1127 else
1128 @compileError("cannot print optional without a specifier (i.e. {?} or {any})");
1129 if (value) |payload| {
1130 return w.printValue(remaining_fmt, options, payload, max_depth);
1131 } else {
1132 return w.alignBufferOptions("null", options);
1133 }
1134 },
1135 .error_union => {
1136 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '!')
1137 stripOptionalOrErrorUnionSpec(fmt)
1138 else if (is_any)
1139 ANY
1140 else
1141 @compileError("cannot print error union without a specifier (i.e. {!} or {any})");
1142 if (value) |payload| {
1143 return w.printValue(remaining_fmt, options, payload, max_depth);
1144 } else |err| {
1145 return w.printValue("", options, err, max_depth);
1146 }
1147 },
1148 .error_set => {
1149 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1150 optionsForbidden(options);
1151 return printErrorSet(w, value);
1152 },
1153 .@"enum" => |info| {
1154 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1155 optionsForbidden(options);
1156 if (info.is_exhaustive) {
1157 return printEnumExhaustive(w, value);
1158 } else {
1159 return printEnumNonexhaustive(w, value);
1160 }
1161 },
1162 .@"union" => |info| {
1163 if (!is_any) {
1164 if (fmt.len != 0) invalidFmtError(fmt, value);
1165 return printValue(w, ANY, options, value, max_depth);
1166 }
1167 if (max_depth == 0) {
1168 try w.writeAll(".{ ... }");
1169 return;
1170 }
1171 if (info.tag_type) |UnionTagType| {
1172 try w.writeAll(".{ .");
1173 try w.writeAll(@tagName(@as(UnionTagType, value)));
1174 try w.writeAll(" = ");
1175 inline for (info.fields) |u_field| {
1176 if (value == @field(UnionTagType, u_field.name)) {
1177 try w.printValue(ANY, options, @field(value, u_field.name), max_depth - 1);
1178 }
1179 }
1180 try w.writeAll(" }");
1181 } else switch (info.layout) {
1182 .auto => {
1183 return w.writeAll(".{ ... }");
1184 },
1185 .@"extern", .@"packed" => {
1186 if (info.fields.len == 0) return w.writeAll(".{}");
1187 try w.writeAll(".{ ");
1188 inline for (info.fields) |field| {
1189 try w.writeByte('.');
1190 try w.writeAll(field.name);
1191 try w.writeAll(" = ");
1192 try w.printValue(ANY, options, @field(value, field.name), max_depth - 1);
1193 (try w.writableArray(2)).* = ", ".*;
1194 }
1195 w.buffer[w.end - 2 ..][0..2].* = " }".*;
1196 },
1197 }
1198 },
1199 .@"struct" => |info| {
1200 if (!is_any) {
1201 if (fmt.len != 0) invalidFmtError(fmt, value);
1202 return printValue(w, ANY, options, value, max_depth);
1203 }
1204 if (info.is_tuple) {
1205 // Skip the type and field names when formatting tuples.
1206 if (max_depth == 0) {
1207 try w.writeAll(".{ ... }");
1208 return;
1209 }
1210 try w.writeAll(".{");
1211 inline for (info.fields, 0..) |f, i| {
1212 if (i == 0) {
1213 try w.writeAll(" ");
1214 } else {
1215 try w.writeAll(", ");
1216 }
1217 try w.printValue(ANY, options, @field(value, f.name), max_depth - 1);
1218 }
1219 try w.writeAll(" }");
1220 return;
1221 }
1222 if (max_depth == 0) {
1223 try w.writeAll(".{ ... }");
1224 return;
1225 }
1226 try w.writeAll(".{");
1227 inline for (info.fields, 0..) |f, i| {
1228 if (i == 0) {
1229 try w.writeAll(" .");
1230 } else {
1231 try w.writeAll(", .");
1232 }
1233 try w.writeAll(f.name);
1234 try w.writeAll(" = ");
1235 try w.printValue(ANY, options, @field(value, f.name), max_depth - 1);
1236 }
1237 try w.writeAll(" }");
1238 },
1239 .pointer => |ptr_info| switch (ptr_info.size) {
1240 .one => switch (@typeInfo(ptr_info.child)) {
1241 .array => |array_info| return w.printValue(fmt, options, @as([]const array_info.child, value), max_depth),
1242 .@"enum", .@"union", .@"struct" => return w.printValue(fmt, options, value.*, max_depth),
1243 else => {
1244 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
1245 try w.writeVecAll(&buffers);
1246 try w.printInt(@intFromPtr(value), 16, .lower, options);
1247 return;
1248 },
1249 },
1250 .many, .c => {
1251 if (!is_any) @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
1252 optionsForbidden(options);
1253 try w.printAddress(value);
1254 },
1255 .slice => {
1256 if (!is_any)
1257 @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})");
1258 if (max_depth == 0) return w.writeAll("{ ... }");
1259 try w.writeAll("{ ");
1260 for (value, 0..) |elem, i| {
1261 try w.printValue(fmt, options, elem, max_depth - 1);
1262 if (i != value.len - 1) {
1263 try w.writeAll(", ");
1264 }
1265 }
1266 try w.writeAll(" }");
1267 },
1268 },
1269 .array => {
1270 if (!is_any) @compileError("cannot format array without a specifier (i.e. {s} or {any})");
1271 if (max_depth == 0) return w.writeAll("{ ... }");
1272 try w.writeAll("{ ");
1273 for (value, 0..) |elem, i| {
1274 try w.printValue(fmt, options, elem, max_depth - 1);
1275 if (i < value.len - 1) {
1276 try w.writeAll(", ");
1277 }
1278 }
1279 try w.writeAll(" }");
1280 },
1281 .vector => {
1282 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1283 return printVector(w, fmt, options, value, max_depth);
1284 },
1285 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),
1286 .type => {
1287 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1288 return w.alignBufferOptions(@typeName(value), options);
1289 },
1290 .enum_literal => {
1291 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1292 optionsForbidden(options);
1293 var vecs: [2][]const u8 = .{ ".", @tagName(value) };
1294 return w.writeVecAll(&vecs);
1295 },
1296 .null => {
1297 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1298 return w.alignBufferOptions("null", options);
1299 },
1300 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
1301 }
1302}
1303
1304fn optionsForbidden(options: std.fmt.Options) void {
1305 assert(options.precision == null);
1306 assert(options.width == null);
1307}
1308
1309fn printErrorSet(w: *Writer, error_set: anyerror) Error!void {
1310 var vecs: [2][]const u8 = .{ "error.", @errorName(error_set) };
1311 try w.writeVecAll(&vecs);
1312}
1313
1314fn printEnumExhaustive(w: *Writer, value: anytype) Error!void {
1315 var vecs: [2][]const u8 = .{ ".", @tagName(value) };
1316 try w.writeVecAll(&vecs);
1317}
1318
1319fn printEnumNonexhaustive(w: *Writer, value: anytype) Error!void {
1320 if (std.enums.tagName(@TypeOf(value), value)) |tag_name| {
1321 var vecs: [2][]const u8 = .{ ".", tag_name };
1322 try w.writeVecAll(&vecs);
1323 return;
1324 }
1325 try w.writeAll("@enumFromInt(");
1326 try w.printInt(@intFromEnum(value), 10, .lower, .{});
1327 try w.writeByte(')');
1328}
1329
1330pub fn printVector(
1331 w: *Writer,
1332 comptime fmt: []const u8,
1333 options: std.fmt.Options,
1334 value: anytype,
1335 max_depth: usize,
1336) Error!void {
1337 const len = @typeInfo(@TypeOf(value)).vector.len;
1338 if (max_depth == 0) return w.writeAll("{ ... }");
1339 try w.writeAll("{ ");
1340 inline for (0..len) |i| {
1341 try w.printValue(fmt, options, value[i], max_depth - 1);
1342 if (i < len - 1) try w.writeAll(", ");
1343 }
1344 try w.writeAll(" }");
1345}
1346
1347// A wrapper around `printIntAny` to avoid the generic explosion of this
1348// function by funneling smaller integer types through `isize` and `usize`.
1349pub inline fn printInt(
1350 w: *Writer,
1351 value: anytype,
1352 base: u8,
1353 case: std.fmt.Case,
1354 options: std.fmt.Options,
1355) Error!void {
1356 switch (@TypeOf(value)) {
1357 isize, usize => {},
1358 comptime_int => {
1359 if (comptime std.math.cast(usize, value)) |x| return printIntAny(w, x, base, case, options);
1360 if (comptime std.math.cast(isize, value)) |x| return printIntAny(w, x, base, case, options);
1361 const Int = std.math.IntFittingRange(value, value);
1362 return printIntAny(w, @as(Int, value), base, case, options);
1363 },
1364 else => switch (@typeInfo(@TypeOf(value)).int.signedness) {
1365 .signed => if (std.math.cast(isize, value)) |x| return printIntAny(w, x, base, case, options),
1366 .unsigned => if (std.math.cast(usize, value)) |x| return printIntAny(w, x, base, case, options),
1367 },
1368 }
1369 return printIntAny(w, value, base, case, options);
1370}
1371
1372/// In general, prefer `printInt` to avoid generic explosion. However this
1373/// function may be used when optimal codegen for a particular integer type is
1374/// desired.
1375pub fn printIntAny(
1376 w: *Writer,
1377 value: anytype,
1378 base: u8,
1379 case: std.fmt.Case,
1380 options: std.fmt.Options,
1381) Error!void {
1382 assert(base >= 2);
1383 const value_info = @typeInfo(@TypeOf(value)).int;
1384
1385 // The type must have the same size as `base` or be wider in order for the
1386 // division to work
1387 const min_int_bits = comptime @max(value_info.bits, 8);
1388 const MinInt = std.meta.Int(.unsigned, min_int_bits);
1389
1390 const abs_value = @abs(value);
1391 // The worst case in terms of space needed is base 2, plus 1 for the sign
1392 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
1393
1394 var a: MinInt = abs_value;
1395 var index: usize = buf.len;
1396
1397 if (base == 10) {
1398 while (a >= 100) : (a = @divTrunc(a, 100)) {
1399 index -= 2;
1400 buf[index..][0..2].* = std.fmt.digits2(@intCast(a % 100));
1401 }
1402
1403 if (a < 10) {
1404 index -= 1;
1405 buf[index] = '0' + @as(u8, @intCast(a));
1406 } else {
1407 index -= 2;
1408 buf[index..][0..2].* = std.fmt.digits2(@intCast(a));
1409 }
1410 } else {
1411 while (true) {
1412 const digit = a % base;
1413 index -= 1;
1414 buf[index] = std.fmt.digitToChar(@intCast(digit), case);
1415 a /= base;
1416 if (a == 0) break;
1417 }
1418 }
1419
1420 if (value_info.signedness == .signed) {
1421 if (value < 0) {
1422 // Negative integer
1423 index -= 1;
1424 buf[index] = '-';
1425 } else if (options.width == null or options.width.? == 0) {
1426 // Positive integer, omit the plus sign
1427 } else {
1428 // Positive integer
1429 index -= 1;
1430 buf[index] = '+';
1431 }
1432 }
1433
1434 return w.alignBufferOptions(buf[index..], options);
1435}
1436
1437pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void {
1438 return w.alignBufferOptions(@as(*const [1]u8, &c), options);
1439}
1440
1441pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void {
1442 return w.alignBufferOptions(bytes, options);
1443}
1444
1445pub fn printUnicodeCodepoint(w: *Writer, c: u21) Error!void {
1446 var buf: [4]u8 = undefined;
1447 const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) {
1448 error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: {
1449 buf[0..3].* = std.unicode.replacement_character_utf8;
1450 break :l 3;
1451 },
1452 };
1453 return w.writeAll(buf[0..len]);
1454}
1455
1456/// Uses a larger stack buffer; asserts mode is decimal or scientific.
1457pub fn printFloat(w: *Writer, value: anytype, options: std.fmt.Number) Error!void {
1458 const mode: std.fmt.float.Mode = switch (options.mode) {
1459 .decimal => .decimal,
1460 .scientific => .scientific,
1461 .binary, .octal, .hex => unreachable,
1462 };
1463 var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined;
1464 const s = std.fmt.float.render(&buf, value, .{
1465 .mode = mode,
1466 .precision = options.precision,
1467 }) catch |err| switch (err) {
1468 error.BufferTooSmall => "(float)",
1469 };
1470 return w.alignBuffer(s, options.width orelse s.len, options.alignment, options.fill);
1471}
1472
1473/// Uses a smaller stack buffer; asserts mode is not decimal or scientific.
1474pub fn printFloatHexOptions(w: *Writer, value: anytype, options: std.fmt.Number) Error!void {
1475 var buf: [50]u8 = undefined; // for aligning
1476 var sub_writer: Writer = .fixed(&buf);
1477 switch (options.mode) {
1478 .decimal => unreachable,
1479 .scientific => unreachable,
1480 .binary => @panic("TODO"),
1481 .octal => @panic("TODO"),
1482 .hex => {},
1483 }
1484 printFloatHex(&sub_writer, value, options.case, options.precision) catch unreachable; // buf is large enough
1485
1486 const printed = sub_writer.buffered();
1487 return w.alignBuffer(printed, options.width orelse printed.len, options.alignment, options.fill);
1488}
1489
1490pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void {
1491 if (std.math.signbit(value)) try w.writeByte('-');
1492 if (std.math.isNan(value)) return w.writeAll(switch (case) {
1493 .lower => "nan",
1494 .upper => "NAN",
1495 });
1496 if (std.math.isInf(value)) return w.writeAll(switch (case) {
1497 .lower => "inf",
1498 .upper => "INF",
1499 });
1500
1501 const T = @TypeOf(value);
1502 const TU = std.meta.Int(.unsigned, @bitSizeOf(T));
1503
1504 const mantissa_bits = std.math.floatMantissaBits(T);
1505 const fractional_bits = std.math.floatFractionalBits(T);
1506 const exponent_bits = std.math.floatExponentBits(T);
1507 const mantissa_mask = (1 << mantissa_bits) - 1;
1508 const exponent_mask = (1 << exponent_bits) - 1;
1509 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
1510
1511 const as_bits: TU = @bitCast(value);
1512 var mantissa = as_bits & mantissa_mask;
1513 var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask));
1514
1515 const is_denormal = exponent == 0 and mantissa != 0;
1516 const is_zero = exponent == 0 and mantissa == 0;
1517
1518 if (is_zero) {
1519 // Handle this case here to simplify the logic below.
1520 try w.writeAll("0x0");
1521 if (opt_precision) |precision| {
1522 if (precision > 0) {
1523 try w.writeAll(".");
1524 try w.splatByteAll('0', precision);
1525 }
1526 } else {
1527 try w.writeAll(".0");
1528 }
1529 try w.writeAll("p0");
1530 return;
1531 }
1532
1533 if (is_denormal) {
1534 // Adjust the exponent for printing.
1535 exponent += 1;
67 } else {1536 } else {
68 var copy = value;1537 if (fractional_bits == mantissa_bits)
69 mem.byteSwapAllFields(@TypeOf(value), &copy);1538 mantissa |= 1 << fractional_bits; // Add the implicit integer bit.
70 return self.writeStruct(copy);1539 }
1540
1541 const mantissa_digits = (fractional_bits + 3) / 4;
1542 // Fill in zeroes to round the fraction width to a multiple of 4.
1543 mantissa <<= mantissa_digits * 4 - fractional_bits;
1544
1545 if (opt_precision) |precision| {
1546 // Round if needed.
1547 if (precision < mantissa_digits) {
1548 // We always have at least 4 extra bits.
1549 var extra_bits = (mantissa_digits - precision) * 4;
1550 // The result LSB is the Guard bit, we need two more (Round and
1551 // Sticky) to round the value.
1552 while (extra_bits > 2) {
1553 mantissa = (mantissa >> 1) | (mantissa & 1);
1554 extra_bits -= 1;
1555 }
1556 // Round to nearest, tie to even.
1557 mantissa |= @intFromBool(mantissa & 0b100 != 0);
1558 mantissa += 1;
1559 // Drop the excess bits.
1560 mantissa >>= 2;
1561 // Restore the alignment.
1562 mantissa <<= @as(std.math.Log2Int(TU), @intCast((mantissa_digits - precision) * 4));
1563
1564 const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0;
1565 // Prefer a normalized result in case of overflow.
1566 if (overflow) {
1567 mantissa >>= 1;
1568 exponent += 1;
1569 }
1570 }
1571 }
1572
1573 // +1 for the decimal part.
1574 var buf: [1 + mantissa_digits]u8 = undefined;
1575 assert(std.fmt.printInt(&buf, mantissa, 16, case, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len);
1576
1577 try w.writeAll("0x");
1578 try w.writeByte(buf[0]);
1579 const trimmed = std.mem.trimRight(u8, buf[1..], "0");
1580 if (opt_precision) |precision| {
1581 if (precision > 0) try w.writeAll(".");
1582 } else if (trimmed.len > 0) {
1583 try w.writeAll(".");
71 }1584 }
1585 try w.writeAll(trimmed);
1586 // Add trailing zeros if explicitly requested.
1587 if (opt_precision) |precision| if (precision > 0) {
1588 if (precision > trimmed.len)
1589 try w.splatByteAll('0', precision - trimmed.len);
1590 };
1591 try w.writeAll("p");
1592 try w.printInt(exponent - exponent_bias, 10, case, .{});
1593}
1594
1595pub const ByteSizeUnits = enum {
1596 /// This formatter represents the number as multiple of 1000 and uses the SI
1597 /// measurement units (kB, MB, GB, ...).
1598 decimal,
1599 /// This formatter represents the number as multiple of 1024 and uses the IEC
1600 /// measurement units (KiB, MiB, GiB, ...).
1601 binary,
1602};
1603
1604/// Format option `precision` is ignored when `value` is less than 1kB
1605pub fn printByteSize(
1606 w: *std.io.Writer,
1607 value: u64,
1608 comptime units: ByteSizeUnits,
1609 options: std.fmt.Options,
1610) Error!void {
1611 if (value == 0) return w.alignBufferOptions("0B", options);
1612 // The worst case in terms of space needed is 32 bytes + 3 for the suffix.
1613 var buf: [std.fmt.float.min_buffer_size + 3]u8 = undefined;
1614
1615 const mags_si = " kMGTPEZY";
1616 const mags_iec = " KMGTPEZY";
1617
1618 const log2 = std.math.log2(value);
1619 const base = switch (units) {
1620 .decimal => 1000,
1621 .binary => 1024,
1622 };
1623 const magnitude = switch (units) {
1624 .decimal => @min(log2 / comptime std.math.log2(1000), mags_si.len - 1),
1625 .binary => @min(log2 / 10, mags_iec.len - 1),
1626 };
1627 const new_value = std.math.lossyCast(f64, value) / std.math.pow(f64, std.math.lossyCast(f64, base), std.math.lossyCast(f64, magnitude));
1628 const suffix = switch (units) {
1629 .decimal => mags_si[magnitude],
1630 .binary => mags_iec[magnitude],
1631 };
1632
1633 const s = switch (magnitude) {
1634 0 => buf[0..std.fmt.printInt(&buf, value, 10, .lower, .{})],
1635 else => std.fmt.float.render(&buf, new_value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1636 error.BufferTooSmall => unreachable,
1637 },
1638 };
1639
1640 var i: usize = s.len;
1641 if (suffix == ' ') {
1642 buf[i] = 'B';
1643 i += 1;
1644 } else switch (units) {
1645 .decimal => {
1646 buf[i..][0..2].* = [_]u8{ suffix, 'B' };
1647 i += 2;
1648 },
1649 .binary => {
1650 buf[i..][0..3].* = [_]u8{ suffix, 'i', 'B' };
1651 i += 3;
1652 },
1653 }
1654
1655 return w.alignBufferOptions(buf[0..i], options);
1656}
1657
1658// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
1659const ANY = "any";
1660
1661fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 {
1662 return if (std.mem.eql(u8, fmt[1..], ANY))
1663 ANY
1664 else
1665 fmt[1..];
72}1666}
731667
74pub fn writeFile(self: Self, file: std.fs.File) anyerror!void {1668pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) noreturn {
75 // TODO: figure out how to adjust std lib abstractions so that this ends up1669 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
76 // doing sendfile or maybe even copy_file_range under the right conditions.1670}
77 var buf: [4000]u8 = undefined;1671
1672pub fn printDurationSigned(w: *Writer, ns: i64) Error!void {
1673 if (ns < 0) try w.writeByte('-');
1674 return w.printDurationUnsigned(@abs(ns));
1675}
1676
1677pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {
1678 var ns_remaining = ns;
1679 inline for (.{
1680 .{ .ns = 365 * std.time.ns_per_day, .sep = 'y' },
1681 .{ .ns = std.time.ns_per_week, .sep = 'w' },
1682 .{ .ns = std.time.ns_per_day, .sep = 'd' },
1683 .{ .ns = std.time.ns_per_hour, .sep = 'h' },
1684 .{ .ns = std.time.ns_per_min, .sep = 'm' },
1685 }) |unit| {
1686 if (ns_remaining >= unit.ns) {
1687 const units = ns_remaining / unit.ns;
1688 try w.printInt(units, 10, .lower, .{});
1689 try w.writeByte(unit.sep);
1690 ns_remaining -= units * unit.ns;
1691 if (ns_remaining == 0) return;
1692 }
1693 }
1694
1695 inline for (.{
1696 .{ .ns = std.time.ns_per_s, .sep = "s" },
1697 .{ .ns = std.time.ns_per_ms, .sep = "ms" },
1698 .{ .ns = std.time.ns_per_us, .sep = "us" },
1699 }) |unit| {
1700 const kunits = ns_remaining * 1000 / unit.ns;
1701 if (kunits >= 1000) {
1702 try w.printInt(kunits / 1000, 10, .lower, .{});
1703 const frac = kunits % 1000;
1704 if (frac > 0) {
1705 // Write up to 3 decimal places
1706 var decimal_buf = [_]u8{ '.', 0, 0, 0 };
1707 var inner: Writer = .fixed(decimal_buf[1..]);
1708 inner.printInt(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable;
1709 var end: usize = 4;
1710 while (end > 1) : (end -= 1) {
1711 if (decimal_buf[end - 1] != '0') break;
1712 }
1713 try w.writeAll(decimal_buf[0..end]);
1714 }
1715 return w.writeAll(unit.sep);
1716 }
1717 }
1718
1719 try w.printInt(ns_remaining, 10, .lower, .{});
1720 try w.writeAll("ns");
1721}
1722
1723/// Writes number of nanoseconds according to its signed magnitude:
1724/// `[#y][#w][#d][#h][#m]#[.###][n|u|m]s`
1725/// `nanoseconds` must be an integer that coerces into `u64` or `i64`.
1726pub fn printDuration(w: *Writer, nanoseconds: anytype, options: std.fmt.Options) Error!void {
1727 // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24
1728 var buf: [24]u8 = undefined;
1729 var sub_writer: Writer = .fixed(&buf);
1730 if (@TypeOf(nanoseconds) == comptime_int) {
1731 if (nanoseconds >= 0) {
1732 sub_writer.printDurationUnsigned(nanoseconds) catch unreachable;
1733 } else {
1734 sub_writer.printDurationSigned(nanoseconds) catch unreachable;
1735 }
1736 } else switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) {
1737 .signed => sub_writer.printDurationSigned(nanoseconds) catch unreachable,
1738 .unsigned => sub_writer.printDurationUnsigned(nanoseconds) catch unreachable,
1739 }
1740 return w.alignBufferOptions(sub_writer.buffered(), options);
1741}
1742
1743pub fn printHex(w: *Writer, bytes: []const u8, case: std.fmt.Case) Error!void {
1744 const charset = switch (case) {
1745 .upper => "0123456789ABCDEF",
1746 .lower => "0123456789abcdef",
1747 };
1748 for (bytes) |c| {
1749 try w.writeByte(charset[c >> 4]);
1750 try w.writeByte(charset[c & 15]);
1751 }
1752}
1753
1754pub fn printBase64(w: *Writer, bytes: []const u8) Error!void {
1755 var chunker = std.mem.window(u8, bytes, 3, 3);
1756 var temp: [5]u8 = undefined;
1757 while (chunker.next()) |chunk| {
1758 try w.writeAll(std.base64.standard.Encoder.encode(&temp, chunk));
1759 }
1760}
1761
1762/// Write a single unsigned integer as LEB128 to the given writer.
1763pub fn writeUleb128(w: *Writer, value: anytype) Error!void {
1764 try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1765 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
1766 .int => |value_info| switch (value_info.signedness) {
1767 .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)),
1768 .unsigned => value,
1769 },
1770 else => comptime unreachable,
1771 });
1772}
1773
1774/// Write a single signed integer as LEB128 to the given writer.
1775pub fn writeSleb128(w: *Writer, value: anytype) Error!void {
1776 try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1777 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
1778 .int => |value_info| switch (value_info.signedness) {
1779 .signed => value,
1780 .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value),
1781 },
1782 else => comptime unreachable,
1783 });
1784}
1785
1786/// Write a single integer as LEB128 to the given writer.
1787pub fn writeLeb128(w: *Writer, value: anytype) Error!void {
1788 const value_info = @typeInfo(@TypeOf(value)).int;
1789 try w.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{
1790 .signedness = value_info.signedness,
1791 .bits = std.mem.alignForwardAnyAlign(u16, value_info.bits, 7),
1792 } }), value));
1793}
1794
1795fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {
1796 const value_info = @typeInfo(@TypeOf(value)).int;
1797 comptime assert(value_info.bits % 7 == 0);
1798 var remaining = value;
78 while (true) {1799 while (true) {
79 const n = try file.readAll(&buf);1800 const buffer: []packed struct(u8) { bits: u7, more: bool } = @ptrCast(try w.writableSliceGreedy(1));
80 try self.writeAll(buf[0..n]);1801 for (buffer, 1..) |*byte, len| {
81 if (n < buf.len) return;1802 const more = switch (value_info.signedness) {
1803 .signed => remaining >> 6 != remaining >> (value_info.bits - 1),
1804 .unsigned => remaining > std.math.maxInt(u7),
1805 };
1806 byte.* = if (@inComptime()) @typeInfo(@TypeOf(buffer)).pointer.child{
1807 .bits = @bitCast(@as(@Type(.{ .int = .{
1808 .signedness = value_info.signedness,
1809 .bits = 7,
1810 } }), @truncate(remaining))),
1811 .more = more,
1812 } else .{
1813 .bits = @bitCast(@as(@Type(.{ .int = .{
1814 .signedness = value_info.signedness,
1815 .bits = 7,
1816 } }), @truncate(remaining))),
1817 .more = more,
1818 };
1819 if (value_info.bits > 7) remaining >>= 7;
1820 if (!more) return w.advance(len);
1821 }
1822 w.advance(buffer.len);
1823 }
1824}
1825
1826test "printValue max_depth" {
1827 const Vec2 = struct {
1828 const SelfType = @This();
1829 x: f32,
1830 y: f32,
1831
1832 pub fn format(self: SelfType, w: *Writer) Error!void {
1833 return w.print("({d:.3},{d:.3})", .{ self.x, self.y });
1834 }
1835 };
1836 const E = enum {
1837 One,
1838 Two,
1839 Three,
1840 };
1841 const TU = union(enum) {
1842 const SelfType = @This();
1843 float: f32,
1844 int: u32,
1845 ptr: ?*SelfType,
1846 };
1847 const S = struct {
1848 const SelfType = @This();
1849 a: ?*SelfType,
1850 tu: TU,
1851 e: E,
1852 vec: Vec2,
1853 };
1854
1855 var inst = S{
1856 .a = null,
1857 .tu = TU{ .ptr = null },
1858 .e = E.Two,
1859 .vec = Vec2{ .x = 10.2, .y = 2.22 },
1860 };
1861 inst.a = &inst;
1862 inst.tu.ptr = &inst.tu;
1863
1864 var buf: [1000]u8 = undefined;
1865 var w: Writer = .fixed(&buf);
1866 try w.printValue("", .{}, inst, 0);
1867 try testing.expectEqualStrings(".{ ... }", w.buffered());
1868
1869 w = .fixed(&buf);
1870 try w.printValue("", .{}, inst, 1);
1871 try testing.expectEqualStrings(".{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }", w.buffered());
1872
1873 w = .fixed(&buf);
1874 try w.printValue("", .{}, inst, 2);
1875 try testing.expectEqualStrings(".{ .a = .{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }, .tu = .{ .ptr = .{ ... } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }", w.buffered());
1876
1877 w = .fixed(&buf);
1878 try w.printValue("", .{}, inst, 3);
1879 try testing.expectEqualStrings(".{ .a = .{ .a = .{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }, .tu = .{ .ptr = .{ ... } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }, .tu = .{ .ptr = .{ .ptr = .{ ... } } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }", w.buffered());
1880
1881 const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
1882 w = .fixed(&buf);
1883 try w.printValue("", .{}, vec, 0);
1884 try testing.expectEqualStrings("{ ... }", w.buffered());
1885
1886 w = .fixed(&buf);
1887 try w.printValue("", .{}, vec, 1);
1888 try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());
1889}
1890
1891test printDuration {
1892 try testDurationCase("0ns", 0);
1893 try testDurationCase("1ns", 1);
1894 try testDurationCase("999ns", std.time.ns_per_us - 1);
1895 try testDurationCase("1us", std.time.ns_per_us);
1896 try testDurationCase("1.45us", 1450);
1897 try testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
1898 try testDurationCase("14.5us", 14500);
1899 try testDurationCase("145us", 145000);
1900 try testDurationCase("999.999us", std.time.ns_per_ms - 1);
1901 try testDurationCase("1ms", std.time.ns_per_ms + 1);
1902 try testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
1903 try testDurationCase("1.11ms", 1110000);
1904 try testDurationCase("1.111ms", 1111000);
1905 try testDurationCase("1.111ms", 1111100);
1906 try testDurationCase("999.999ms", std.time.ns_per_s - 1);
1907 try testDurationCase("1s", std.time.ns_per_s);
1908 try testDurationCase("59.999s", std.time.ns_per_min - 1);
1909 try testDurationCase("1m", std.time.ns_per_min);
1910 try testDurationCase("1h", std.time.ns_per_hour);
1911 try testDurationCase("1d", std.time.ns_per_day);
1912 try testDurationCase("1w", std.time.ns_per_week);
1913 try testDurationCase("1y", 365 * std.time.ns_per_day);
1914 try testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
1915 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);
1916 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);
1917 try testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1918 try testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1919 try testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1920 try testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1921 try testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
1922
1923 try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1924 try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1925 try testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
1926}
1927
1928test printDurationSigned {
1929 try testDurationCaseSigned("0ns", 0);
1930 try testDurationCaseSigned("1ns", 1);
1931 try testDurationCaseSigned("-1ns", -(1));
1932 try testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
1933 try testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
1934 try testDurationCaseSigned("1us", std.time.ns_per_us);
1935 try testDurationCaseSigned("-1us", -(std.time.ns_per_us));
1936 try testDurationCaseSigned("1.45us", 1450);
1937 try testDurationCaseSigned("-1.45us", -(1450));
1938 try testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
1939 try testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
1940 try testDurationCaseSigned("14.5us", 14500);
1941 try testDurationCaseSigned("-14.5us", -(14500));
1942 try testDurationCaseSigned("145us", 145000);
1943 try testDurationCaseSigned("-145us", -(145000));
1944 try testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
1945 try testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
1946 try testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
1947 try testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
1948 try testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
1949 try testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
1950 try testDurationCaseSigned("1.11ms", 1110000);
1951 try testDurationCaseSigned("-1.11ms", -(1110000));
1952 try testDurationCaseSigned("1.111ms", 1111000);
1953 try testDurationCaseSigned("-1.111ms", -(1111000));
1954 try testDurationCaseSigned("1.111ms", 1111100);
1955 try testDurationCaseSigned("-1.111ms", -(1111100));
1956 try testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
1957 try testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
1958 try testDurationCaseSigned("1s", std.time.ns_per_s);
1959 try testDurationCaseSigned("-1s", -(std.time.ns_per_s));
1960 try testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
1961 try testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
1962 try testDurationCaseSigned("1m", std.time.ns_per_min);
1963 try testDurationCaseSigned("-1m", -(std.time.ns_per_min));
1964 try testDurationCaseSigned("1h", std.time.ns_per_hour);
1965 try testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
1966 try testDurationCaseSigned("1d", std.time.ns_per_day);
1967 try testDurationCaseSigned("-1d", -(std.time.ns_per_day));
1968 try testDurationCaseSigned("1w", std.time.ns_per_week);
1969 try testDurationCaseSigned("-1w", -(std.time.ns_per_week));
1970 try testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
1971 try testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
1972 try testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
1973 try testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
1974 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);
1975 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));
1976 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);
1977 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));
1978 try testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
1979 try testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
1980 try testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
1981 try testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
1982 try testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
1983 try testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
1984 try testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
1985 try testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
1986 try testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
1987 try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
1988 try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
1989
1990 try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
1991 try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
1992 try testing.expectFmt("-1ns======", "{D:=<10}", .{-(1)});
1993 try testing.expectFmt(" -999ns ", "{D:^10}", .{-(std.time.ns_per_us - 1)});
1994}
1995
1996fn testDurationCase(expected: []const u8, input: u64) !void {
1997 var buf: [24]u8 = undefined;
1998 var w: Writer = .fixed(&buf);
1999 try w.printDurationUnsigned(input);
2000 try testing.expectEqualStrings(expected, w.buffered());
2001}
2002
2003fn testDurationCaseSigned(expected: []const u8, input: i64) !void {
2004 var buf: [24]u8 = undefined;
2005 var w: Writer = .fixed(&buf);
2006 try w.printDurationSigned(input);
2007 try testing.expectEqualStrings(expected, w.buffered());
2008}
2009
2010test printInt {
2011 try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{});
2012
2013 try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{});
2014 try testPrintIntCase("-12345678", @as(i32, -12345678), 10, .lower, .{});
2015 try testPrintIntCase("-bc614e", @as(i32, -12345678), 16, .lower, .{});
2016 try testPrintIntCase("-BC614E", @as(i32, -12345678), 16, .upper, .{});
2017
2018 try testPrintIntCase("12345678", @as(u32, 12345678), 10, .upper, .{});
2019
2020 try testPrintIntCase(" 666", @as(u32, 666), 10, .lower, .{ .width = 6 });
2021 try testPrintIntCase(" 1234", @as(u32, 0x1234), 16, .lower, .{ .width = 6 });
2022 try testPrintIntCase("1234", @as(u32, 0x1234), 16, .lower, .{ .width = 1 });
2023
2024 try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 });
2025 try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 });
2026
2027 try testPrintIntCase("123456789123456789", @as(comptime_int, 123456789123456789), 10, .lower, .{});
2028}
2029
2030test "printFloat with comptime_float" {
2031 var buf: [20]u8 = undefined;
2032 var w: Writer = .fixed(&buf);
2033 try w.printFloat(@as(comptime_float, 1.0), std.fmt.Options.toNumber(.{}, .scientific, .lower));
2034 try testing.expectEqualStrings(w.buffered(), "1e0");
2035 try testing.expectFmt("1", "{}", .{1.0});
2036}
2037
2038fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
2039 var buffer: [100]u8 = undefined;
2040 var w: Writer = .fixed(&buffer);
2041 try w.printInt(value, base, case, options);
2042 try testing.expectEqualStrings(expected, w.buffered());
2043}
2044
2045test printByteSize {
2046 try testing.expectFmt("file size: 42B\n", "file size: {B}\n", .{42});
2047 try testing.expectFmt("file size: 42B\n", "file size: {Bi}\n", .{42});
2048 try testing.expectFmt("file size: 63MB\n", "file size: {B}\n", .{63 * 1000 * 1000});
2049 try testing.expectFmt("file size: 63MiB\n", "file size: {Bi}\n", .{63 * 1024 * 1024});
2050 try testing.expectFmt("file size: 42B\n", "file size: {B:.2}\n", .{42});
2051 try testing.expectFmt("file size: 42B\n", "file size: {B:>9.2}\n", .{42});
2052 try testing.expectFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{63 * 1024 * 1024});
2053 try testing.expectFmt("file size: 60.08MiB\n", "file size: {Bi:.2}\n", .{63 * 1000 * 1000});
2054 try testing.expectFmt("file size: =66.06MB=\n", "file size: {B:=^9.2}\n", .{63 * 1024 * 1024});
2055 try testing.expectFmt("file size: 66.06MB\n", "file size: {B: >9.2}\n", .{63 * 1024 * 1024});
2056 try testing.expectFmt("file size: 66.06MB \n", "file size: {B: <9.2}\n", .{63 * 1024 * 1024});
2057 try testing.expectFmt("file size: 0.01844674407370955ZB\n", "file size: {B}\n", .{std.math.maxInt(u64)});
2058}
2059
2060test "bytes.hex" {
2061 const some_bytes = "\xCA\xFE\xBA\xBE";
2062 try testing.expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
2063 try testing.expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
2064 try testing.expectFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
2065 try testing.expectFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
2066 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
2067 try testing.expectFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
2068}
2069
2070test fixed {
2071 {
2072 var buf: [255]u8 = undefined;
2073 var w: Writer = .fixed(&buf);
2074 try w.print("{s}{s}!", .{ "Hello", "World" });
2075 try testing.expectEqualStrings("HelloWorld!", w.buffered());
2076 }
2077
2078 comptime {
2079 var buf: [255]u8 = undefined;
2080 var w: Writer = .fixed(&buf);
2081 try w.print("{s}{s}!", .{ "Hello", "World" });
2082 try testing.expectEqualStrings("HelloWorld!", w.buffered());
2083 }
2084}
2085
2086test "fixed output" {
2087 var buffer: [10]u8 = undefined;
2088 var w: Writer = .fixed(&buffer);
2089
2090 try w.writeAll("Hello");
2091 try testing.expect(std.mem.eql(u8, w.buffered(), "Hello"));
2092
2093 try w.writeAll("world");
2094 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
2095
2096 try testing.expectError(error.WriteFailed, w.writeAll("!"));
2097 try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
2098
2099 w = .fixed(&buffer);
2100
2101 try testing.expect(w.buffered().len == 0);
2102
2103 try testing.expectError(error.WriteFailed, w.writeAll("Hello world!"));
2104 try testing.expect(std.mem.eql(u8, w.buffered(), "Hello worl"));
2105}
2106
2107test "writeSplat 0 len splat larger than capacity" {
2108 var buf: [8]u8 = undefined;
2109 var w: std.io.Writer = .fixed(&buf);
2110 const n = try w.writeSplat(&.{"something that overflows buf"}, 0);
2111 try testing.expectEqual(0, n);
2112}
2113
2114pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2115 _ = w;
2116 _ = data;
2117 _ = splat;
2118 return error.WriteFailed;
2119}
2120
2121pub fn failingSendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
2122 _ = w;
2123 _ = file_reader;
2124 _ = limit;
2125 return error.WriteFailed;
2126}
2127
2128pub const Discarding = struct {
2129 count: u64,
2130 writer: Writer,
2131
2132 pub fn init(buffer: []u8) Discarding {
2133 return .{
2134 .count = 0,
2135 .writer = .{
2136 .vtable = &.{
2137 .drain = Discarding.drain,
2138 .sendFile = Discarding.sendFile,
2139 },
2140 .buffer = buffer,
2141 },
2142 };
82 }2143 }
2144
2145 pub fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2146 const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));
2147 const slice = data[0 .. data.len - 1];
2148 const pattern = data[slice.len..];
2149 var written: usize = pattern.len * splat;
2150 for (slice) |bytes| written += bytes.len;
2151 d.count += w.end + written;
2152 w.end = 0;
2153 return written;
2154 }
2155
2156 pub fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
2157 if (File.Handle == void) return error.Unimplemented;
2158 const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));
2159 d.count += w.end;
2160 w.end = 0;
2161 if (file_reader.getSize()) |size| {
2162 const n = limit.minInt64(size - file_reader.pos);
2163 file_reader.seekBy(@intCast(n)) catch return error.Unimplemented;
2164 w.end = 0;
2165 d.count += n;
2166 return n;
2167 } else |_| {
2168 // Error is observable on `file_reader` instance, and it is better to
2169 // treat the file as a pipe.
2170 return error.Unimplemented;
2171 }
2172 }
2173};
2174
2175/// Removes the first `n` bytes from `buffer` by shifting buffer contents,
2176/// returning how many bytes are left after consuming the entire buffer, or
2177/// zero if the entire buffer was not consumed.
2178///
2179/// Useful for `VTable.drain` function implementations to implement partial
2180/// drains.
2181pub fn consume(w: *Writer, n: usize) usize {
2182 if (n < w.end) {
2183 const remaining = w.buffer[n..w.end];
2184 @memmove(w.buffer[0..remaining.len], remaining);
2185 w.end = remaining.len;
2186 return 0;
2187 }
2188 defer w.end = 0;
2189 return n - w.end;
2190}
2191
2192/// Shortcut for setting `end` to zero and returning zero. Equivalent to
2193/// calling `consume` with `end`.
2194pub fn consumeAll(w: *Writer) usize {
2195 w.end = 0;
2196 return 0;
83}2197}
2198
2199/// For use when the `Writer` implementation can cannot offer a more efficient
2200/// implementation than a basic read/write loop on the file.
2201pub fn unimplementedSendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
2202 _ = w;
2203 _ = file_reader;
2204 _ = limit;
2205 return error.Unimplemented;
2206}
2207
2208/// When this function is called it usually means the buffer got full, so it's
2209/// time to return an error. However, we still need to make sure all of the
2210/// available buffer has been filled. Also, it may be called from `flush` in
2211/// which case it should return successfully.
2212pub fn fixedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2213 if (data.len == 0) return 0;
2214 for (data[0 .. data.len - 1]) |bytes| {
2215 const dest = w.buffer[w.end..];
2216 const len = @min(bytes.len, dest.len);
2217 @memcpy(dest[0..len], bytes[0..len]);
2218 w.end += len;
2219 if (bytes.len > dest.len) return error.WriteFailed;
2220 }
2221 const pattern = data[data.len - 1];
2222 const dest = w.buffer[w.end..];
2223 switch (pattern.len) {
2224 0 => return w.end,
2225 1 => {
2226 assert(splat >= dest.len);
2227 @memset(dest, pattern[0]);
2228 w.end += dest.len;
2229 return error.WriteFailed;
2230 },
2231 else => {
2232 for (0..splat) |i| {
2233 const remaining = dest[i * pattern.len ..];
2234 const len = @min(pattern.len, remaining.len);
2235 @memcpy(remaining[0..len], pattern[0..len]);
2236 w.end += len;
2237 if (pattern.len > remaining.len) return error.WriteFailed;
2238 }
2239 unreachable;
2240 },
2241 }
2242}
2243
2244/// Provides a `Writer` implementation based on calling `Hasher.update`, sending
2245/// all data also to an underlying `Writer`.
2246///
2247/// When using this, the underlying writer is best unbuffered because all
2248/// writes are passed on directly to it.
2249///
2250/// This implementation makes suboptimal buffering decisions due to being
2251/// generic. A better solution will involve creating a writer for each hash
2252/// function, where the splat buffer can be tailored to the hash implementation
2253/// details.
2254pub fn Hashed(comptime Hasher: type) type {
2255 return struct {
2256 out: *Writer,
2257 hasher: Hasher,
2258 writer: Writer,
2259
2260 pub fn init(out: *Writer, buffer: []u8) @This() {
2261 return .initHasher(out, .{}, buffer);
2262 }
2263
2264 pub fn initHasher(out: *Writer, hasher: Hasher, buffer: []u8) @This() {
2265 return .{
2266 .out = out,
2267 .hasher = hasher,
2268 .writer = .{
2269 .buffer = buffer,
2270 .vtable = &.{ .drain = @This().drain },
2271 },
2272 };
2273 }
2274
2275 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2276 const this: *@This() = @alignCast(@fieldParentPtr("writer", w));
2277 const aux = w.buffered();
2278 const aux_n = try this.out.writeSplatHeader(aux, data, splat);
2279 if (aux_n < w.end) {
2280 this.hasher.update(w.buffer[0..aux_n]);
2281 const remaining = w.buffer[aux_n..w.end];
2282 @memmove(w.buffer[0..remaining.len], remaining);
2283 w.end = remaining.len;
2284 return 0;
2285 }
2286 this.hasher.update(aux);
2287 const n = aux_n - w.end;
2288 w.end = 0;
2289 var remaining: usize = n;
2290 for (data[0 .. data.len - 1]) |slice| {
2291 if (remaining <= slice.len) {
2292 this.hasher.update(slice[0..remaining]);
2293 return n;
2294 }
2295 remaining -= slice.len;
2296 this.hasher.update(slice);
2297 }
2298 const pattern = data[data.len - 1];
2299 assert(remaining == splat * pattern.len);
2300 switch (pattern.len) {
2301 0 => {
2302 assert(remaining == 0);
2303 },
2304 1 => {
2305 var buffer: [64]u8 = undefined;
2306 @memset(&buffer, pattern[0]);
2307 while (remaining > 0) {
2308 const update_len = @min(remaining, buffer.len);
2309 this.hasher.update(buffer[0..update_len]);
2310 remaining -= update_len;
2311 }
2312 },
2313 else => {
2314 while (remaining > 0) {
2315 const update_len = @min(remaining, pattern.len);
2316 this.hasher.update(pattern[0..update_len]);
2317 remaining -= update_len;
2318 }
2319 },
2320 }
2321 return n;
2322 }
2323 };
2324}
2325
2326/// Maintains `Writer` state such that it writes to the unused capacity of an
2327/// array list, filling it up completely before making a call through the
2328/// vtable, causing a resize. Consequently, the same, optimized, non-generic
2329/// machine code that uses `std.io.Reader`, such as formatted printing, takes
2330/// the hot paths when using this API.
2331///
2332/// When using this API, it is not necessary to call `flush`.
2333pub const Allocating = struct {
2334 allocator: Allocator,
2335 writer: Writer,
2336
2337 pub fn init(allocator: Allocator) Allocating {
2338 return .{
2339 .allocator = allocator,
2340 .writer = .{
2341 .buffer = &.{},
2342 .vtable = &vtable,
2343 },
2344 };
2345 }
2346
2347 pub fn initCapacity(allocator: Allocator, capacity: usize) error{OutOfMemory}!Allocating {
2348 return .{
2349 .allocator = allocator,
2350 .writer = .{
2351 .buffer = try allocator.alloc(u8, capacity),
2352 .vtable = &vtable,
2353 },
2354 };
2355 }
2356
2357 pub fn initOwnedSlice(allocator: Allocator, slice: []u8) Allocating {
2358 return .{
2359 .allocator = allocator,
2360 .writer = .{
2361 .buffer = slice,
2362 .vtable = &vtable,
2363 },
2364 };
2365 }
2366
2367 /// Replaces `array_list` with empty, taking ownership of the memory.
2368 pub fn fromArrayList(allocator: Allocator, array_list: *std.ArrayListUnmanaged(u8)) Allocating {
2369 defer array_list.* = .empty;
2370 return .{
2371 .allocator = allocator,
2372 .writer = .{
2373 .vtable = &vtable,
2374 .buffer = array_list.allocatedSlice(),
2375 .end = array_list.items.len,
2376 },
2377 };
2378 }
2379
2380 const vtable: VTable = .{
2381 .drain = Allocating.drain,
2382 .sendFile = Allocating.sendFile,
2383 .flush = noopFlush,
2384 };
2385
2386 pub fn deinit(a: *Allocating) void {
2387 a.allocator.free(a.writer.buffer);
2388 a.* = undefined;
2389 }
2390
2391 /// Returns an array list that takes ownership of the allocated memory.
2392 /// Resets the `Allocating` to an empty state.
2393 pub fn toArrayList(a: *Allocating) std.ArrayListUnmanaged(u8) {
2394 const w = &a.writer;
2395 const result: std.ArrayListUnmanaged(u8) = .{
2396 .items = w.buffer[0..w.end],
2397 .capacity = w.buffer.len,
2398 };
2399 w.buffer = &.{};
2400 w.end = 0;
2401 return result;
2402 }
2403
2404 pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 {
2405 var list = a.toArrayList();
2406 return list.toOwnedSlice(a.allocator);
2407 }
2408
2409 pub fn toOwnedSliceSentinel(a: *Allocating, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 {
2410 const gpa = a.allocator;
2411 var list = toArrayList(a);
2412 return list.toOwnedSliceSentinel(gpa, sentinel);
2413 }
2414
2415 pub fn getWritten(a: *Allocating) []u8 {
2416 return a.writer.buffered();
2417 }
2418
2419 pub fn shrinkRetainingCapacity(a: *Allocating, new_len: usize) void {
2420 a.writer.end = new_len;
2421 }
2422
2423 pub fn clearRetainingCapacity(a: *Allocating) void {
2424 a.shrinkRetainingCapacity(0);
2425 }
2426
2427 fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2428 const a: *Allocating = @fieldParentPtr("writer", w);
2429 const gpa = a.allocator;
2430 const pattern = data[data.len - 1];
2431 const splat_len = pattern.len * splat;
2432 var list = a.toArrayList();
2433 defer setArrayList(a, list);
2434 const start_len = list.items.len;
2435 // Even if we append no data, this function needs to ensure there is more
2436 // capacity in the buffer to avoid infinite loop, hence the +1 in this loop.
2437 assert(data.len != 0);
2438 for (data) |bytes| {
2439 list.ensureUnusedCapacity(gpa, bytes.len + splat_len + 1) catch return error.WriteFailed;
2440 list.appendSliceAssumeCapacity(bytes);
2441 }
2442 if (splat == 0) {
2443 list.items.len -= pattern.len;
2444 } else switch (pattern.len) {
2445 0 => {},
2446 1 => list.appendNTimesAssumeCapacity(pattern[0], splat - 1),
2447 else => for (0..splat - 1) |_| list.appendSliceAssumeCapacity(pattern),
2448 }
2449 return list.items.len - start_len;
2450 }
2451
2452 fn sendFile(w: *Writer, file_reader: *File.Reader, limit: std.io.Limit) FileError!usize {
2453 if (File.Handle == void) return error.Unimplemented;
2454 const a: *Allocating = @fieldParentPtr("writer", w);
2455 const gpa = a.allocator;
2456 var list = a.toArrayList();
2457 defer setArrayList(a, list);
2458 const pos = file_reader.pos;
2459 const additional = if (file_reader.getSize()) |size| size - pos else |_| std.atomic.cache_line;
2460 list.ensureUnusedCapacity(gpa, limit.minInt64(additional)) catch return error.WriteFailed;
2461 const dest = limit.slice(list.unusedCapacitySlice());
2462 const n = file_reader.read(dest) catch |err| switch (err) {
2463 error.ReadFailed => return error.ReadFailed,
2464 error.EndOfStream => 0,
2465 };
2466 list.items.len += n;
2467 return n;
2468 }
2469
2470 fn setArrayList(a: *Allocating, list: std.ArrayListUnmanaged(u8)) void {
2471 a.writer.buffer = list.allocatedSlice();
2472 a.writer.end = list.items.len;
2473 }
2474
2475 test Allocating {
2476 var a: Allocating = .init(testing.allocator);
2477 defer a.deinit();
2478 const w = &a.writer;
2479
2480 const x: i32 = 42;
2481 const y: i32 = 1234;
2482 try w.print("x: {}\ny: {}\n", .{ x, y });
2483
2484 try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", a.getWritten());
2485 }
2486};
lib/std/io/buffered_atomic_file.zig+2-2
...@@ -11,7 +11,7 @@ pub const BufferedAtomicFile = struct {...@@ -11,7 +11,7 @@ pub const BufferedAtomicFile = struct {
1111
12 pub const buffer_size = 4096;12 pub const buffer_size = 4096;
13 pub const BufferedWriter = std.io.BufferedWriter(buffer_size, File.Writer);13 pub const BufferedWriter = std.io.BufferedWriter(buffer_size, File.Writer);
14 pub const Writer = std.io.Writer(*BufferedWriter, BufferedWriter.Error, BufferedWriter.write);14 pub const Writer = std.io.GenericWriter(*BufferedWriter, BufferedWriter.Error, BufferedWriter.write);
1515
16 /// TODO when https://github.com/ziglang/zig/issues/2761 is solved16 /// TODO when https://github.com/ziglang/zig/issues/2761 is solved
17 /// this API will not need an allocator17 /// this API will not need an allocator
...@@ -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/buffered_reader.zig+3-3
...@@ -12,7 +12,7 @@ pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) ty...@@ -12,7 +12,7 @@ pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) ty
12 end: usize = 0,12 end: usize = 0,
1313
14 pub const Error = ReaderType.Error;14 pub const Error = ReaderType.Error;
15 pub const Reader = io.Reader(*Self, Error, read);15 pub const Reader = io.GenericReader(*Self, Error, read);
1616
17 const Self = @This();17 const Self = @This();
1818
...@@ -61,7 +61,7 @@ test "OneByte" {...@@ -61,7 +61,7 @@ test "OneByte" {
6161
62 const Error = error{NoError};62 const Error = error{NoError};
63 const Self = @This();63 const Self = @This();
64 const Reader = io.Reader(*Self, Error, read);64 const Reader = io.GenericReader(*Self, Error, read);
6565
66 fn init(str: []const u8) Self {66 fn init(str: []const u8) Self {
67 return Self{67 return Self{
...@@ -105,7 +105,7 @@ test "Block" {...@@ -105,7 +105,7 @@ test "Block" {
105105
106 const Error = error{NoError};106 const Error = error{NoError};
107 const Self = @This();107 const Self = @This();
108 const Reader = io.Reader(*Self, Error, read);108 const Reader = io.GenericReader(*Self, Error, read);
109109
110 fn init(block: []const u8, reads_allowed: usize) Self {110 fn init(block: []const u8, reads_allowed: usize) Self {
111 return Self{111 return Self{
lib/std/io/buffered_writer.zig+1-1
...@@ -10,7 +10,7 @@ pub fn BufferedWriter(comptime buffer_size: usize, comptime WriterType: type) ty...@@ -10,7 +10,7 @@ pub fn BufferedWriter(comptime buffer_size: usize, comptime WriterType: type) ty
10 end: usize = 0,10 end: usize = 0,
1111
12 pub const Error = WriterType.Error;12 pub const Error = WriterType.Error;
13 pub const Writer = io.Writer(*Self, Error, write);13 pub const Writer = io.GenericWriter(*Self, Error, write);
1414
15 const Self = @This();15 const Self = @This();
1616
lib/std/io/c_writer.zig+1-1
...@@ -3,7 +3,7 @@ const builtin = @import("builtin");...@@ -3,7 +3,7 @@ const builtin = @import("builtin");
3const io = std.io;3const io = std.io;
4const testing = std.testing;4const testing = std.testing;
55
6pub const CWriter = io.Writer(*std.c.FILE, std.fs.File.WriteError, cWriterWrite);6pub const CWriter = io.GenericWriter(*std.c.FILE, std.fs.File.WriteError, cWriterWrite);
77
8pub fn cWriter(c_file: *std.c.FILE) CWriter {8pub fn cWriter(c_file: *std.c.FILE) CWriter {
9 return .{ .context = c_file };9 return .{ .context = c_file };
lib/std/io/change_detection_stream.zig+1-1
...@@ -8,7 +8,7 @@ pub fn ChangeDetectionStream(comptime WriterType: type) type {...@@ -8,7 +8,7 @@ pub fn ChangeDetectionStream(comptime WriterType: type) type {
8 return struct {8 return struct {
9 const Self = @This();9 const Self = @This();
10 pub const Error = WriterType.Error;10 pub const Error = WriterType.Error;
11 pub const Writer = io.Writer(*Self, Error, write);11 pub const Writer = io.GenericWriter(*Self, Error, write);
1212
13 anything_changed: bool,13 anything_changed: bool,
14 underlying_writer: WriterType,14 underlying_writer: WriterType,
lib/std/io/counting_reader.zig+1-1
...@@ -9,7 +9,7 @@ pub fn CountingReader(comptime ReaderType: anytype) type {...@@ -9,7 +9,7 @@ pub fn CountingReader(comptime ReaderType: anytype) type {
9 bytes_read: u64 = 0,9 bytes_read: u64 = 0,
1010
11 pub const Error = ReaderType.Error;11 pub const Error = ReaderType.Error;
12 pub const Reader = io.Reader(*@This(), Error, read);12 pub const Reader = io.GenericReader(*@This(), Error, read);
1313
14 pub fn read(self: *@This(), buf: []u8) Error!usize {14 pub fn read(self: *@This(), buf: []u8) Error!usize {
15 const amt = try self.child_reader.read(buf);15 const amt = try self.child_reader.read(buf);
lib/std/io/counting_writer.zig+1-1
...@@ -9,7 +9,7 @@ pub fn CountingWriter(comptime WriterType: type) type {...@@ -9,7 +9,7 @@ pub fn CountingWriter(comptime WriterType: type) type {
9 child_stream: WriterType,9 child_stream: WriterType,
1010
11 pub const Error = WriterType.Error;11 pub const Error = WriterType.Error;
12 pub const Writer = io.Writer(*Self, Error, write);12 pub const Writer = io.GenericWriter(*Self, Error, write);
1313
14 const Self = @This();14 const Self = @This();
1515
lib/std/io/find_byte_writer.zig+1-1
...@@ -8,7 +8,7 @@ pub fn FindByteWriter(comptime UnderlyingWriter: type) type {...@@ -8,7 +8,7 @@ pub fn FindByteWriter(comptime UnderlyingWriter: type) type {
8 return struct {8 return struct {
9 const Self = @This();9 const Self = @This();
10 pub const Error = UnderlyingWriter.Error;10 pub const Error = UnderlyingWriter.Error;
11 pub const Writer = io.Writer(*Self, Error, write);11 pub const Writer = io.GenericWriter(*Self, Error, write);
1212
13 underlying_writer: UnderlyingWriter,13 underlying_writer: UnderlyingWriter,
14 byte_found: bool,14 byte_found: bool,
lib/std/io/fixed_buffer_stream.zig+4-4
...@@ -4,8 +4,8 @@ const testing = std.testing;...@@ -4,8 +4,8 @@ const testing = std.testing;
4const mem = std.mem;4const mem = std.mem;
5const assert = std.debug.assert;5const assert = std.debug.assert;
66
7/// This turns a byte buffer into an `io.Writer`, `io.Reader`, or `io.SeekableStream`.7/// This turns a byte buffer into an `io.GenericWriter`, `io.GenericReader`, or `io.SeekableStream`.
8/// If the supplied byte buffer is const, then `io.Writer` is not available.8/// If the supplied byte buffer is const, then `io.GenericWriter` is not available.
9pub fn FixedBufferStream(comptime Buffer: type) type {9pub fn FixedBufferStream(comptime Buffer: type) type {
10 return struct {10 return struct {
11 /// `Buffer` is either a `[]u8` or `[]const u8`.11 /// `Buffer` is either a `[]u8` or `[]const u8`.
...@@ -17,8 +17,8 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -17,8 +17,8 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
17 pub const SeekError = error{};17 pub const SeekError = error{};
18 pub const GetSeekPosError = error{};18 pub const GetSeekPosError = error{};
1919
20 pub const Reader = io.Reader(*Self, ReadError, read);20 pub const Reader = io.GenericReader(*Self, ReadError, read);
21 pub const Writer = io.Writer(*Self, WriteError, write);21 pub const Writer = io.GenericWriter(*Self, WriteError, write);
2222
23 pub const SeekableStream = io.SeekableStream(23 pub const SeekableStream = io.SeekableStream(
24 *Self,24 *Self,
lib/std/io/limited_reader.zig+1-1
...@@ -9,7 +9,7 @@ pub fn LimitedReader(comptime ReaderType: type) type {...@@ -9,7 +9,7 @@ pub fn LimitedReader(comptime ReaderType: type) type {
9 bytes_left: u64,9 bytes_left: u64,
1010
11 pub const Error = ReaderType.Error;11 pub const Error = ReaderType.Error;
12 pub const Reader = io.Reader(*Self, Error, read);12 pub const Reader = io.GenericReader(*Self, Error, read);
1313
14 const Self = @This();14 const Self = @This();
1515
lib/std/io/multi_writer.zig+1-1
...@@ -15,7 +15,7 @@ pub fn MultiWriter(comptime Writers: type) type {...@@ -15,7 +15,7 @@ pub fn MultiWriter(comptime Writers: type) type {
15 streams: Writers,15 streams: Writers,
1616
17 pub const Error = ErrSet;17 pub const Error = ErrSet;
18 pub const Writer = io.Writer(*Self, Error, write);18 pub const Writer = io.GenericWriter(*Self, Error, write);
1919
20 pub fn writer(self: *Self) Writer {20 pub fn writer(self: *Self) Writer {
21 return .{ .context = self };21 return .{ .context = self };
lib/std/io/stream_source.zig+4-4
...@@ -2,9 +2,9 @@ const std = @import("../std.zig");...@@ -2,9 +2,9 @@ const std = @import("../std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const io = std.io;3const io = std.io;
44
5/// Provides `io.Reader`, `io.Writer`, and `io.SeekableStream` for in-memory buffers as5/// Provides `io.GenericReader`, `io.GenericWriter`, and `io.SeekableStream` for in-memory buffers as
6/// well as files.6/// well as files.
7/// For memory sources, if the supplied byte buffer is const, then `io.Writer` is not available.7/// For memory sources, if the supplied byte buffer is const, then `io.GenericWriter` is not available.
8/// The error set of the stream functions is the error set of the corresponding file functions.8/// The error set of the stream functions is the error set of the corresponding file functions.
9pub const StreamSource = union(enum) {9pub const StreamSource = union(enum) {
10 // TODO: expose UEFI files to std.os in a way that allows this to be true10 // TODO: expose UEFI files to std.os in a way that allows this to be true
...@@ -26,8 +26,8 @@ pub const StreamSource = union(enum) {...@@ -26,8 +26,8 @@ pub const StreamSource = union(enum) {
26 pub const SeekError = io.FixedBufferStream([]u8).SeekError || (if (has_file) std.fs.File.SeekError else error{});26 pub const SeekError = io.FixedBufferStream([]u8).SeekError || (if (has_file) std.fs.File.SeekError else error{});
27 pub const GetSeekPosError = io.FixedBufferStream([]u8).GetSeekPosError || (if (has_file) std.fs.File.GetSeekPosError else error{});27 pub const GetSeekPosError = io.FixedBufferStream([]u8).GetSeekPosError || (if (has_file) std.fs.File.GetSeekPosError else error{});
2828
29 pub const Reader = io.Reader(*StreamSource, ReadError, read);29 pub const Reader = io.GenericReader(*StreamSource, ReadError, read);
30 pub const Writer = io.Writer(*StreamSource, WriteError, write);30 pub const Writer = io.GenericWriter(*StreamSource, WriteError, write);
31 pub const SeekableStream = io.SeekableStream(31 pub const SeekableStream = io.SeekableStream(
32 *StreamSource,32 *StreamSource,
33 SeekError,33 SeekError,
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/io/tty.zig+39-36
...@@ -5,36 +5,9 @@ const process = std.process;...@@ -5,36 +5,9 @@ const process = std.process;
5const windows = std.os.windows;5const windows = std.os.windows;
6const native_os = builtin.os.tag;6const native_os = builtin.os.tag;
77
8/// Detect suitable TTY configuration options for the given file (commonly stdout/stderr).8/// Deprecated in favor of `Config.detect`.
9/// This includes feature checks for ANSI escape codes and the Windows console API, as well as
10/// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default.
11/// Will attempt to enable ANSI escape code support if necessary/possible.
12pub fn detectConfig(file: File) Config {9pub fn detectConfig(file: File) Config {
13 const force_color: ?bool = if (builtin.os.tag == .wasi)10 return .detect(file);
14 null // wasi does not support environment variables
15 else if (process.hasNonEmptyEnvVarConstant("NO_COLOR"))
16 false
17 else if (process.hasNonEmptyEnvVarConstant("CLICOLOR_FORCE"))
18 true
19 else
20 null;
21
22 if (force_color == false) return .no_color;
23
24 if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes;
25
26 if (native_os == .windows and file.isTty()) {
27 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
28 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) == windows.FALSE) {
29 return if (force_color == true) .escape_codes else .no_color;
30 }
31 return .{ .windows_api = .{
32 .handle = file.handle,
33 .reset_attributes = info.wAttributes,
34 } };
35 }
36
37 return if (force_color == true) .escape_codes else .no_color;
38}11}
3912
40pub const Color = enum {13pub const Color = enum {
...@@ -66,17 +39,46 @@ pub const Config = union(enum) {...@@ -66,17 +39,46 @@ pub const Config = union(enum) {
66 escape_codes,39 escape_codes,
67 windows_api: if (native_os == .windows) WindowsContext else void,40 windows_api: if (native_os == .windows) WindowsContext else void,
6841
42 /// Detect suitable TTY configuration options for the given file (commonly stdout/stderr).
43 /// This includes feature checks for ANSI escape codes and the Windows console API, as well as
44 /// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default.
45 /// Will attempt to enable ANSI escape code support if necessary/possible.
46 pub fn detect(file: File) Config {
47 const force_color: ?bool = if (builtin.os.tag == .wasi)
48 null // wasi does not support environment variables
49 else if (process.hasNonEmptyEnvVarConstant("NO_COLOR"))
50 false
51 else if (process.hasNonEmptyEnvVarConstant("CLICOLOR_FORCE"))
52 true
53 else
54 null;
55
56 if (force_color == false) return .no_color;
57
58 if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes;
59
60 if (native_os == .windows and file.isTty()) {
61 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
62 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) == windows.FALSE) {
63 return if (force_color == true) .escape_codes else .no_color;
64 }
65 return .{ .windows_api = .{
66 .handle = file.handle,
67 .reset_attributes = info.wAttributes,
68 } };
69 }
70
71 return if (force_color == true) .escape_codes else .no_color;
72 }
73
69 pub const WindowsContext = struct {74 pub const WindowsContext = struct {
70 handle: File.Handle,75 handle: File.Handle,
71 reset_attributes: u16,76 reset_attributes: u16,
72 };77 };
7378
74 pub fn setColor(79 pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || std.io.Writer.Error;
75 conf: Config,80
76 writer: anytype,81 pub fn setColor(conf: Config, w: *std.io.Writer, color: Color) SetColorError!void {
77 color: Color,
78 ) (@typeInfo(@TypeOf(writer.writeAll(""))).error_union.error_set ||
79 windows.SetConsoleTextAttributeError)!void {
80 nosuspend switch (conf) {82 nosuspend switch (conf) {
81 .no_color => return,83 .no_color => return,
82 .escape_codes => {84 .escape_codes => {
...@@ -101,7 +103,7 @@ pub const Config = union(enum) {...@@ -101,7 +103,7 @@ pub const Config = union(enum) {
101 .dim => "\x1b[2m",103 .dim => "\x1b[2m",
102 .reset => "\x1b[0m",104 .reset => "\x1b[0m",
103 };105 };
104 try writer.writeAll(color_string);106 try w.writeAll(color_string);
105 },107 },
106 .windows_api => |ctx| if (native_os == .windows) {108 .windows_api => |ctx| if (native_os == .windows) {
107 const attributes = switch (color) {109 const attributes = switch (color) {
...@@ -126,6 +128,7 @@ pub const Config = union(enum) {...@@ -126,6 +128,7 @@ pub const Config = union(enum) {
126 .dim => windows.FOREGROUND_INTENSITY,128 .dim => windows.FOREGROUND_INTENSITY,
127 .reset => ctx.reset_attributes,129 .reset => ctx.reset_attributes,
128 };130 };
131 try w.flush();
129 try windows.SetConsoleTextAttribute(ctx.handle, attributes);132 try windows.SetConsoleTextAttribute(ctx.handle, attributes);
130 } else {133 } else {
131 unreachable;134 unreachable;
lib/std/json.zig+2-2
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1//! JSON parsing and stringification conforming to RFC 8259. https://datatracker.ietf.org/doc/html/rfc82591//! JSON parsing and stringification conforming to RFC 8259. https://datatracker.ietf.org/doc/html/rfc8259
2//!2//!
3//! The low-level `Scanner` API produces `Token`s from an input slice or successive slices of inputs,3//! The low-level `Scanner` API produces `Token`s from an input slice or successive slices of inputs,
4//! The `Reader` API connects a `std.io.Reader` to a `Scanner`.4//! The `Reader` API connects a `std.io.GenericReader` to a `Scanner`.
5//!5//!
6//! The high-level `parseFromSlice` and `parseFromTokenSource` deserialize a JSON document into a Zig type.6//! The high-level `parseFromSlice` and `parseFromTokenSource` deserialize a JSON document into a Zig type.
7//! Parse into a dynamically-typed `Value` to load any JSON value for runtime inspection.7//! Parse into a dynamically-typed `Value` to load any JSON value for runtime inspection.
8//!8//!
9//! The low-level `writeStream` emits syntax-conformant JSON tokens to a `std.io.Writer`.9//! The low-level `writeStream` emits syntax-conformant JSON tokens to a `std.io.GenericWriter`.
10//! The high-level `stringify` serializes a Zig or `Value` type into JSON.10//! The high-level `stringify` serializes a Zig or `Value` type into JSON.
1111
12const builtin = @import("builtin");12const builtin = @import("builtin");
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.io.getStdErr().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/dynamic_test.zig+2-2
...@@ -254,7 +254,7 @@ test "Value.jsonStringify" {...@@ -254,7 +254,7 @@ test "Value.jsonStringify" {
254 \\ true,254 \\ true,
255 \\ 42,255 \\ 42,
256 \\ 43,256 \\ 43,
257 \\ 4.2e1,257 \\ 42,
258 \\ "weeee",258 \\ "weeee",
259 \\ [259 \\ [
260 \\ 1,260 \\ 1,
...@@ -266,7 +266,7 @@ test "Value.jsonStringify" {...@@ -266,7 +266,7 @@ test "Value.jsonStringify" {
266 \\ }266 \\ }
267 \\]267 \\]
268 ;268 ;
269 try testing.expectEqualSlices(u8, expected, fbs.getWritten());269 try testing.expectEqualStrings(expected, fbs.getWritten());
270}270}
271271
272test "parseFromValue(std.json.Value,...)" {272test "parseFromValue(std.json.Value,...)" {
lib/std/json/fmt.zig+3-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,7 @@ pub fn Formatter(comptime T: type) type {...@@ -14,14 +15,7 @@ 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) std.io.Writer.Error!void {
18 self: @This(),
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);19 try stringify(self.value, self.options, writer);
26 }20 }
27 };21 };
lib/std/json/scanner.zig+1-1
...@@ -219,7 +219,7 @@ pub const AllocWhen = enum { alloc_if_needed, alloc_always };...@@ -219,7 +219,7 @@ pub const AllocWhen = enum { alloc_if_needed, alloc_always };
219/// This limit can be specified by calling `nextAllocMax()` instead of `nextAlloc()`.219/// This limit can be specified by calling `nextAllocMax()` instead of `nextAlloc()`.
220pub const default_max_value_len = 4 * 1024 * 1024;220pub const default_max_value_len = 4 * 1024 * 1024;
221221
222/// Connects a `std.io.Reader` to a `std.json.Scanner`.222/// Connects a `std.io.GenericReader` to a `std.json.Scanner`.
223/// All `next*()` methods here handle `error.BufferUnderrun` from `std.json.Scanner`, and then read from the reader.223/// All `next*()` methods here handle `error.BufferUnderrun` from `std.json.Scanner`, and then read from the reader.
224pub fn Reader(comptime buffer_size: usize, comptime ReaderType: type) type {224pub fn Reader(comptime buffer_size: usize, comptime ReaderType: type) type {
225 return struct {225 return struct {
lib/std/json/stringify.zig+8-6
...@@ -38,7 +38,7 @@ pub const StringifyOptions = struct {...@@ -38,7 +38,7 @@ pub const StringifyOptions = struct {
38 emit_nonportable_numbers_as_strings: bool = false,38 emit_nonportable_numbers_as_strings: bool = false,
39};39};
4040
41/// Writes the given value to the `std.io.Writer` stream.41/// Writes the given value to the `std.io.GenericWriter` stream.
42/// See `WriteStream` for how the given value is serialized into JSON.42/// See `WriteStream` for how the given value is serialized into JSON.
43/// The maximum nesting depth of the output JSON document is 256.43/// The maximum nesting depth of the output JSON document is 256.
44/// See also `stringifyMaxDepth` and `stringifyArbitraryDepth`.44/// See also `stringifyMaxDepth` and `stringifyArbitraryDepth`.
...@@ -81,7 +81,7 @@ pub fn stringifyArbitraryDepth(...@@ -81,7 +81,7 @@ pub fn stringifyArbitraryDepth(
81}81}
8282
83/// Calls `stringifyArbitraryDepth` and stores the result in dynamically allocated memory83/// Calls `stringifyArbitraryDepth` and stores the result in dynamically allocated memory
84/// instead of taking a `std.io.Writer`.84/// instead of taking a `std.io.GenericWriter`.
85///85///
86/// Caller owns returned memory.86/// Caller owns returned memory.
87pub fn stringifyAlloc(87pub fn stringifyAlloc(
...@@ -469,7 +469,6 @@ pub fn WriteStream(...@@ -469,7 +469,6 @@ pub fn WriteStream(
469 /// * When option `emit_nonportable_numbers_as_strings` is true, if the value is outside the range `+-1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number.469 /// * When option `emit_nonportable_numbers_as_strings` is true, if the value is outside the range `+-1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number.
470 /// * Zig floats -> JSON number or string.470 /// * Zig floats -> JSON number or string.
471 /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number.471 /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number.
472 /// * TODO: Float rendering will likely change in the future, e.g. to remove the unnecessary "e+00".
473 /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string.472 /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string.
474 /// * See `StringifyOptions.emit_strings_as_arrays`.473 /// * See `StringifyOptions.emit_strings_as_arrays`.
475 /// * If the content is not valid UTF-8, rendered as an array of numbers instead.474 /// * If the content is not valid UTF-8, rendered as an array of numbers instead.
...@@ -689,7 +688,8 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {...@@ -689,7 +688,8 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
689 // then it may be represented as a six-character sequence: a reverse solidus, followed688 // 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.689 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
691 try out_stream.writeAll("\\u");690 try out_stream.writeAll("\\u");
692 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);691 //try w.printInt("x", .{ .width = 4, .fill = '0' }, codepoint);
692 try std.fmt.format(out_stream, "{x:0>4}", .{codepoint});
693 } else {693 } else {
694 assert(codepoint <= 0x10FFFF);694 assert(codepoint <= 0x10FFFF);
695 // To escape an extended character that is not in the Basic Multilingual Plane,695 // To escape an extended character that is not in the Basic Multilingual Plane,
...@@ -697,9 +697,11 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {...@@ -697,9 +697,11 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
697 const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;697 const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;
698 const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;698 const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;
699 try out_stream.writeAll("\\u");699 try out_stream.writeAll("\\u");
700 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);700 //try w.printInt("x", .{ .width = 4, .fill = '0' }, high);
701 try std.fmt.format(out_stream, "{x:0>4}", .{high});
701 try out_stream.writeAll("\\u");702 try out_stream.writeAll("\\u");
702 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);703 //try w.printInt("x", .{ .width = 4, .fill = '0' }, low);
704 try std.fmt.format(out_stream, "{x:0>4}", .{low});
703 }705 }
704}706}
705707
lib/std/json/stringify_test.zig+7-7
...@@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void {...@@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void {
74 \\{74 \\{
75 \\ "object": {75 \\ "object": {
76 \\ "one": 1,76 \\ "one": 1,
77 \\ "two": 2e077 \\ "two": 2
78 \\ },78 \\ },
79 \\ "string": "This is a string",79 \\ "string": "This is a string",
80 \\ "array": [80 \\ "array": [
81 \\ "Another string",81 \\ "Another string",
82 \\ 1,82 \\ 1,
83 \\ 3.5e083 \\ 3.5
84 \\ ],84 \\ ],
85 \\ "int": 10,85 \\ "int": 10,
86 \\ "float": 3.5e086 \\ "float": 3.5
87 \\}87 \\}
88 ;88 ;
89 try std.testing.expectEqualStrings(expected, result);89 try std.testing.expectEqualStrings(expected, result);
...@@ -123,12 +123,12 @@ test "stringify basic types" {...@@ -123,12 +123,12 @@ test "stringify basic types" {
123 try testStringify("null", @as(?u8, null), .{});123 try testStringify("null", @as(?u8, null), .{});
124 try testStringify("null", @as(?*u32, null), .{});124 try testStringify("null", @as(?*u32, null), .{});
125 try testStringify("42", 42, .{});125 try testStringify("42", 42, .{});
126 try testStringify("4.2e1", 42.0, .{});126 try testStringify("42", 42.0, .{});
127 try testStringify("42", @as(u8, 42), .{});127 try testStringify("42", @as(u8, 42), .{});
128 try testStringify("42", @as(u128, 42), .{});128 try testStringify("42", @as(u128, 42), .{});
129 try testStringify("9999999999999999", 9999999999999999, .{});129 try testStringify("9999999999999999", 9999999999999999, .{});
130 try testStringify("4.2e1", @as(f32, 42), .{});130 try testStringify("42", @as(f32, 42), .{});
131 try testStringify("4.2e1", @as(f64, 42), .{});131 try testStringify("42", @as(f64, 42), .{});
132 try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{});132 try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{});
133 try testStringify("\"ItBroke\"", error.ItBroke, .{});133 try testStringify("\"ItBroke\"", error.ItBroke, .{});
134}134}
...@@ -307,7 +307,7 @@ test "stringify tuple" {...@@ -307,7 +307,7 @@ test "stringify tuple" {
307fn testStringify(expected: []const u8, value: anytype, options: StringifyOptions) !void {307fn testStringify(expected: []const u8, value: anytype, options: StringifyOptions) !void {
308 const ValidationWriter = struct {308 const ValidationWriter = struct {
309 const Self = @This();309 const Self = @This();
310 pub const Writer = std.io.Writer(*Self, Error, write);310 pub const Writer = std.io.GenericWriter(*Self, Error, write);
311 pub const Error = error{311 pub const Error = error{
312 TooMuchData,312 TooMuchData,
313 DifferentData,313 DifferentData,
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.io.getStdErr().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.io.getStdErr().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+21-39
...@@ -2028,6 +2028,14 @@ pub const Mutable = struct {...@@ -2028,6 +2028,14 @@ pub const Mutable = struct {
2028 pub fn normalize(r: *Mutable, length: usize) void {2028 pub fn normalize(r: *Mutable, length: usize) void {
2029 r.len = llnormalize(r.limbs[0..length]);2029 r.len = llnormalize(r.limbs[0..length]);
2030 }2030 }
2031
2032 pub fn format(self: Mutable, w: *std.io.Writer) std.io.Writer.Error!void {
2033 return formatNumber(self, w, .{});
2034 }
2035
2036 pub fn formatNumber(self: Const, w: *std.io.Writer, n: std.fmt.Number) std.io.Writer.Error!void {
2037 return self.toConst().formatNumber(w, n);
2038 }
2031};2039};
20322040
2033/// A arbitrary-precision big integer, with a fixed set of immutable limbs.2041/// A arbitrary-precision big integer, with a fixed set of immutable limbs.
...@@ -2317,50 +2325,25 @@ pub const Const = struct {...@@ -2317,50 +2325,25 @@ pub const Const = struct {
2317 return .{ normalized_res.reconstruct(if (self.positive) .positive else .negative), exactness };2325 return .{ normalized_res.reconstruct(if (self.positive) .positive else .negative), exactness };
2318 }2326 }
23192327
2320 /// To allow `std.fmt.format` to work with this type.
2321 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,2328 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,
2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2329 /// 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.2330 /// 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.2331 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2325 pub fn format(2332 pub fn formatNumber(self: Const, w: *std.io.Writer, number: std.fmt.Number) 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;
2333 comptime var case: std.fmt.Case = .lower;
2334
2335 if (fmt.len == 0 or comptime mem.eql(u8, fmt, "d")) {
2336 base = 10;
2337 case = .lower;
2338 } else if (comptime mem.eql(u8, fmt, "b")) {
2339 base = 2;
2340 case = .lower;
2341 } else if (comptime mem.eql(u8, fmt, "x")) {
2342 base = 16;
2343 case = .lower;
2344 } else if (comptime mem.eql(u8, fmt, "X")) {
2345 base = 16;
2346 case = .upper;
2347 } else {
2348 std.fmt.invalidFmtError(fmt, self);
2349 }
2350
2351 const available_len = 64;2333 const available_len = 64;
2352 if (self.limbs.len > available_len)2334 if (self.limbs.len > available_len)
2353 return out_stream.writeAll("(BigInt)");2335 return w.writeAll("(BigInt)");
23542336
2355 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;2337 var limbs: [calcToStringLimbsBufferLen(available_len, 10)]Limb = undefined;
23562338
2357 const biggest: Const = .{2339 const biggest: Const = .{
2358 .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len),2340 .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len),
2359 .positive = false,2341 .positive = false,
2360 };2342 };
2361 var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;2343 var buf: [biggest.sizeInBaseUpperBound(2)]u8 = undefined;
2362 const len = self.toString(&buf, base, case, &limbs);2344 const base: u8 = number.mode.base() orelse @panic("TODO print big int in scientific form");
2363 return out_stream.writeAll(buf[0..len]);2345 const len = self.toString(&buf, base, number.case, &limbs);
2346 return w.writeAll(buf[0..len]);
2364 }2347 }
23652348
2366 /// Converts self to a string in the requested base.2349 /// Converts self to a string in the requested base.
...@@ -2930,17 +2913,16 @@ pub const Managed = struct {...@@ -2930,17 +2913,16 @@ pub const Managed = struct {
2930 }2913 }
29312914
2932 /// To allow `std.fmt.format` to work with `Managed`.2915 /// To allow `std.fmt.format` to work with `Managed`.
2916 pub fn format(self: Managed, w: *std.io.Writer) std.io.Writer.Error!void {
2917 return formatNumber(self, w, .{});
2918 }
2919
2933 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,2920 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,
2934 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2921 /// 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.2922 /// 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.2923 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2937 pub fn format(2924 pub fn formatNumber(self: Managed, w: *std.io.Writer, n: std.fmt.Number) std.io.Writer.Error!void {
2938 self: Managed,2925 return self.toConst().formatNumber(w, n);
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 }2926 }
29452927
2946 /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==2928 /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==
lib/std/math/big/int_test.zig+4-7
...@@ -3813,13 +3813,10 @@ test "(BigInt) positive" {...@@ -3813,13 +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 try testing.expectFmt("(BigInt)", "{d}", .{a});
3817 defer testing.allocator.free(a_fmt);
38183817
3819 const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});3818 const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b});
3820 defer testing.allocator.free(b_fmt);3819 defer testing.allocator.free(b_fmt);
3821
3822 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
3823 try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)"));3820 try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)"));
3824}3821}
38253822
...@@ -3838,10 +3835,10 @@ test "(BigInt) negative" {...@@ -3838,10 +3835,10 @@ test "(BigInt) negative" {
3838 a.negate();3835 a.negate();
3839 try b.add(&a, &c);3836 try b.add(&a, &c);
38403837
3841 const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});3838 const a_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{a});
3842 defer testing.allocator.free(a_fmt);3839 defer testing.allocator.free(a_fmt);
38433840
3844 const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});3841 const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b});
3845 defer testing.allocator.free(b_fmt);3842 defer testing.allocator.free(b_fmt);
38463843
3847 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));3844 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
lib/std/mem.zig+4-2
...@@ -1714,7 +1714,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: Endian)...@@ -1714,7 +1714,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: Endian)
1714 }1714 }
1715 },1715 },
1716 }1716 }
1717 return @as(ReturnType, @truncate(result));1717 return @truncate(result);
1718}1718}
17191719
1720test readVarInt {1720test readVarInt {
...@@ -2196,7 +2196,9 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {...@@ -2196,7 +2196,9 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
2196 }2196 }
2197 }2197 }
2198 },2198 },
2199 else => @compileError("byteSwapAllFields expects a struct or array as the first argument"),2199 else => {
2200 ptr.* = @byteSwap(ptr.*);
2201 },
2200 }2202 }
2201}2203}
22022204
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+21-50
...@@ -161,22 +161,13 @@ pub const Address = extern union {...@@ -161,22 +161,13 @@ pub const Address = extern union {
161 }161 }
162 }162 }
163163
164 pub fn format(164 pub fn format(self: Address, w: *std.io.Writer) std.io.Writer.Error!void {
165 self: Address,
166 comptime fmt: []const u8,
167 options: std.fmt.FormatOptions,
168 out_stream: anytype,
169 ) !void {
170 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
171 switch (self.any.family) {165 switch (self.any.family) {
172 posix.AF.INET => try self.in.format(fmt, options, out_stream),166 posix.AF.INET => try self.in.format(w),
173 posix.AF.INET6 => try self.in6.format(fmt, options, out_stream),167 posix.AF.INET6 => try self.in6.format(w),
174 posix.AF.UNIX => {168 posix.AF.UNIX => {
175 if (!has_unix_sockets) {169 if (!has_unix_sockets) unreachable;
176 unreachable;170 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 },171 },
181 else => unreachable,172 else => unreachable,
182 }173 }
...@@ -349,22 +340,9 @@ pub const Ip4Address = extern struct {...@@ -349,22 +340,9 @@ pub const Ip4Address = extern struct {
349 self.sa.port = mem.nativeToBig(u16, port);340 self.sa.port = mem.nativeToBig(u16, port);
350 }341 }
351342
352 pub fn format(343 pub fn format(self: Ip4Address, w: *std.io.Writer) std.io.Writer.Error!void {
353 self: Ip4Address,344 const bytes: *const [4]u8 = @ptrCast(&self.sa.addr);
354 comptime fmt: []const u8,345 try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() });
355 options: std.fmt.FormatOptions,
356 out_stream: anytype,
357 ) !void {
358 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
359 _ = options;
360 const bytes = @as(*const [4]u8, @ptrCast(&self.sa.addr));
361 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
362 bytes[0],
363 bytes[1],
364 bytes[2],
365 bytes[3],
366 self.getPort(),
367 });
368 }346 }
369347
370 pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {348 pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {
...@@ -653,17 +631,10 @@ pub const Ip6Address = extern struct {...@@ -653,17 +631,10 @@ pub const Ip6Address = extern struct {
653 self.sa.port = mem.nativeToBig(u16, port);631 self.sa.port = mem.nativeToBig(u16, port);
654 }632 }
655633
656 pub fn format(634 pub fn format(self: Ip6Address, w: *std.io.Writer) std.io.Writer.Error!void {
657 self: Ip6Address,
658 comptime fmt: []const u8,
659 options: std.fmt.FormatOptions,
660 out_stream: anytype,
661 ) !void {
662 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
663 _ = options;
664 const port = mem.bigToNative(u16, self.sa.port);635 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 })) {636 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:{}.{}.{}.{}]:{}", .{637 try w.print("[::ffff:{d}.{d}.{d}.{d}]:{d}", .{
667 self.sa.addr[12],638 self.sa.addr[12],
668 self.sa.addr[13],639 self.sa.addr[13],
669 self.sa.addr[14],640 self.sa.addr[14],
...@@ -711,14 +682,14 @@ pub const Ip6Address = extern struct {...@@ -711,14 +682,14 @@ pub const Ip6Address = extern struct {
711 longest_len = 0;682 longest_len = 0;
712 }683 }
713684
714 try out_stream.writeAll("[");685 try w.writeAll("[");
715 var i: usize = 0;686 var i: usize = 0;
716 var abbrv = false;687 var abbrv = false;
717 while (i < native_endian_parts.len) : (i += 1) {688 while (i < native_endian_parts.len) : (i += 1) {
718 if (i == longest_start) {689 if (i == longest_start) {
719 // Emit "::" for the longest zero run690 // Emit "::" for the longest zero run
720 if (!abbrv) {691 if (!abbrv) {
721 try out_stream.writeAll(if (i == 0) "::" else ":");692 try w.writeAll(if (i == 0) "::" else ":");
722 abbrv = true;693 abbrv = true;
723 }694 }
724 i += longest_len - 1; // Skip the compressed range695 i += longest_len - 1; // Skip the compressed range
...@@ -727,12 +698,12 @@ pub const Ip6Address = extern struct {...@@ -727,12 +698,12 @@ pub const Ip6Address = extern struct {
727 if (abbrv) {698 if (abbrv) {
728 abbrv = false;699 abbrv = false;
729 }700 }
730 try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});701 try w.print("{x}", .{native_endian_parts[i]});
731 if (i != native_endian_parts.len - 1) {702 if (i != native_endian_parts.len - 1) {
732 try out_stream.writeAll(":");703 try w.writeAll(":");
733 }704 }
734 }705 }
735 try std.fmt.format(out_stream, "]:{}", .{port});706 try w.print("]:{}", .{port});
736 }707 }
737708
738 pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {709 pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {
...@@ -894,7 +865,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get...@@ -894,7 +865,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
894 const name_c = try allocator.dupeZ(u8, name);865 const name_c = try allocator.dupeZ(u8, name);
895 defer allocator.free(name_c);866 defer allocator.free(name_c);
896867
897 const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port});868 const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0);
898 defer allocator.free(port_c);869 defer allocator.free(port_c);
899870
900 const ws2_32 = windows.ws2_32;871 const ws2_32 = windows.ws2_32;
...@@ -966,7 +937,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get...@@ -966,7 +937,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
966 const name_c = try allocator.dupeZ(u8, name);937 const name_c = try allocator.dupeZ(u8, name);
967 defer allocator.free(name_c);938 defer allocator.free(name_c);
968939
969 const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port});940 const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0);
970 defer allocator.free(port_c);941 defer allocator.free(port_c);
971942
972 const hints: posix.addrinfo = .{943 const hints: posix.addrinfo = .{
...@@ -1356,7 +1327,7 @@ fn linuxLookupNameFromHosts(...@@ -1356,7 +1327,7 @@ fn linuxLookupNameFromHosts(
1356 };1327 };
1357 defer file.close();1328 defer file.close();
13581329
1359 var buffered_reader = std.io.bufferedReader(file.reader());1330 var buffered_reader = std.io.bufferedReader(file.deprecatedReader());
1360 const reader = buffered_reader.reader();1331 const reader = buffered_reader.reader();
1361 var line_buf: [512]u8 = undefined;1332 var line_buf: [512]u8 = undefined;
1362 while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {1333 while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
...@@ -1557,7 +1528,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {...@@ -1557,7 +1528,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
1557 };1528 };
1558 defer file.close();1529 defer file.close();
15591530
1560 var buf_reader = std.io.bufferedReader(file.reader());1531 var buf_reader = std.io.bufferedReader(file.deprecatedReader());
1561 const stream = buf_reader.reader();1532 const stream = buf_reader.reader();
1562 var line_buf: [512]u8 = undefined;1533 var line_buf: [512]u8 = undefined;
1563 while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {1534 while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
...@@ -1845,8 +1816,8 @@ pub const Stream = struct {...@@ -1845,8 +1816,8 @@ pub const Stream = struct {
1845 pub const ReadError = posix.ReadError;1816 pub const ReadError = posix.ReadError;
1846 pub const WriteError = posix.WriteError;1817 pub const WriteError = posix.WriteError;
18471818
1848 pub const Reader = io.Reader(Stream, ReadError, read);1819 pub const Reader = io.GenericReader(Stream, ReadError, read);
1849 pub const Writer = io.Writer(Stream, WriteError, write);1820 pub const Writer = io.GenericWriter(Stream, WriteError, write);
18501821
1851 pub fn reader(self: Stream) Reader {1822 pub fn reader(self: Stream) Reader {
1852 return .{ .context = self };1823 return .{ .context = self };
lib/std/net/test.zig+16-53
...@@ -5,20 +5,13 @@ const mem = std.mem;...@@ -5,20 +5,13 @@ const mem = std.mem;
5const testing = std.testing;5const testing = std.testing;
66
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;
9 comptime {8 comptime {
10 var ipAddrBuffer: [16]u8 = undefined;
11 // Parses IPv6 at comptime
12 const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;9 const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
13 var ipv6 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv6addr}) catch unreachable;10 try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr});
14 try std.testing.expect(std.mem.eql(u8, "::1", ipv6[1 .. ipv6.len - 3]));
1511
16 // Parses IPv4 at comptime
17 const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;12 const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;
18 var ipv4 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv4addr}) catch unreachable;13 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]));
2014
21 // Returns error for invalid IP addresses at comptime
22 try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0));15 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));16 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));17 try testing.expectError(error.InvalidIPAddressFormat, net.Address.resolveIp("::123.123.123.123", 0));
...@@ -27,47 +20,23 @@ test "parse and render IP addresses at comptime" {...@@ -27,47 +20,23 @@ test "parse and render IP addresses at comptime" {
27}20}
2821
29test "format IPv6 address with no zero runs" {22test "format IPv6 address with no zero runs" {
30 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);23 const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);
3324 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}25}
3926
40test "parse IPv6 addresses and check compressed form" {27test "parse IPv6 addresses and check compressed form" {
41 if (builtin.os.tag == .wasi) return error.SkipZigTest;28 try std.testing.expectFmt("[2001:db8::1:0:0:2]:0", "{f}", .{
4229 try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0),
43 const alloc = testing.allocator;30 });
4431 try std.testing.expectFmt("[2001:db8::1:2]:0", "{f}", .{
45 // 1) Parse an IPv6 address that should compress to [2001:db8::1:0:0:2]:032 try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0),
46 const addr1 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0);33 });
4734 try std.testing.expectFmt("[2001:db8:1:0:1::2]:0", "{f}", .{
48 // 2) Parse an IPv6 address that should compress to [2001:db8::1:2]:035 try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0),
49 const addr2 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0);36 });
50
51 // 3) Parse an IPv6 address that should compress to [2001:db8:1:0:1::2]:0
52 const addr3 = try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0);
53
54 // Print each address in Zig's default "[ipv6]:port" form.
55 const printed1 = try std.fmt.allocPrint(alloc, "{any}", .{addr1});
56 defer testing.allocator.free(printed1);
57 const printed2 = try std.fmt.allocPrint(alloc, "{any}", .{addr2});
58 defer testing.allocator.free(printed2);
59 const printed3 = try std.fmt.allocPrint(alloc, "{any}", .{addr3});
60 defer testing.allocator.free(printed3);
61
62 // Check the exact compressed forms we expect.
63 try std.testing.expectEqualStrings("[2001:db8::1:0:0:2]:0", printed1);
64 try std.testing.expectEqualStrings("[2001:db8::1:2]:0", printed2);
65 try std.testing.expectEqualStrings("[2001:db8:1:0:1::2]:0", printed3);
66}37}
6738
68test "parse IPv6 address, check raw bytes" {39test "parse IPv6 address, check raw bytes" {
69 if (builtin.os.tag == .wasi) return error.SkipZigTest;
70
71 const expected_raw: [16]u8 = .{40 const expected_raw: [16]u8 = .{
72 0x20, 0x01, 0x0d, 0xb8, // 2001:db841 0x20, 0x01, 0x0d, 0xb8, // 2001:db8
73 0x00, 0x00, 0x00, 0x00, // :0000:000042 0x00, 0x00, 0x00, 0x00, // :0000:0000
...@@ -82,8 +51,6 @@ test "parse IPv6 address, check raw bytes" {...@@ -82,8 +51,6 @@ test "parse IPv6 address, check raw bytes" {
82}51}
8352
84test "parse and render IPv6 addresses" {53test "parse and render IPv6 addresses" {
85 if (builtin.os.tag == .wasi) return error.SkipZigTest;
86
87 var buffer: [100]u8 = undefined;54 var buffer: [100]u8 = undefined;
88 const ips = [_][]const u8{55 const ips = [_][]const u8{
89 "FF01:0:0:0:0:0:0:FB",56 "FF01:0:0:0:0:0:0:FB",
...@@ -111,12 +78,12 @@ test "parse and render IPv6 addresses" {...@@ -111,12 +78,12 @@ test "parse and render IPv6 addresses" {
111 };78 };
112 for (ips, 0..) |ip, i| {79 for (ips, 0..) |ip, i| {
113 const addr = net.Address.parseIp6(ip, 0) catch unreachable;80 const addr = net.Address.parseIp6(ip, 0) catch unreachable;
114 var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;81 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]));82 try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
11683
117 if (builtin.os.tag == .linux) {84 if (builtin.os.tag == .linux) {
118 const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;85 const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;
119 var newResolvedIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr_via_resolve}) catch unreachable;86 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]));87 try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));
121 }88 }
122 }89 }
...@@ -148,8 +115,6 @@ test "invalid but parseable IPv6 scope ids" {...@@ -148,8 +115,6 @@ test "invalid but parseable IPv6 scope ids" {
148}115}
149116
150test "parse and render IPv4 addresses" {117test "parse and render IPv4 addresses" {
151 if (builtin.os.tag == .wasi) return error.SkipZigTest;
152
153 var buffer: [18]u8 = undefined;118 var buffer: [18]u8 = undefined;
154 for ([_][]const u8{119 for ([_][]const u8{
155 "0.0.0.0",120 "0.0.0.0",
...@@ -159,7 +124,7 @@ test "parse and render IPv4 addresses" {...@@ -159,7 +124,7 @@ test "parse and render IPv4 addresses" {
159 "127.0.0.1",124 "127.0.0.1",
160 }) |ip| {125 }) |ip| {
161 const addr = net.Address.parseIp4(ip, 0) catch unreachable;126 const addr = net.Address.parseIp4(ip, 0) catch unreachable;
162 var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;127 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]));128 try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
164 }129 }
165130
...@@ -175,10 +140,8 @@ test "parse and render UNIX addresses" {...@@ -175,10 +140,8 @@ test "parse and render UNIX addresses" {
175 if (builtin.os.tag == .wasi) return error.SkipZigTest;140 if (builtin.os.tag == .wasi) return error.SkipZigTest;
176 if (!net.has_unix_sockets) return error.SkipZigTest;141 if (!net.has_unix_sockets) return error.SkipZigTest;
177142
178 var buffer: [14]u8 = undefined;
179 const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;143 const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;
180 const fmt_addr = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;144 try std.testing.expectFmt("/tmp/testpath", "{f}", .{addr});
181 try std.testing.expectEqualSlices(u8, "/tmp/testpath", fmt_addr);
182145
183 const too_long = [_]u8{'a'} ** 200;146 const too_long = [_]u8{'a'} ** 200;
184 try testing.expectError(error.NameTooLong, net.Address.initUnix(too_long[0..]));147 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 = std.posix.UnexpectedError || 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+148-2
...@@ -103,8 +103,6 @@ pub const dev_t = arch_bits.dev_t;...@@ -103,8 +103,6 @@ pub const dev_t = arch_bits.dev_t;
103pub const ino_t = arch_bits.ino_t;103pub const ino_t = arch_bits.ino_t;
104pub const mcontext_t = arch_bits.mcontext_t;104pub const mcontext_t = arch_bits.mcontext_t;
105pub const mode_t = arch_bits.mode_t;105pub const mode_t = arch_bits.mode_t;
106pub const msghdr = arch_bits.msghdr;
107pub const msghdr_const = arch_bits.msghdr_const;
108pub const nlink_t = arch_bits.nlink_t;106pub const nlink_t = arch_bits.nlink_t;
109pub const off_t = arch_bits.off_t;107pub const off_t = arch_bits.off_t;
110pub const time_t = arch_bits.time_t;108pub const time_t = arch_bits.time_t;
...@@ -9403,3 +9401,151 @@ pub const SHADOW_STACK = struct {...@@ -9403,3 +9401,151 @@ pub const SHADOW_STACK = struct {
9403 /// Set up a restore token in the shadow stack.9401 /// Set up a restore token in the shadow stack.
9404 pub const SET_TOKEN: u64 = 1 << 0;9402 pub const SET_TOKEN: u64 = 1 << 0;
9405};9403};
9404
9405pub const msghdr = extern struct {
9406 name: ?*sockaddr,
9407 namelen: socklen_t,
9408 iov: [*]iovec,
9409 iovlen: usize,
9410 control: ?*anyopaque,
9411 controllen: usize,
9412 flags: u32,
9413};
9414
9415pub const msghdr_const = extern struct {
9416 name: ?*const sockaddr,
9417 namelen: socklen_t,
9418 iov: [*]const iovec_const,
9419 iovlen: usize,
9420 control: ?*const anyopaque,
9421 controllen: usize,
9422 flags: u32,
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/linux/aarch64.zig-24
...@@ -199,30 +199,6 @@ pub const Flock = extern struct {...@@ -199,30 +199,6 @@ pub const Flock = extern struct {
199 __unused: [4]u8,199 __unused: [4]u8,
200};200};
201201
202pub const msghdr = extern struct {
203 name: ?*sockaddr,
204 namelen: socklen_t,
205 iov: [*]iovec,
206 iovlen: i32,
207 __pad1: i32 = 0,
208 control: ?*anyopaque,
209 controllen: socklen_t,
210 __pad2: socklen_t = 0,
211 flags: i32,
212};
213
214pub const msghdr_const = extern struct {
215 name: ?*const sockaddr,
216 namelen: socklen_t,
217 iov: [*]const iovec_const,
218 iovlen: i32,
219 __pad1: i32 = 0,
220 control: ?*const anyopaque,
221 controllen: socklen_t,
222 __pad2: socklen_t = 0,
223 flags: i32,
224};
225
226pub const blksize_t = i32;202pub const blksize_t = i32;
227pub const nlink_t = u32;203pub const nlink_t = u32;
228pub const time_t = isize;204pub const time_t = isize;
lib/std/os/linux/arm.zig-20
...@@ -237,26 +237,6 @@ pub const Flock = extern struct {...@@ -237,26 +237,6 @@ pub const Flock = extern struct {
237 __unused: [4]u8,237 __unused: [4]u8,
238};238};
239239
240pub const msghdr = extern struct {
241 name: ?*sockaddr,
242 namelen: socklen_t,
243 iov: [*]iovec,
244 iovlen: i32,
245 control: ?*anyopaque,
246 controllen: socklen_t,
247 flags: i32,
248};
249
250pub const msghdr_const = extern struct {
251 name: ?*const sockaddr,
252 namelen: socklen_t,
253 iov: [*]const iovec_const,
254 iovlen: i32,
255 control: ?*const anyopaque,
256 controllen: socklen_t,
257 flags: i32,
258};
259
260pub const blksize_t = i32;240pub const blksize_t = i32;
261pub const nlink_t = u32;241pub const nlink_t = u32;
262pub const time_t = isize;242pub const time_t = isize;
lib/std/os/linux/mips.zig-20
...@@ -309,26 +309,6 @@ pub const Flock = extern struct {...@@ -309,26 +309,6 @@ pub const Flock = extern struct {
309 __unused: [4]u8,309 __unused: [4]u8,
310};310};
311311
312pub const msghdr = extern struct {
313 name: ?*sockaddr,
314 namelen: socklen_t,
315 iov: [*]iovec,
316 iovlen: i32,
317 control: ?*anyopaque,
318 controllen: socklen_t,
319 flags: i32,
320};
321
322pub const msghdr_const = extern struct {
323 name: ?*const sockaddr,
324 namelen: socklen_t,
325 iov: [*]const iovec_const,
326 iovlen: i32,
327 control: ?*const anyopaque,
328 controllen: socklen_t,
329 flags: i32,
330};
331
332pub const blksize_t = u32;312pub const blksize_t = u32;
333pub const nlink_t = u32;313pub const nlink_t = u32;
334pub const time_t = i32;314pub const time_t = i32;
lib/std/os/linux/mips64.zig-20
...@@ -288,26 +288,6 @@ pub const Flock = extern struct {...@@ -288,26 +288,6 @@ pub const Flock = extern struct {
288 __unused: [4]u8,288 __unused: [4]u8,
289};289};
290290
291pub const msghdr = extern struct {
292 name: ?*sockaddr,
293 namelen: socklen_t,
294 iov: [*]iovec,
295 iovlen: i32,
296 control: ?*anyopaque,
297 controllen: socklen_t,
298 flags: i32,
299};
300
301pub const msghdr_const = extern struct {
302 name: ?*const sockaddr,
303 namelen: socklen_t,
304 iov: [*]const iovec_const,
305 iovlen: i32,
306 control: ?*const anyopaque,
307 controllen: socklen_t,
308 flags: i32,
309};
310
311pub const blksize_t = u32;291pub const blksize_t = u32;
312pub const nlink_t = u32;292pub const nlink_t = u32;
313pub const time_t = i32;293pub const time_t = i32;
lib/std/os/linux/powerpc.zig-20
...@@ -247,26 +247,6 @@ pub const Flock = extern struct {...@@ -247,26 +247,6 @@ pub const Flock = extern struct {
247 pid: pid_t,247 pid: pid_t,
248};248};
249249
250pub const msghdr = extern struct {
251 name: ?*sockaddr,
252 namelen: socklen_t,
253 iov: [*]iovec,
254 iovlen: usize,
255 control: ?*anyopaque,
256 controllen: socklen_t,
257 flags: i32,
258};
259
260pub const msghdr_const = extern struct {
261 name: ?*const sockaddr,
262 namelen: socklen_t,
263 iov: [*]const iovec_const,
264 iovlen: usize,
265 control: ?*const anyopaque,
266 controllen: socklen_t,
267 flags: i32,
268};
269
270pub const blksize_t = i32;250pub const blksize_t = i32;
271pub const nlink_t = u32;251pub const nlink_t = u32;
272pub const time_t = isize;252pub const time_t = isize;
lib/std/os/linux/powerpc64.zig-20
...@@ -233,26 +233,6 @@ pub const Flock = extern struct {...@@ -233,26 +233,6 @@ pub const Flock = extern struct {
233 __unused: [4]u8,233 __unused: [4]u8,
234};234};
235235
236pub const msghdr = extern struct {
237 name: ?*sockaddr,
238 namelen: socklen_t,
239 iov: [*]iovec,
240 iovlen: usize,
241 control: ?*anyopaque,
242 controllen: usize,
243 flags: i32,
244};
245
246pub const msghdr_const = extern struct {
247 name: ?*const sockaddr,
248 namelen: socklen_t,
249 iov: [*]const iovec_const,
250 iovlen: usize,
251 control: ?*const anyopaque,
252 controllen: usize,
253 flags: i32,
254};
255
256pub const blksize_t = i64;236pub const blksize_t = i64;
257pub const nlink_t = u64;237pub const nlink_t = u64;
258pub const time_t = i64;238pub const time_t = i64;
lib/std/os/linux/riscv32.zig-24
...@@ -200,30 +200,6 @@ pub const Flock = extern struct {...@@ -200,30 +200,6 @@ pub const Flock = extern struct {
200 __unused: [4]u8,200 __unused: [4]u8,
201};201};
202202
203pub const msghdr = extern struct {
204 name: ?*sockaddr,
205 namelen: socklen_t,
206 iov: [*]iovec,
207 iovlen: i32,
208 __pad1: i32 = 0,
209 control: ?*anyopaque,
210 controllen: socklen_t,
211 __pad2: socklen_t = 0,
212 flags: i32,
213};
214
215pub const msghdr_const = extern struct {
216 name: ?*const sockaddr,
217 namelen: socklen_t,
218 iov: [*]const iovec_const,
219 iovlen: i32,
220 __pad1: i32 = 0,
221 control: ?*const anyopaque,
222 controllen: socklen_t,
223 __pad2: socklen_t = 0,
224 flags: i32,
225};
226
227// The `stat` definition used by the Linux kernel.203// The `stat` definition used by the Linux kernel.
228pub const Stat = extern struct {204pub const Stat = extern struct {
229 dev: dev_t,205 dev: dev_t,
lib/std/os/linux/riscv64.zig-24
...@@ -200,30 +200,6 @@ pub const Flock = extern struct {...@@ -200,30 +200,6 @@ pub const Flock = extern struct {
200 __unused: [4]u8,200 __unused: [4]u8,
201};201};
202202
203pub const msghdr = extern struct {
204 name: ?*sockaddr,
205 namelen: socklen_t,
206 iov: [*]iovec,
207 iovlen: i32,
208 __pad1: i32 = 0,
209 control: ?*anyopaque,
210 controllen: socklen_t,
211 __pad2: socklen_t = 0,
212 flags: i32,
213};
214
215pub const msghdr_const = extern struct {
216 name: ?*const sockaddr,
217 namelen: socklen_t,
218 iov: [*]const iovec_const,
219 iovlen: i32,
220 __pad1: i32 = 0,
221 control: ?*const anyopaque,
222 controllen: socklen_t,
223 __pad2: socklen_t = 0,
224 flags: i32,
225};
226
227// The `stat` definition used by the Linux kernel.203// The `stat` definition used by the Linux kernel.
228pub const Stat = extern struct {204pub const Stat = extern struct {
229 dev: dev_t,205 dev: dev_t,
lib/std/os/linux/sparc64.zig-20
...@@ -282,26 +282,6 @@ pub const Flock = extern struct {...@@ -282,26 +282,6 @@ pub const Flock = extern struct {
282 pid: pid_t,282 pid: pid_t,
283};283};
284284
285pub const msghdr = extern struct {
286 name: ?*sockaddr,
287 namelen: socklen_t,
288 iov: [*]iovec,
289 iovlen: u64,
290 control: ?*anyopaque,
291 controllen: u64,
292 flags: i32,
293};
294
295pub const msghdr_const = extern struct {
296 name: ?*const sockaddr,
297 namelen: socklen_t,
298 iov: [*]const iovec_const,
299 iovlen: u64,
300 control: ?*const anyopaque,
301 controllen: u64,
302 flags: i32,
303};
304
305pub const off_t = i64;285pub const off_t = i64;
306pub const ino_t = u64;286pub const ino_t = u64;
307pub const time_t = isize;287pub const time_t = isize;
lib/std/os/linux/x86.zig-20
...@@ -245,26 +245,6 @@ pub const Flock = extern struct {...@@ -245,26 +245,6 @@ pub const Flock = extern struct {
245 pid: pid_t,245 pid: pid_t,
246};246};
247247
248pub const msghdr = extern struct {
249 name: ?*sockaddr,
250 namelen: socklen_t,
251 iov: [*]iovec,
252 iovlen: i32,
253 control: ?*anyopaque,
254 controllen: socklen_t,
255 flags: i32,
256};
257
258pub const msghdr_const = extern struct {
259 name: ?*const sockaddr,
260 namelen: socklen_t,
261 iov: [*]const iovec_const,
262 iovlen: i32,
263 control: ?*const anyopaque,
264 controllen: socklen_t,
265 flags: i32,
266};
267
268pub const blksize_t = i32;248pub const blksize_t = i32;
269pub const nlink_t = u32;249pub const nlink_t = u32;
270pub const time_t = isize;250pub const time_t = isize;
lib/std/os/linux/x86_64.zig-24
...@@ -233,30 +233,6 @@ pub const Flock = extern struct {...@@ -233,30 +233,6 @@ pub const Flock = extern struct {
233 pid: pid_t,233 pid: pid_t,
234};234};
235235
236pub const msghdr = extern struct {
237 name: ?*sockaddr,
238 namelen: socklen_t,
239 iov: [*]iovec,
240 iovlen: i32,
241 __pad1: i32 = 0,
242 control: ?*anyopaque,
243 controllen: socklen_t,
244 __pad2: socklen_t = 0,
245 flags: i32,
246};
247
248pub const msghdr_const = extern struct {
249 name: ?*const sockaddr,
250 namelen: socklen_t,
251 iov: [*]const iovec_const,
252 iovlen: i32,
253 __pad1: i32 = 0,
254 control: ?*const anyopaque,
255 controllen: socklen_t,
256 __pad2: socklen_t = 0,
257 flags: i32,
258};
259
260pub const off_t = i64;236pub const off_t = i64;
261pub const ino_t = u64;237pub const ino_t = u64;
262pub const dev_t = u64;238pub const dev_t = u64;
lib/std/os/uefi.zig+14-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,19 @@ pub const Guid = extern struct {...@@ -59,31 +60,19 @@ 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) std.io.Writer.Error!void {
63 self: @This(),64 const time_low = @byteSwap(self.time_low);
64 comptime f: []const u8,65 const time_mid = @byteSwap(self.time_mid);
65 options: std.fmt.FormatOptions,66 const time_high_and_version = @byteSwap(self.time_high_and_version);
66 writer: anytype,67
67 ) !void {68 return writer.print("{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
68 _ = options;69 std.mem.asBytes(&time_low),
69 if (f.len == 0) {70 std.mem.asBytes(&time_mid),
70 const fmt = std.fmt.fmtSliceHexLower;71 std.mem.asBytes(&time_high_and_version),
7172 std.mem.asBytes(&self.clock_seq_high_and_reserved),
72 const time_low = @byteSwap(self.time_low);73 std.mem.asBytes(&self.clock_seq_low),
73 const time_mid = @byteSwap(self.time_mid);74 std.mem.asBytes(&self.node),
74 const time_high_and_version = @byteSwap(self.time_high_and_version);75 });
75
76 return std.fmt.format(writer, "{:0>8}-{:0>4}-{:0>4}-{:0>2}{:0>2}-{:0>12}", .{
77 fmt(std.mem.asBytes(&time_low)),
78 fmt(std.mem.asBytes(&time_mid)),
79 fmt(std.mem.asBytes(&time_high_and_version)),
80 fmt(std.mem.asBytes(&self.clock_seq_high_and_reserved)),
81 fmt(std.mem.asBytes(&self.clock_seq_low)),
82 fmt(std.mem.asBytes(&self.node)),
83 });
84 } else {
85 std.fmt.invalidFmtError(f, self);
86 }
87 }76 }
8877
89 pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {78 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.Reader(*File, ReadError, read);
92 pub const Writer = io.Writer(*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+2-37
...@@ -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}
...@@ -2846,9 +2812,8 @@ pub fn unexpectedError(err: Win32Error) UnexpectedError {...@@ -2846,9 +2812,8 @@ pub fn unexpectedError(err: Win32Error) UnexpectedError {
2846 buf_wstr.len,2812 buf_wstr.len,
2847 null,2813 null,
2848 );2814 );
2849 std.debug.print("error.Unexpected: GetLastError({}): {}\n", .{2815 std.debug.print("error.Unexpected: GetLastError({d}): {f}\n", .{
2850 @intFromEnum(err),2816 err, std.unicode.fmtUtf16Le(buf_wstr[0..len]),
2851 std.unicode.fmtUtf16Le(buf_wstr[0..len]),
2852 });2817 });
2853 std.debug.dumpCurrentStackTrace(@returnAddress());2818 std.debug.dumpCurrentStackTrace(@returnAddress());
2854 }2819 }
lib/std/os/windows/test.zig+2-2
...@@ -30,7 +30,7 @@ fn testToPrefixedFileNoOracle(comptime path: []const u8, comptime expected_path:...@@ -30,7 +30,7 @@ fn testToPrefixedFileNoOracle(comptime path: []const u8, comptime expected_path:
30 const expected_path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(expected_path);30 const expected_path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(expected_path);
31 const actual_path = try windows.wToPrefixedFileW(null, path_utf16);31 const actual_path = try windows.wToPrefixedFileW(null, path_utf16);
32 std.testing.expectEqualSlices(u16, expected_path_utf16, actual_path.span()) catch |e| {32 std.testing.expectEqualSlices(u16, expected_path_utf16, actual_path.span()) catch |e| {
33 std.debug.print("got '{s}', expected '{s}'\n", .{ std.unicode.fmtUtf16Le(actual_path.span()), std.unicode.fmtUtf16Le(expected_path_utf16) });33 std.debug.print("got '{f}', expected '{f}'\n", .{ std.unicode.fmtUtf16Le(actual_path.span()), std.unicode.fmtUtf16Le(expected_path_utf16) });
34 return e;34 return e;
35 };35 };
36}36}
...@@ -48,7 +48,7 @@ fn testToPrefixedFileOnlyOracle(comptime path: []const u8) !void {...@@ -48,7 +48,7 @@ fn testToPrefixedFileOnlyOracle(comptime path: []const u8) !void {
48 const zig_result = try windows.wToPrefixedFileW(null, path_utf16);48 const zig_result = try windows.wToPrefixedFileW(null, path_utf16);
49 const win32_api_result = try RtlDosPathNameToNtPathName_U(path_utf16);49 const win32_api_result = try RtlDosPathNameToNtPathName_U(path_utf16);
50 std.testing.expectEqualSlices(u16, win32_api_result.span(), zig_result.span()) catch |e| {50 std.testing.expectEqualSlices(u16, win32_api_result.span(), zig_result.span()) catch |e| {
51 std.debug.print("got '{s}', expected '{s}'\n", .{ std.unicode.fmtUtf16Le(zig_result.span()), std.unicode.fmtUtf16Le(win32_api_result.span()) });51 std.debug.print("got '{f}', expected '{f}'\n", .{ std.unicode.fmtUtf16Le(zig_result.span()), std.unicode.fmtUtf16Le(win32_api_result.span()) });
52 return e;52 return e;
53 };53 };
54}54}
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/tar.zig+1-1
...@@ -348,7 +348,7 @@ pub fn Iterator(comptime ReaderType: type) type {...@@ -348,7 +348,7 @@ pub fn Iterator(comptime ReaderType: type) type {
348 unread_bytes: *u64,348 unread_bytes: *u64,
349 parent_reader: ReaderType,349 parent_reader: ReaderType,
350350
351 pub const Reader = std.io.Reader(File, ReaderType.Error, File.read);351 pub const Reader = std.io.GenericReader(File, ReaderType.Error, File.read);
352352
353 pub fn reader(self: File) Reader {353 pub fn reader(self: File) Reader {
354 return .{ .context = self };354 return .{ .context = self };
lib/std/testing.zig+85-31
...@@ -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);
...@@ -356,9 +360,6 @@ test expectApproxEqRel {...@@ -356,9 +360,6 @@ test expectApproxEqRel {
356/// The colorized output is optional and controlled by the return of `std.io.tty.detectConfig()`.360/// The colorized output is optional and controlled by the return of `std.io.tty.detectConfig()`.
357/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.361/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.
358pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {362pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {
359 if (expected.ptr == actual.ptr and expected.len == actual.len) {
360 return;
361 }
362 const diff_index: usize = diff_index: {363 const diff_index: usize = diff_index: {
363 const shortest = @min(expected.len, actual.len);364 const shortest = @min(expected.len, actual.len);
364 var index: usize = 0;365 var index: usize = 0;
...@@ -367,12 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -367,12 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
367 }368 }
368 break :diff_index if (expected.len == actual.len) return else shortest;369 break :diff_index if (expected.len == actual.len) return else shortest;
369 };370 };
371 if (!backend_can_print) return error.TestExpectedEqual;
372 const stderr_w = std.debug.lockStderrWriter(&.{});
373 defer std.debug.unlockStderrWriter();
374 failEqualSlices(T, expected, actual, diff_index, stderr_w) catch {};
375 return error.TestExpectedEqual;
376}
370377
371 if (!backend_can_print) {378fn failEqualSlices(
372 return error.TestExpectedEqual;379 comptime T: type,
373 }380 expected: []const T,
374381 actual: []const T,
375 print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });382 diff_index: usize,
383 w: *std.io.Writer,
384) !void {
385 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });
376386
377 // TODO: Should this be configurable by the caller?387 // TODO: Should this be configurable by the caller?
378 const max_lines: usize = 16;388 const max_lines: usize = 16;
...@@ -390,8 +400,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -390,8 +400,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
390 const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];400 const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];
391 const actual_truncated = window_start + actual_window.len < actual.len;401 const actual_truncated = window_start + actual_window.len < actual.len;
392402
393 const stderr = std.io.getStdErr();403 const ttyconf = std.io.tty.detectConfig(.stderr());
394 const ttyconf = std.io.tty.detectConfig(stderr);
395 var differ = if (T == u8) BytesDiffer{404 var differ = if (T == u8) BytesDiffer{
396 .expected = expected_window,405 .expected = expected_window,
397 .actual = actual_window,406 .actual = actual_window,
...@@ -407,47 +416,47 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -407,47 +416,47 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
407 // that is usually useful.416 // that is usually useful.
408 const index_fmt = if (T == u8) "0x{X}" else "{}";417 const index_fmt = if (T == u8) "0x{X}" else "{}";
409418
410 print("\n============ expected this output: ============= len: {} (0x{X})\n\n", .{ expected.len, expected.len });419 try w.print("\n============ expected this output: ============= len: {} (0x{X})\n\n", .{ expected.len, expected.len });
411 if (window_start > 0) {420 if (window_start > 0) {
412 if (T == u8) {421 if (T == u8) {
413 print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});422 try w.print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});
414 } else {423 } else {
415 print("... truncated ...\n", .{});424 try w.print("... truncated ...\n", .{});
416 }425 }
417 }426 }
418 differ.write(stderr.writer()) catch {};427 differ.write(w) catch {};
419 if (expected_truncated) {428 if (expected_truncated) {
420 const end_offset = window_start + expected_window.len;429 const end_offset = window_start + expected_window.len;
421 const num_missing_items = expected.len - (window_start + expected_window.len);430 const num_missing_items = expected.len - (window_start + expected_window.len);
422 if (T == u8) {431 if (T == u8) {
423 print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });432 try w.print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });
424 } else {433 } else {
425 print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});434 try w.print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});
426 }435 }
427 }436 }
428437
429 // now reverse expected/actual and print again438 // now reverse expected/actual and print again
430 differ.expected = actual_window;439 differ.expected = actual_window;
431 differ.actual = expected_window;440 differ.actual = expected_window;
432 print("\n============= instead found this: ============== len: {} (0x{X})\n\n", .{ actual.len, actual.len });441 try w.print("\n============= instead found this: ============== len: {} (0x{X})\n\n", .{ actual.len, actual.len });
433 if (window_start > 0) {442 if (window_start > 0) {
434 if (T == u8) {443 if (T == u8) {
435 print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});444 try w.print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});
436 } else {445 } else {
437 print("... truncated ...\n", .{});446 try w.print("... truncated ...\n", .{});
438 }447 }
439 }448 }
440 differ.write(stderr.writer()) catch {};449 differ.write(w) catch {};
441 if (actual_truncated) {450 if (actual_truncated) {
442 const end_offset = window_start + actual_window.len;451 const end_offset = window_start + actual_window.len;
443 const num_missing_items = actual.len - (window_start + actual_window.len);452 const num_missing_items = actual.len - (window_start + actual_window.len);
444 if (T == u8) {453 if (T == u8) {
445 print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });454 try w.print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });
446 } else {455 } else {
447 print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});456 try w.print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});
448 }457 }
449 }458 }
450 print("\n================================================\n\n", .{});459 try w.print("\n================================================\n\n", .{});
451460
452 return error.TestExpectedEqual;461 return error.TestExpectedEqual;
453}462}
...@@ -461,7 +470,7 @@ fn SliceDiffer(comptime T: type) type {...@@ -461,7 +470,7 @@ fn SliceDiffer(comptime T: type) type {
461470
462 const Self = @This();471 const Self = @This();
463472
464 pub fn write(self: Self, writer: anytype) !void {473 pub fn write(self: Self, writer: *std.io.Writer) !void {
465 for (self.expected, 0..) |value, i| {474 for (self.expected, 0..) |value, i| {
466 const full_index = self.start_index + i;475 const full_index = self.start_index + i;
467 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;476 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;
...@@ -482,7 +491,7 @@ const BytesDiffer = struct {...@@ -482,7 +491,7 @@ const BytesDiffer = struct {
482 actual: []const u8,491 actual: []const u8,
483 ttyconf: std.io.tty.Config,492 ttyconf: std.io.tty.Config,
484493
485 pub fn write(self: BytesDiffer, writer: anytype) !void {494 pub fn write(self: BytesDiffer, writer: *std.io.Writer) !void {
486 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);495 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);
487 var row: usize = 0;496 var row: usize = 0;
488 while (expected_iterator.next()) |chunk| {497 while (expected_iterator.next()) |chunk| {
...@@ -499,7 +508,7 @@ const BytesDiffer = struct {...@@ -499,7 +508,7 @@ const BytesDiffer = struct {
499 if (chunk.len < 16) {508 if (chunk.len < 16) {
500 var missing_columns = (16 - chunk.len) * 3;509 var missing_columns = (16 - chunk.len) * 3;
501 if (chunk.len < 8) missing_columns += 1;510 if (chunk.len < 8) missing_columns += 1;
502 try writer.writeByteNTimes(' ', missing_columns);511 try writer.splatByteAll(' ', missing_columns);
503 }512 }
504 for (chunk, 0..) |byte, col| {513 for (chunk, 0..) |byte, col| {
505 const diff = diffs.isSet(col);514 const diff = diffs.isSet(col);
...@@ -528,7 +537,7 @@ const BytesDiffer = struct {...@@ -528,7 +537,7 @@ const BytesDiffer = struct {
528 }537 }
529 }538 }
530539
531 fn writeDiff(self: BytesDiffer, writer: anytype, comptime fmt: []const u8, args: anytype, diff: bool) !void {540 fn writeDiff(self: BytesDiffer, writer: *std.io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void {
532 if (diff) try self.ttyconf.setColor(writer, .red);541 if (diff) try self.ttyconf.setColor(writer, .red);
533 try writer.print(fmt, args);542 try writer.print(fmt, args);
534 if (diff) try self.ttyconf.setColor(writer, .reset);543 if (diff) try self.ttyconf.setColor(writer, .reset);
...@@ -637,6 +646,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir {...@@ -637,6 +646,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir {
637646
638pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {647pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
639 if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| {648 if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| {
649 if (@inComptime()) {
650 @compileError(std.fmt.comptimePrint("\nexpected:\n{s}\nfound:\n{s}\ndifference starts at index {d}", .{
651 expected, actual, diff_index,
652 }));
653 }
640 print("\n====== expected this output: =========\n", .{});654 print("\n====== expected this output: =========\n", .{});
641 printWithVisibleNewlines(expected);655 printWithVisibleNewlines(expected);
642 print("\n======== instead found this: =========\n", .{});656 print("\n======== instead found this: =========\n", .{});
...@@ -1108,7 +1122,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime...@@ -1108,7 +1122,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
1108 const arg_i_str = comptime str: {1122 const arg_i_str = comptime str: {
1109 var str_buf: [100]u8 = undefined;1123 var str_buf: [100]u8 = undefined;
1110 const args_i = i + 1;1124 const args_i = i + 1;
1111 const str_len = std.fmt.formatIntBuf(&str_buf, args_i, 10, .lower, .{});1125 const str_len = std.fmt.printInt(&str_buf, args_i, 10, .lower, .{});
1112 break :str str_buf[0..str_len];1126 break :str str_buf[0..str_len];
1113 };1127 };
1114 @field(args, arg_i_str) = @field(extra_args, field.name);1128 @field(args, arg_i_str) = @field(extra_args, field.name);
...@@ -1138,7 +1152,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime...@@ -1138,7 +1152,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
1138 error.OutOfMemory => {1152 error.OutOfMemory => {
1139 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {1153 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
1140 print(1154 print(
1141 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {}",1155 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}",
1142 .{1156 .{
1143 fail_index,1157 fail_index,
1144 needed_alloc_count,1158 needed_alloc_count,
...@@ -1192,3 +1206,43 @@ pub inline fn fuzz(...@@ -1192,3 +1206,43 @@ pub inline fn fuzz(
1192) anyerror!void {1206) anyerror!void {
1193 return @import("root").fuzz(context, testOne, options);1207 return @import("root").fuzz(context, testOne, options);
1194}1208}
1209
1210/// A `std.io.Reader` that writes a predetermined list of buffers during `stream`.
1211pub const Reader = struct {
1212 calls: []const Call,
1213 interface: std.io.Reader,
1214 next_call_index: usize,
1215 next_offset: usize,
1216
1217 pub const Call = struct {
1218 buffer: []const u8,
1219 };
1220
1221 pub fn init(buffer: []u8, calls: []const Call) Reader {
1222 return .{
1223 .next_call_index = 0,
1224 .next_offset = 0,
1225 .interface = .{
1226 .vtable = &.{ .stream = stream },
1227 .buffer = buffer,
1228 .seek = 0,
1229 .end = 0,
1230 },
1231 .calls = calls,
1232 };
1233 }
1234
1235 fn stream(io_r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
1236 const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r));
1237 if (r.calls.len - r.next_call_index == 0) return error.EndOfStream;
1238 const call = r.calls[r.next_call_index];
1239 const buffer = limit.sliceConst(call.buffer[r.next_offset..]);
1240 const n = try w.write(buffer);
1241 r.next_offset += n;
1242 if (call.buffer.len - r.next_offset == 0) {
1243 r.next_call_index += 1;
1244 r.next_offset = 0;
1245 }
1246 return n;
1247 }
1248};
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.io.getStdOut().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+107-120
...@@ -48,7 +48,7 @@ pub const Color = enum {...@@ -48,7 +48,7 @@ pub const Color = enum {
4848
49 pub fn get_tty_conf(color: Color) std.io.tty.Config {49 pub fn get_tty_conf(color: Color) std.io.tty.Config {
50 return switch (color) {50 return switch (color) {
51 .auto => std.io.tty.detectConfig(std.io.getStdErr()),51 .auto => std.io.tty.detectConfig(std.fs.File.stderr()),
52 .on => .escape_codes,52 .on => .escape_codes,
53 .off => .no_color,53 .off => .no_color,
54 };54 };
...@@ -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.printInt(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.printInt(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/AstGen.zig+1-7
...@@ -11305,13 +11305,7 @@ fn failWithStrLitError(...@@ -11305,13 +11305,7 @@ fn failWithStrLitError(
11305 offset: u32,11305 offset: u32,
11306) InnerError {11306) InnerError {
11307 const raw_string = bytes[offset..];11307 const raw_string = bytes[offset..];
11308 return failOff(11308 return failOff(astgen, token, @intCast(offset + err.offset()), "{f}", .{err.fmt(raw_string)});
11309 astgen,
11310 token,
11311 @intCast(offset + err.offset()),
11312 "{}",
11313 .{err.fmt(raw_string)},
11314 );
11315}11309}
1131611310
11317fn failNode(11311fn failNode(
lib/std/zig/ErrorBundle.zig+81-71
...@@ -7,6 +7,12 @@...@@ -7,6 +7,12 @@
7//! empty, it means there are no errors. This special encoding exists so that7//! empty, it means there are no errors. This special encoding exists so that
8//! heap allocation is not needed in the common case of no errors.8//! heap allocation is not needed in the common case of no errors.
99
10const std = @import("std");
11const ErrorBundle = @This();
12const Allocator = std.mem.Allocator;
13const assert = std.debug.assert;
14const Writer = std.io.Writer;
15
10string_bytes: []const u8,16string_bytes: []const u8,
11/// The first thing in this array is an `ErrorMessageList`.17/// The first thing in this array is an `ErrorMessageList`.
12extra: []const u32,18extra: []const u32,
...@@ -157,23 +163,23 @@ pub const RenderOptions = struct {...@@ -157,23 +163,23 @@ pub const RenderOptions = struct {
157};163};
158164
159pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {165pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {
160 std.debug.lockStdErr();166 var buffer: [256]u8 = undefined;
161 defer std.debug.unlockStdErr();167 const w = std.debug.lockStderrWriter(&buffer);
162 const stderr = std.io.getStdErr();168 defer std.debug.unlockStderrWriter();
163 return renderToWriter(eb, options, stderr.writer()) catch return;169 renderToWriter(eb, options, w) catch return;
164}170}
165171
166pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void {172pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) (Writer.Error || std.posix.UnexpectedError)!void {
167 if (eb.extra.len == 0) return;173 if (eb.extra.len == 0) return;
168 for (eb.getMessages()) |err_msg| {174 for (eb.getMessages()) |err_msg| {
169 try renderErrorMessageToWriter(eb, options, err_msg, writer, "error", .red, 0);175 try renderErrorMessageToWriter(eb, options, err_msg, w, "error", .red, 0);
170 }176 }
171177
172 if (options.include_log_text) {178 if (options.include_log_text) {
173 const log_text = eb.getCompileLogOutput();179 const log_text = eb.getCompileLogOutput();
174 if (log_text.len != 0) {180 if (log_text.len != 0) {
175 try writer.writeAll("\nCompile Log Output:\n");181 try w.writeAll("\nCompile Log Output:\n");
176 try writer.writeAll(log_text);182 try w.writeAll(log_text);
177 }183 }
178 }184 }
179}185}
...@@ -182,74 +188,81 @@ fn renderErrorMessageToWriter(...@@ -182,74 +188,81 @@ fn renderErrorMessageToWriter(
182 eb: ErrorBundle,188 eb: ErrorBundle,
183 options: RenderOptions,189 options: RenderOptions,
184 err_msg_index: MessageIndex,190 err_msg_index: MessageIndex,
185 stderr: anytype,191 w: *Writer,
186 kind: []const u8,192 kind: []const u8,
187 color: std.io.tty.Color,193 color: std.io.tty.Color,
188 indent: usize,194 indent: usize,
189) anyerror!void {195) (Writer.Error || std.posix.UnexpectedError)!void {
190 const ttyconf = options.ttyconf;196 const ttyconf = options.ttyconf;
191 var counting_writer = std.io.countingWriter(stderr);
192 const counting_stderr = counting_writer.writer();
193 const err_msg = eb.getErrorMessage(err_msg_index);197 const err_msg = eb.getErrorMessage(err_msg_index);
194 if (err_msg.src_loc != .none) {198 if (err_msg.src_loc != .none) {
195 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));199 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
196 try counting_stderr.writeByteNTimes(' ', indent);200 var prefix: std.io.Writer.Discarding = .init(&.{});
197 try ttyconf.setColor(stderr, .bold);201 try w.splatByteAll(' ', indent);
198 try counting_stderr.print("{s}:{d}:{d}: ", .{202 prefix.count += indent;
203 try ttyconf.setColor(w, .bold);
204 try w.print("{s}:{d}:{d}: ", .{
205 eb.nullTerminatedString(src.data.src_path),
206 src.data.line + 1,
207 src.data.column + 1,
208 });
209 try prefix.writer.print("{s}:{d}:{d}: ", .{
199 eb.nullTerminatedString(src.data.src_path),210 eb.nullTerminatedString(src.data.src_path),
200 src.data.line + 1,211 src.data.line + 1,
201 src.data.column + 1,212 src.data.column + 1,
202 });213 });
203 try ttyconf.setColor(stderr, color);214 try ttyconf.setColor(w, color);
204 try counting_stderr.writeAll(kind);215 try w.writeAll(kind);
205 try counting_stderr.writeAll(": ");216 prefix.count += kind.len;
217 try w.writeAll(": ");
218 prefix.count += 2;
206 // This is the length of the part before the error message:219 // This is the length of the part before the error message:
207 // e.g. "file.zig:4:5: error: "220 // e.g. "file.zig:4:5: error: "
208 const prefix_len: usize = @intCast(counting_stderr.context.bytes_written);221 const prefix_len: usize = @intCast(prefix.count);
209 try ttyconf.setColor(stderr, .reset);222 try ttyconf.setColor(w, .reset);
210 try ttyconf.setColor(stderr, .bold);223 try ttyconf.setColor(w, .bold);
211 if (err_msg.count == 1) {224 if (err_msg.count == 1) {
212 try writeMsg(eb, err_msg, stderr, prefix_len);225 try writeMsg(eb, err_msg, w, prefix_len);
213 try stderr.writeByte('\n');226 try w.writeByte('\n');
214 } else {227 } else {
215 try writeMsg(eb, err_msg, stderr, prefix_len);228 try writeMsg(eb, err_msg, w, prefix_len);
216 try ttyconf.setColor(stderr, .dim);229 try ttyconf.setColor(w, .dim);
217 try stderr.print(" ({d} times)\n", .{err_msg.count});230 try w.print(" ({d} times)\n", .{err_msg.count});
218 }231 }
219 try ttyconf.setColor(stderr, .reset);232 try ttyconf.setColor(w, .reset);
220 if (src.data.source_line != 0 and options.include_source_line) {233 if (src.data.source_line != 0 and options.include_source_line) {
221 const line = eb.nullTerminatedString(src.data.source_line);234 const line = eb.nullTerminatedString(src.data.source_line);
222 for (line) |b| switch (b) {235 for (line) |b| switch (b) {
223 '\t' => try stderr.writeByte(' '),236 '\t' => try w.writeByte(' '),
224 else => try stderr.writeByte(b),237 else => try w.writeByte(b),
225 };238 };
226 try stderr.writeByte('\n');239 try w.writeByte('\n');
227 // TODO basic unicode code point monospace width240 // TODO basic unicode code point monospace width
228 const before_caret = src.data.span_main - src.data.span_start;241 const before_caret = src.data.span_main - src.data.span_start;
229 // -1 since span.main includes the caret242 // -1 since span.main includes the caret
230 const after_caret = src.data.span_end -| src.data.span_main -| 1;243 const after_caret = src.data.span_end -| src.data.span_main -| 1;
231 try stderr.writeByteNTimes(' ', src.data.column - before_caret);244 try w.splatByteAll(' ', src.data.column - before_caret);
232 try ttyconf.setColor(stderr, .green);245 try ttyconf.setColor(w, .green);
233 try stderr.writeByteNTimes('~', before_caret);246 try w.splatByteAll('~', before_caret);
234 try stderr.writeByte('^');247 try w.writeByte('^');
235 try stderr.writeByteNTimes('~', after_caret);248 try w.splatByteAll('~', after_caret);
236 try stderr.writeByte('\n');249 try w.writeByte('\n');
237 try ttyconf.setColor(stderr, .reset);250 try ttyconf.setColor(w, .reset);
238 }251 }
239 for (eb.getNotes(err_msg_index)) |note| {252 for (eb.getNotes(err_msg_index)) |note| {
240 try renderErrorMessageToWriter(eb, options, note, stderr, "note", .cyan, indent);253 try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent);
241 }254 }
242 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {255 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {
243 try ttyconf.setColor(stderr, .reset);256 try ttyconf.setColor(w, .reset);
244 try ttyconf.setColor(stderr, .dim);257 try ttyconf.setColor(w, .dim);
245 try stderr.print("referenced by:\n", .{});258 try w.print("referenced by:\n", .{});
246 var ref_index = src.end;259 var ref_index = src.end;
247 for (0..src.data.reference_trace_len) |_| {260 for (0..src.data.reference_trace_len) |_| {
248 const ref_trace = eb.extraData(ReferenceTrace, ref_index);261 const ref_trace = eb.extraData(ReferenceTrace, ref_index);
249 ref_index = ref_trace.end;262 ref_index = ref_trace.end;
250 if (ref_trace.data.src_loc != .none) {263 if (ref_trace.data.src_loc != .none) {
251 const ref_src = eb.getSourceLocation(ref_trace.data.src_loc);264 const ref_src = eb.getSourceLocation(ref_trace.data.src_loc);
252 try stderr.print(" {s}: {s}:{d}:{d}\n", .{265 try w.print(" {s}: {s}:{d}:{d}\n", .{
253 eb.nullTerminatedString(ref_trace.data.decl_name),266 eb.nullTerminatedString(ref_trace.data.decl_name),
254 eb.nullTerminatedString(ref_src.src_path),267 eb.nullTerminatedString(ref_src.src_path),
255 ref_src.line + 1,268 ref_src.line + 1,
...@@ -257,36 +270,36 @@ fn renderErrorMessageToWriter(...@@ -257,36 +270,36 @@ fn renderErrorMessageToWriter(
257 });270 });
258 } else if (ref_trace.data.decl_name != 0) {271 } else if (ref_trace.data.decl_name != 0) {
259 const count = ref_trace.data.decl_name;272 const count = ref_trace.data.decl_name;
260 try stderr.print(273 try w.print(
261 " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n",274 " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n",
262 .{ count, count + src.data.reference_trace_len - 1 },275 .{ count, count + src.data.reference_trace_len - 1 },
263 );276 );
264 } else {277 } else {
265 try stderr.print(278 try w.print(
266 " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n",279 " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n",
267 .{},280 .{},
268 );281 );
269 }282 }
270 }283 }
271 try ttyconf.setColor(stderr, .reset);284 try ttyconf.setColor(w, .reset);
272 }285 }
273 } else {286 } else {
274 try ttyconf.setColor(stderr, color);287 try ttyconf.setColor(w, color);
275 try stderr.writeByteNTimes(' ', indent);288 try w.splatByteAll(' ', indent);
276 try stderr.writeAll(kind);289 try w.writeAll(kind);
277 try stderr.writeAll(": ");290 try w.writeAll(": ");
278 try ttyconf.setColor(stderr, .reset);291 try ttyconf.setColor(w, .reset);
279 const msg = eb.nullTerminatedString(err_msg.msg);292 const msg = eb.nullTerminatedString(err_msg.msg);
280 if (err_msg.count == 1) {293 if (err_msg.count == 1) {
281 try stderr.print("{s}\n", .{msg});294 try w.print("{s}\n", .{msg});
282 } else {295 } else {
283 try stderr.print("{s}", .{msg});296 try w.print("{s}", .{msg});
284 try ttyconf.setColor(stderr, .dim);297 try ttyconf.setColor(w, .dim);
285 try stderr.print(" ({d} times)\n", .{err_msg.count});298 try w.print(" ({d} times)\n", .{err_msg.count});
286 }299 }
287 try ttyconf.setColor(stderr, .reset);300 try ttyconf.setColor(w, .reset);
288 for (eb.getNotes(err_msg_index)) |note| {301 for (eb.getNotes(err_msg_index)) |note| {
289 try renderErrorMessageToWriter(eb, options, note, stderr, "note", .cyan, indent + 4);302 try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent + 4);
290 }303 }
291 }304 }
292}305}
...@@ -295,21 +308,16 @@ fn renderErrorMessageToWriter(...@@ -295,21 +308,16 @@ fn renderErrorMessageToWriter(
295/// to allow for long, good-looking error messages.308/// to allow for long, good-looking error messages.
296///309///
297/// This is used to split the message in `@compileError("hello\nworld")` for example.310/// This is used to split the message in `@compileError("hello\nworld")` for example.
298fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, stderr: anytype, indent: usize) !void {311fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, w: *Writer, indent: usize) !void {
299 var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n');312 var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n');
300 while (lines.next()) |line| {313 while (lines.next()) |line| {
301 try stderr.writeAll(line);314 try w.writeAll(line);
302 if (lines.index == null) break;315 if (lines.index == null) break;
303 try stderr.writeByte('\n');316 try w.writeByte('\n');
304 try stderr.writeByteNTimes(' ', indent);317 try w.splatByteAll(' ', indent);
305 }318 }
306}319}
307320
308const std = @import("std");
309const ErrorBundle = @This();
310const Allocator = std.mem.Allocator;
311const assert = std.debug.assert;
312
313pub const Wip = struct {321pub const Wip = struct {
314 gpa: Allocator,322 gpa: Allocator,
315 string_bytes: std.ArrayListUnmanaged(u8),323 string_bytes: std.ArrayListUnmanaged(u8),
...@@ -398,7 +406,7 @@ pub const Wip = struct {...@@ -398,7 +406,7 @@ pub const Wip = struct {
398 pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String {406 pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String {
399 const gpa = wip.gpa;407 const gpa = wip.gpa;
400 const index: String = @intCast(wip.string_bytes.items.len);408 const index: String = @intCast(wip.string_bytes.items.len);
401 try wip.string_bytes.writer(gpa).print(fmt, args);409 try wip.string_bytes.print(gpa, fmt, args);
402 try wip.string_bytes.append(gpa, 0);410 try wip.string_bytes.append(gpa, 0);
403 return index;411 return index;
404 }412 }
...@@ -788,9 +796,10 @@ pub const Wip = struct {...@@ -788,9 +796,10 @@ pub const Wip = struct {
788796
789 const ttyconf: std.io.tty.Config = .no_color;797 const ttyconf: std.io.tty.Config = .no_color;
790798
791 var bundle_buf = std.ArrayList(u8).init(std.testing.allocator);799 var bundle_buf: std.io.Writer.Allocating = .init(std.testing.allocator);
800 const bundle_bw = &bundle_buf.interface;
792 defer bundle_buf.deinit();801 defer bundle_buf.deinit();
793 try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_buf.writer());802 try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_bw);
794803
795 var copy = copy: {804 var copy = copy: {
796 var wip: ErrorBundle.Wip = undefined;805 var wip: ErrorBundle.Wip = undefined;
...@@ -803,10 +812,11 @@ pub const Wip = struct {...@@ -803,10 +812,11 @@ pub const Wip = struct {
803 };812 };
804 defer copy.deinit(std.testing.allocator);813 defer copy.deinit(std.testing.allocator);
805814
806 var copy_buf = std.ArrayList(u8).init(std.testing.allocator);815 var copy_buf: std.io.Writer.Allocating = .init(std.testing.allocator);
816 const copy_bw = &copy_buf.interface;
807 defer copy_buf.deinit();817 defer copy_buf.deinit();
808 try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_buf.writer());818 try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_bw);
809819
810 try std.testing.expectEqualStrings(bundle_buf.items, copy_buf.items);820 try std.testing.expectEqualStrings(bundle_bw.getWritten(), copy_bw.getWritten());
811 }821 }
812};822};
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+718-741
...@@ -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,38 @@ pub const String = enum(u32) {...@@ -90,31 +101,38 @@ 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(112 }
108 string_slice,113
109 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|114 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
110 .always_quote115 return .{ .data = .{
111 else116 .string = self,
112 .quote_unless_valid_identifier,117 .builder = builder,
113 writer,118 .quote_behavior = .quote_unless_valid_identifier,
114 );119 } };
120 }
121
122 pub fn fmtQ(self: String, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
123 return .{ .data = .{
124 .string = self,
125 .builder = builder,
126 .quote_behavior = .always_quote,
127 } };
115 }128 }
116 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {129
117 return .{ .data = .{ .string = self, .builder = builder } };130 pub fn fmtRaw(self: String, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
131 return .{ .data = .{
132 .string = self,
133 .builder = builder,
134 .quote_behavior = null,
135 } };
118 }136 }
119137
120 fn fromIndex(index: ?usize) String {138 fn fromIndex(index: ?usize) String {
...@@ -228,7 +246,7 @@ pub const Type = enum(u32) {...@@ -228,7 +246,7 @@ pub const Type = enum(u32) {
228 _,246 _,
229247
230 pub const ptr_amdgpu_constant =248 pub const ptr_amdgpu_constant =
231 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));249 @field(Type, std.fmt.comptimePrint("ptr{f}", .{AddrSpace.amdgpu.constant.fmt(" ")}));
232250
233 pub const Tag = enum(u4) {251 pub const Tag = enum(u4) {
234 simple,252 simple,
...@@ -653,18 +671,16 @@ pub const Type = enum(u32) {...@@ -653,18 +671,16 @@ pub const Type = enum(u32) {
653 const FormatData = struct {671 const FormatData = struct {
654 type: Type,672 type: Type,
655 builder: *const Builder,673 builder: *const Builder,
674 mode: Mode,
675
676 const Mode = enum { default, m, lt, gt, percent };
656 };677 };
657 fn format(678 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);679 assert(data.type != .none);
664 if (comptime std.mem.eql(u8, fmt_str, "m")) {680 if (data.mode == .m) {
665 const item = data.builder.type_items.items[@intFromEnum(data.type)];681 const item = data.builder.type_items.items[@intFromEnum(data.type)];
666 switch (item.tag) {682 switch (item.tag) {
667 .simple => try writer.writeAll(switch (@as(Simple, @enumFromInt(item.data))) {683 .simple => try w.writeAll(switch (@as(Simple, @enumFromInt(item.data))) {
668 .void => "isVoid",684 .void => "isVoid",
669 .half => "f16",685 .half => "f16",
670 .bfloat => "bf16",686 .bfloat => "bf16",
...@@ -681,36 +697,36 @@ pub const Type = enum(u32) {...@@ -681,36 +697,36 @@ pub const Type = enum(u32) {
681 .function, .vararg_function => |kind| {697 .function, .vararg_function => |kind| {
682 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);698 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
683 const params = extra.trail.next(extra.data.params_len, Type, data.builder);699 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
684 try writer.print("f_{m}", .{extra.data.ret.fmt(data.builder)});700 try w.print("f_{f}", .{extra.data.ret.fmt(data.builder, .m)});
685 for (params) |param| try writer.print("{m}", .{param.fmt(data.builder)});701 for (params) |param| try w.print("{f}", .{param.fmt(data.builder, .m)});
686 switch (kind) {702 switch (kind) {
687 .function => {},703 .function => {},
688 .vararg_function => try writer.writeAll("vararg"),704 .vararg_function => try w.writeAll("vararg"),
689 else => unreachable,705 else => unreachable,
690 }706 }
691 try writer.writeByte('f');707 try w.writeByte('f');
692 },708 },
693 .integer => try writer.print("i{d}", .{item.data}),709 .integer => try w.print("i{d}", .{item.data}),
694 .pointer => try writer.print("p{d}", .{item.data}),710 .pointer => try w.print("p{d}", .{item.data}),
695 .target => {711 .target => {
696 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);712 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
697 const types = extra.trail.next(extra.data.types_len, Type, data.builder);713 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);714 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
699 try writer.print("t{s}", .{extra.data.name.slice(data.builder).?});715 try w.print("t{s}", .{extra.data.name.slice(data.builder).?});
700 for (types) |ty| try writer.print("_{m}", .{ty.fmt(data.builder)});716 for (types) |ty| try w.print("_{f}", .{ty.fmt(data.builder, .m)});
701 for (ints) |int| try writer.print("_{d}", .{int});717 for (ints) |int| try w.print("_{d}", .{int});
702 try writer.writeByte('t');718 try w.writeByte('t');
703 },719 },
704 .vector, .scalable_vector => |kind| {720 .vector, .scalable_vector => |kind| {
705 const extra = data.builder.typeExtraData(Type.Vector, item.data);721 const extra = data.builder.typeExtraData(Type.Vector, item.data);
706 try writer.print("{s}v{d}{m}", .{722 try w.print("{s}v{d}{f}", .{
707 switch (kind) {723 switch (kind) {
708 .vector => "",724 .vector => "",
709 .scalable_vector => "nx",725 .scalable_vector => "nx",
710 else => unreachable,726 else => unreachable,
711 },727 },
712 extra.len,728 extra.len,
713 extra.child.fmt(data.builder),729 extra.child.fmt(data.builder, .m),
714 });730 });
715 },731 },
716 inline .small_array, .array => |kind| {732 inline .small_array, .array => |kind| {
...@@ -719,72 +735,72 @@ pub const Type = enum(u32) {...@@ -719,72 +735,72 @@ pub const Type = enum(u32) {
719 .array => Type.Array,735 .array => Type.Array,
720 else => unreachable,736 else => unreachable,
721 }, item.data);737 }, item.data);
722 try writer.print("a{d}{m}", .{ extra.length(), extra.child.fmt(data.builder) });738 try w.print("a{d}{f}", .{ extra.length(), extra.child.fmt(data.builder, .m) });
723 },739 },
724 .structure, .packed_structure => {740 .structure, .packed_structure => {
725 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);741 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
726 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);742 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
727 try writer.writeAll("sl_");743 try w.writeAll("sl_");
728 for (fields) |field| try writer.print("{m}", .{field.fmt(data.builder)});744 for (fields) |field| try w.print("{f}", .{field.fmt(data.builder, .m)});
729 try writer.writeByte('s');745 try w.writeByte('s');
730 },746 },
731 .named_structure => {747 .named_structure => {
732 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);748 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
733 try writer.writeAll("s_");749 try w.writeAll("s_");
734 if (extra.id.slice(data.builder)) |id| try writer.writeAll(id);750 if (extra.id.slice(data.builder)) |id| try w.writeAll(id);
735 },751 },
736 }752 }
737 return;753 return;
738 }754 }
739 if (std.enums.tagName(Type, data.type)) |name| return writer.writeAll(name);755 if (std.enums.tagName(Type, data.type)) |name| return w.writeAll(name);
740 const item = data.builder.type_items.items[@intFromEnum(data.type)];756 const item = data.builder.type_items.items[@intFromEnum(data.type)];
741 switch (item.tag) {757 switch (item.tag) {
742 .simple => unreachable,758 .simple => unreachable,
743 .function, .vararg_function => |kind| {759 .function, .vararg_function => |kind| {
744 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);760 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
745 const params = extra.trail.next(extra.data.params_len, Type, data.builder);761 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
746 if (!comptime std.mem.eql(u8, fmt_str, ">"))762 if (data.mode != .gt)
747 try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)});763 try w.print("{f} ", .{extra.data.ret.fmt(data.builder, .percent)});
748 if (!comptime std.mem.eql(u8, fmt_str, "<")) {764 if (data.mode != .lt) {
749 try writer.writeByte('(');765 try w.writeByte('(');
750 for (params, 0..) |param, index| {766 for (params, 0..) |param, index| {
751 if (index > 0) try writer.writeAll(", ");767 if (index > 0) try w.writeAll(", ");
752 try writer.print("{%}", .{param.fmt(data.builder)});768 try w.print("{f}", .{param.fmt(data.builder, .percent)});
753 }769 }
754 switch (kind) {770 switch (kind) {
755 .function => {},771 .function => {},
756 .vararg_function => {772 .vararg_function => {
757 if (params.len > 0) try writer.writeAll(", ");773 if (params.len > 0) try w.writeAll(", ");
758 try writer.writeAll("...");774 try w.writeAll("...");
759 },775 },
760 else => unreachable,776 else => unreachable,
761 }777 }
762 try writer.writeByte(')');778 try w.writeByte(')');
763 }779 }
764 },780 },
765 .integer => try writer.print("i{d}", .{item.data}),781 .integer => try w.print("i{d}", .{item.data}),
766 .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}),782 .pointer => try w.print("ptr{f}", .{@as(AddrSpace, @enumFromInt(item.data)).fmt(" ")}),
767 .target => {783 .target => {
768 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);784 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
769 const types = extra.trail.next(extra.data.types_len, Type, data.builder);785 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);786 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
771 try writer.print(787 try w.print(
772 \\target({"}788 \\target({f}
773 , .{extra.data.name.fmt(data.builder)});789 , .{extra.data.name.fmtQ(data.builder)});
774 for (types) |ty| try writer.print(", {%}", .{ty.fmt(data.builder)});790 for (types) |ty| try w.print(", {f}", .{ty.fmt(data.builder, .percent)});
775 for (ints) |int| try writer.print(", {d}", .{int});791 for (ints) |int| try w.print(", {d}", .{int});
776 try writer.writeByte(')');792 try w.writeByte(')');
777 },793 },
778 .vector, .scalable_vector => |kind| {794 .vector, .scalable_vector => |kind| {
779 const extra = data.builder.typeExtraData(Type.Vector, item.data);795 const extra = data.builder.typeExtraData(Type.Vector, item.data);
780 try writer.print("<{s}{d} x {%}>", .{796 try w.print("<{s}{d} x {f}>", .{
781 switch (kind) {797 switch (kind) {
782 .vector => "",798 .vector => "",
783 .scalable_vector => "vscale x ",799 .scalable_vector => "vscale x ",
784 else => unreachable,800 else => unreachable,
785 },801 },
786 extra.len,802 extra.len,
787 extra.child.fmt(data.builder),803 extra.child.fmt(data.builder, .percent),
788 });804 });
789 },805 },
790 inline .small_array, .array => |kind| {806 inline .small_array, .array => |kind| {
...@@ -793,44 +809,45 @@ pub const Type = enum(u32) {...@@ -793,44 +809,45 @@ pub const Type = enum(u32) {
793 .array => Type.Array,809 .array => Type.Array,
794 else => unreachable,810 else => unreachable,
795 }, item.data);811 }, item.data);
796 try writer.print("[{d} x {%}]", .{ extra.length(), extra.child.fmt(data.builder) });812 try w.print("[{d} x {f}]", .{ extra.length(), extra.child.fmt(data.builder, .percent) });
797 },813 },
798 .structure, .packed_structure => |kind| {814 .structure, .packed_structure => |kind| {
799 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);815 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
800 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);816 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
801 switch (kind) {817 switch (kind) {
802 .structure => {},818 .structure => {},
803 .packed_structure => try writer.writeByte('<'),819 .packed_structure => try w.writeByte('<'),
804 else => unreachable,820 else => unreachable,
805 }821 }
806 try writer.writeAll("{ ");822 try w.writeAll("{ ");
807 for (fields, 0..) |field, index| {823 for (fields, 0..) |field, index| {
808 if (index > 0) try writer.writeAll(", ");824 if (index > 0) try w.writeAll(", ");
809 try writer.print("{%}", .{field.fmt(data.builder)});825 try w.print("{f}", .{field.fmt(data.builder, .percent)});
810 }826 }
811 try writer.writeAll(" }");827 try w.writeAll(" }");
812 switch (kind) {828 switch (kind) {
813 .structure => {},829 .structure => {},
814 .packed_structure => try writer.writeByte('>'),830 .packed_structure => try w.writeByte('>'),
815 else => unreachable,831 else => unreachable,
816 }832 }
817 },833 },
818 .named_structure => {834 .named_structure => {
819 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);835 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
820 if (comptime std.mem.eql(u8, fmt_str, "%")) try writer.print("%{}", .{836 if (data.mode == .percent) try w.print("%{f}", .{
821 extra.id.fmt(data.builder),837 extra.id.fmt(data.builder),
822 }) else switch (extra.body) {838 }) else switch (extra.body) {
823 .none => try writer.writeAll("opaque"),839 .none => try w.writeAll("opaque"),
824 else => try format(.{840 else => try format(.{
825 .type = extra.body,841 .type = extra.body,
826 .builder = data.builder,842 .builder = data.builder,
827 }, fmt_str, fmt_opts, writer),843 .mode = data.mode,
844 }, w),
828 }845 }
829 },846 },
830 }847 }
831 }848 }
832 pub fn fmt(self: Type, builder: *const Builder) std.fmt.Formatter(format) {849 pub fn fmt(self: Type, builder: *const Builder, mode: FormatData.Mode) std.fmt.Formatter(FormatData, format) {
833 return .{ .data = .{ .type = self, .builder = builder } };850 return .{ .data = .{ .type = self, .builder = builder, .mode = mode } };
834 }851 }
835852
836 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);853 const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void);
...@@ -1138,15 +1155,13 @@ pub const Attribute = union(Kind) {...@@ -1138,15 +1155,13 @@ pub const Attribute = union(Kind) {
1138 const FormatData = struct {1155 const FormatData = struct {
1139 attribute_index: Index,1156 attribute_index: Index,
1140 builder: *const Builder,1157 builder: *const Builder,
1158 flags: Flags = .{},
1159 const Flags = struct {
1160 pound: bool = false,
1161 quote: bool = false,
1162 };
1141 };1163 };
1142 fn format(1164 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);1165 const attribute = data.attribute_index.toAttribute(data.builder);
1151 switch (attribute) {1166 switch (attribute) {
1152 .zeroext,1167 .zeroext,
...@@ -1219,97 +1234,99 @@ pub const Attribute = union(Kind) {...@@ -1219,97 +1234,99 @@ pub const Attribute = union(Kind) {
1219 .no_sanitize_address,1234 .no_sanitize_address,
1220 .no_sanitize_hwaddress,1235 .no_sanitize_hwaddress,
1221 .sanitize_address_dyninit,1236 .sanitize_address_dyninit,
1222 => try writer.print(" {s}", .{@tagName(attribute)}),1237 => try w.print(" {s}", .{@tagName(attribute)}),
1223 .byval,1238 .byval,
1224 .byref,1239 .byref,
1225 .preallocated,1240 .preallocated,
1226 .inalloca,1241 .inalloca,
1227 .sret,1242 .sret,
1228 .elementtype,1243 .elementtype,
1229 => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),1244 => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }),
1230 .@"align" => |alignment| try writer.print("{ }", .{alignment}),1245 .@"align" => |alignment| try w.print("{f}", .{alignment.fmt(" ")}),
1231 .dereferenceable,1246 .dereferenceable,
1232 .dereferenceable_or_null,1247 .dereferenceable_or_null,
1233 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),1248 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
1234 .nofpclass => |fpclass| {1249 .nofpclass => |fpclass| {
1235 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;1250 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
1236 try writer.print(" {s}(", .{@tagName(attribute)});1251 try w.print(" {s}(", .{@tagName(attribute)});
1237 var any = false;1252 var any = false;
1238 var remaining: Int = @bitCast(fpclass);1253 var remaining: Int = @bitCast(fpclass);
1239 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {1254 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {
1240 const pattern: Int = @bitCast(@field(FpClass, decl.name));1255 const pattern: Int = @bitCast(@field(FpClass, decl.name));
1241 if (remaining & pattern == pattern) {1256 if (remaining & pattern == pattern) {
1242 if (!any) {1257 if (!any) {
1243 try writer.writeByte(' ');1258 try w.writeByte(' ');
1244 any = true;1259 any = true;
1245 }1260 }
1246 try writer.writeAll(decl.name);1261 try w.writeAll(decl.name);
1247 remaining &= ~pattern;1262 remaining &= ~pattern;
1248 }1263 }
1249 }1264 }
1250 try writer.writeByte(')');1265 try w.writeByte(')');
1266 },
1267 .alignstack => |alignment| {
1268 try w.print(" {t}", .{attribute});
1269 const alignment_bytes = alignment.toByteUnits() orelse return;
1270 if (data.flags.pound) {
1271 try w.print("={d}", .{alignment_bytes});
1272 } else {
1273 try w.print("({d})", .{alignment_bytes});
1274 }
1251 },1275 },
1252 .alignstack => |alignment| try writer.print(
1253 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)
1254 " {s}={d}"
1255 else
1256 " {s}({d})",
1257 .{ @tagName(attribute), alignment.toByteUnits() orelse return },
1258 ),
1259 .allockind => |allockind| {1276 .allockind => |allockind| {
1260 try writer.print(" {s}(\"", .{@tagName(attribute)});1277 try w.print(" {t}(\"", .{attribute});
1261 var any = false;1278 var any = false;
1262 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {1279 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {
1263 if (comptime std.mem.eql(u8, field.name, "_")) continue;1280 if (comptime std.mem.eql(u8, field.name, "_")) continue;
1264 if (@field(allockind, field.name)) {1281 if (@field(allockind, field.name)) {
1265 if (!any) {1282 if (!any) {
1266 try writer.writeByte(',');1283 try w.writeByte(',');
1267 any = true;1284 any = true;
1268 }1285 }
1269 try writer.writeAll(field.name);1286 try w.writeAll(field.name);
1270 }1287 }
1271 }1288 }
1272 try writer.writeAll("\")");1289 try w.writeAll("\")");
1273 },1290 },
1274 .allocsize => |allocsize| {1291 .allocsize => |allocsize| {
1275 try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });1292 try w.print(" {t}({d}", .{ attribute, allocsize.elem_size });
1276 if (allocsize.num_elems != AllocSize.none)1293 if (allocsize.num_elems != AllocSize.none)
1277 try writer.print(",{d}", .{allocsize.num_elems});1294 try w.print(",{d}", .{allocsize.num_elems});
1278 try writer.writeByte(')');1295 try w.writeByte(')');
1279 },1296 },
1280 .memory => |memory| {1297 .memory => |memory| {
1281 try writer.print(" {s}(", .{@tagName(attribute)});1298 try w.print(" {t}(", .{attribute});
1282 var any = memory.other != .none or1299 var any = memory.other != .none or
1283 (memory.argmem == .none and memory.inaccessiblemem == .none);1300 (memory.argmem == .none and memory.inaccessiblemem == .none);
1284 if (any) try writer.writeAll(@tagName(memory.other));1301 if (any) try w.writeAll(@tagName(memory.other));
1285 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {1302 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
1286 if (@field(memory, kind) != memory.other) {1303 if (@field(memory, kind) != memory.other) {
1287 if (any) try writer.writeAll(", ");1304 if (any) try w.writeAll(", ");
1288 try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });1305 try w.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
1289 any = true;1306 any = true;
1290 }1307 }
1291 }1308 }
1292 try writer.writeByte(')');1309 try w.writeByte(')');
1293 },1310 },
1294 .uwtable => |uwtable| if (uwtable != .none) {1311 .uwtable => |uwtable| if (uwtable != .none) {
1295 try writer.print(" {s}", .{@tagName(attribute)});1312 try w.print(" {s}", .{@tagName(attribute)});
1296 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});1313 if (uwtable != UwTable.default) try w.print("({s})", .{@tagName(uwtable)});
1297 },1314 },
1298 .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{1315 .vscale_range => |vscale_range| try w.print(" {s}({d},{d})", .{
1299 @tagName(attribute),1316 @tagName(attribute),
1300 vscale_range.min.toByteUnits().?,1317 vscale_range.min.toByteUnits().?,
1301 vscale_range.max.toByteUnits() orelse 0,1318 vscale_range.max.toByteUnits() orelse 0,
1302 }),1319 }),
1303 .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) {1320 .string => |string_attr| if (data.flags.quote) {
1304 try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)});1321 try w.print(" {f}", .{string_attr.kind.fmtQ(data.builder)});
1305 if (string_attr.value != .empty)1322 if (string_attr.value != .empty)
1306 try writer.print("={\"}", .{string_attr.value.fmt(data.builder)});1323 try w.print("={f}", .{string_attr.value.fmtQ(data.builder)});
1307 },1324 },
1308 .none => unreachable,1325 .none => unreachable,
1309 }1326 }
1310 }1327 }
1311 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {1328 pub fn fmt(self: Index, builder: *const Builder, mode: FormatData.mode) std.fmt.Formatter(FormatData, format) {
1312 return .{ .data = .{ .attribute_index = self, .builder = builder } };1329 return .{ .data = .{ .attribute_index = self, .builder = builder, .mode = mode } };
1313 }1330 }
13141331
1315 fn toStorage(self: Index, builder: *const Builder) Storage {1332 fn toStorage(self: Index, builder: *const Builder) Storage {
...@@ -1582,20 +1599,18 @@ pub const Attributes = enum(u32) {...@@ -1582,20 +1599,18 @@ pub const Attributes = enum(u32) {
1582 const FormatData = struct {1599 const FormatData = struct {
1583 attributes: Attributes,1600 attributes: Attributes,
1584 builder: *const Builder,1601 builder: *const Builder,
1602 flags: Flags = .{},
1603 const Flags = Attribute.Index.FormatData.Flags;
1585 };1604 };
1586 fn format(1605 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(.{1606 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{
1593 .attribute_index = attribute_index,1607 .attribute_index = attribute_index,
1594 .builder = data.builder,1608 .builder = data.builder,
1595 }, fmt_str, fmt_opts, writer);1609 .flags = data.flags,
1610 }, w);
1596 }1611 }
1597 pub fn fmt(self: Attributes, builder: *const Builder) std.fmt.Formatter(format) {1612 pub fn fmt(self: Attributes, builder: *const Builder, flags: FormatData.Flags) std.fmt.Formatter(FormatData, format) {
1598 return .{ .data = .{ .attributes = self, .builder = builder } };1613 return .{ .data = .{ .attributes = self, .builder = builder, .flags = flags } };
1599 }1614 }
1600};1615};
16011616
...@@ -1781,24 +1796,14 @@ pub const Linkage = enum(u4) {...@@ -1781,24 +1796,14 @@ pub const Linkage = enum(u4) {
1781 extern_weak = 7,1796 extern_weak = 7,
1782 external = 0,1797 external = 0,
17831798
1784 pub fn format(1799 pub fn format(self: Linkage, w: *Writer) Writer.Error!void {
1785 self: Linkage,1800 if (self != .external) try w.print(" {s}", .{@tagName(self)});
1786 comptime _: []const u8,
1787 _: std.fmt.FormatOptions,
1788 writer: anytype,
1789 ) @TypeOf(writer).Error!void {
1790 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1791 }1801 }
17921802
1793 fn formatOptional(1803 fn formatOptional(data: ?Linkage, w: *Writer) Writer.Error!void {
1794 data: ?Linkage,1804 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 }1805 }
1801 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {1806 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(?Linkage, formatOptional) {
1802 return .{ .data = self };1807 return .{ .data = self };
1803 }1808 }
1804};1809};
...@@ -1808,13 +1813,8 @@ pub const Preemption = enum {...@@ -1808,13 +1813,8 @@ pub const Preemption = enum {
1808 dso_local,1813 dso_local,
1809 implicit_dso_local,1814 implicit_dso_local,
18101815
1811 pub fn format(1816 pub fn format(self: Preemption, w: *Writer) Writer.Error!void {
1812 self: Preemption,1817 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 }1818 }
1819};1819};
18201820
...@@ -1831,12 +1831,7 @@ pub const Visibility = enum(u2) {...@@ -1831,12 +1831,7 @@ pub const Visibility = enum(u2) {
1831 };1831 };
1832 }1832 }
18331833
1834 pub fn format(1834 pub fn format(self: Visibility, writer: *Writer) Writer.Error!void {
1835 self: Visibility,
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)});1835 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1841 }1836 }
1842};1837};
...@@ -1846,13 +1841,8 @@ pub const DllStorageClass = enum(u2) {...@@ -1846,13 +1841,8 @@ pub const DllStorageClass = enum(u2) {
1846 dllimport = 1,1841 dllimport = 1,
1847 dllexport = 2,1842 dllexport = 2,
18481843
1849 pub fn format(1844 pub fn format(self: DllStorageClass, w: *Writer) Writer.Error!void {
1850 self: DllStorageClass,1845 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 }1846 }
1857};1847};
18581848
...@@ -1863,15 +1853,31 @@ pub const ThreadLocal = enum(u3) {...@@ -1863,15 +1853,31 @@ pub const ThreadLocal = enum(u3) {
1863 initialexec = 3,1853 initialexec = 3,
1864 localexec = 4,1854 localexec = 4,
18651855
1866 pub fn format(1856 pub fn format(tl: ThreadLocal, w: *Writer) Writer.Error!void {
1867 self: ThreadLocal,1857 return Prefixed.format(.{ .thread_local = tl, .prefix = "" }, w);
1868 comptime prefix: []const u8,1858 }
1869 _: std.fmt.FormatOptions,1859
1870 writer: anytype,1860 pub const Prefixed = struct {
1871 ) @TypeOf(writer).Error!void {1861 thread_local: ThreadLocal,
1872 if (self == .default) return;1862 prefix: []const u8,
1873 try writer.print("{s}thread_local", .{prefix});1863
1874 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});1864 pub fn format(p: Prefixed, w: *Writer) Writer.Error!void {
1865 switch (p.thread_local) {
1866 .default => return,
1867 .generaldynamic => {
1868 var vecs: [2][]const u8 = .{ p.prefix, "thread_local" };
1869 return w.writeVecAll(&vecs);
1870 },
1871 else => {
1872 var vecs: [4][]const u8 = .{ p.prefix, "thread_local(", @tagName(p.thread_local), ")" };
1873 return w.writeVecAll(&vecs);
1874 },
1875 }
1876 }
1877 };
1878
1879 pub fn fmt(tl: ThreadLocal, prefix: []const u8) Prefixed {
1880 return .{ .thread_local = tl, .prefix = prefix };
1875 }1881 }
1876};1882};
18771883
...@@ -1882,13 +1888,8 @@ pub const UnnamedAddr = enum(u2) {...@@ -1882,13 +1888,8 @@ pub const UnnamedAddr = enum(u2) {
1882 unnamed_addr = 1,1888 unnamed_addr = 1,
1883 local_unnamed_addr = 2,1889 local_unnamed_addr = 2,
18841890
1885 pub fn format(1891 pub fn format(self: UnnamedAddr, w: *Writer) Writer.Error!void {
1886 self: UnnamedAddr,1892 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 }1893 }
1893};1894};
18941895
...@@ -1981,13 +1982,24 @@ pub const AddrSpace = enum(u24) {...@@ -1981,13 +1982,24 @@ pub const AddrSpace = enum(u24) {
1981 pub const funcref: AddrSpace = @enumFromInt(20);1982 pub const funcref: AddrSpace = @enumFromInt(20);
1982 };1983 };
19831984
1984 pub fn format(1985 pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void {
1985 self: AddrSpace,1986 return Prefixed.format(.{ .addr_space = addr_space, .prefix = "" }, w);
1986 comptime prefix: []const u8,1987 }
1987 _: std.fmt.FormatOptions,1988
1988 writer: anytype,1989 pub const Prefixed = struct {
1989 ) @TypeOf(writer).Error!void {1990 addr_space: AddrSpace,
1990 if (self != .default) try writer.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });1991 prefix: []const u8,
1992
1993 pub fn format(p: Prefixed, w: *Writer) Writer.Error!void {
1994 switch (p.addr_space) {
1995 .default => return,
1996 else => return w.print("{s}addrspace({d})", .{ p.prefix, p.addr_space }),
1997 }
1998 }
1999 };
2000
2001 pub fn fmt(addr_space: AddrSpace, prefix: []const u8) Prefixed {
2002 return .{ .addr_space = addr_space, .prefix = prefix };
1991 }2003 }
1992};2004};
19932005
...@@ -1995,15 +2007,8 @@ pub const ExternallyInitialized = enum {...@@ -1995,15 +2007,8 @@ pub const ExternallyInitialized = enum {
1995 default,2007 default,
1996 externally_initialized,2008 externally_initialized,
19972009
1998 pub fn format(2010 pub fn format(self: ExternallyInitialized, w: *Writer) Writer.Error!void {
1999 self: ExternallyInitialized,2011 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 }2012 }
2008};2013};
20092014
...@@ -2026,13 +2031,18 @@ pub const Alignment = enum(u6) {...@@ -2026,13 +2031,18 @@ pub const Alignment = enum(u6) {
2026 return if (self == .default) 0 else (@intFromEnum(self) + 1);2031 return if (self == .default) 0 else (@intFromEnum(self) + 1);
2027 }2032 }
20282033
2029 pub fn format(2034 pub const Prefixed = struct {
2030 self: Alignment,2035 alignment: Alignment,
2031 comptime prefix: []const u8,2036 prefix: []const u8,
2032 _: std.fmt.FormatOptions,2037
2033 writer: anytype,2038 pub fn format(p: Prefixed, w: *Writer) Writer.Error!void {
2034 ) @TypeOf(writer).Error!void {2039 const byte_units = p.alignment.toByteUnits() orelse return;
2035 try writer.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });2040 return w.print("{s}align ({d})", .{ p.prefix, byte_units });
2041 }
2042 };
2043
2044 pub fn fmt(alignment: Alignment, prefix: []const u8) Prefixed {
2045 return .{ .alignment = alignment, .prefix = prefix };
2036 }2046 }
2037};2047};
20382048
...@@ -2105,12 +2115,7 @@ pub const CallConv = enum(u10) {...@@ -2105,12 +2115,7 @@ pub const CallConv = enum(u10) {
21052115
2106 pub const default = CallConv.ccc;2116 pub const default = CallConv.ccc;
21072117
2108 pub fn format(2118 pub fn format(self: CallConv, w: *Writer) 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) {2119 switch (self) {
2115 default => {},2120 default => {},
2116 .fastcc,2121 .fastcc,
...@@ -2164,8 +2169,8 @@ pub const CallConv = enum(u10) {...@@ -2164,8 +2169,8 @@ pub const CallConv = enum(u10) {
2164 .aarch64_sme_preservemost_from_x2,2169 .aarch64_sme_preservemost_from_x2,
2165 .m68k_rtdcc,2170 .m68k_rtdcc,
2166 .riscv_vectorcallcc,2171 .riscv_vectorcallcc,
2167 => try writer.print(" {s}", .{@tagName(self)}),2172 => try w.print(" {s}", .{@tagName(self)}),
2168 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2173 _ => try w.print(" cc{d}", .{@intFromEnum(self)}),
2169 }2174 }
2170 }2175 }
2171};2176};
...@@ -2190,31 +2195,25 @@ pub const StrtabString = enum(u32) {...@@ -2190,31 +2195,25 @@ pub const StrtabString = enum(u32) {
2190 const FormatData = struct {2195 const FormatData = struct {
2191 string: StrtabString,2196 string: StrtabString,
2192 builder: *const Builder,2197 builder: *const Builder,
2198 quote_behavior: ?QuoteBehavior,
2193 };2199 };
2194 fn format(2200 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);2201 assert(data.string != .none);
2203 const string_slice = data.string.slice(data.builder) orelse2202 const string_slice = data.string.slice(data.builder) orelse
2204 return writer.print("{d}", .{@intFromEnum(data.string)});2203 return w.print("{d}", .{@intFromEnum(data.string)});
2205 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|2204 const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice);
2206 return writer.writeAll(string_slice);2205 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 }2206 }
2216 pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) {2207 pub fn fmt(
2217 return .{ .data = .{ .string = self, .builder = builder } };2208 self: StrtabString,
2209 builder: *const Builder,
2210 quote_behavior: ?QuoteBehavior,
2211 ) std.fmt.Formatter(FormatData, format) {
2212 return .{ .data = .{
2213 .string = self,
2214 .builder = builder,
2215 .quote_behavior = quote_behavior,
2216 } };
2218 }2217 }
22192218
2220 fn fromIndex(index: ?usize) StrtabString {2219 fn fromIndex(index: ?usize) StrtabString {
...@@ -2264,7 +2263,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a...@@ -2264,7 +2263,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a
2264}2263}
22652264
2266pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString {2265pub 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;2266 self.strtab_string_bytes.printAssumeCapacity(fmt_str, fmt_args);
2268 return self.trailingStrtabStringAssumeCapacity();2267 return self.trailingStrtabStringAssumeCapacity();
2269}2268}
22702269
...@@ -2383,17 +2382,12 @@ pub const Global = struct {...@@ -2383,17 +2382,12 @@ pub const Global = struct {
2383 global: Index,2382 global: Index,
2384 builder: *const Builder,2383 builder: *const Builder,
2385 };2384 };
2386 fn format(2385 fn format(data: FormatData, w: *Writer) Writer.Error!void {
2387 data: FormatData,2386 try w.print("@{f}", .{
2388 comptime _: []const u8,2387 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder, null),
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),
2394 });2388 });
2395 }2389 }
2396 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {2390 pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
2397 return .{ .data = .{ .global = self, .builder = builder } };2391 return .{ .data = .{ .global = self, .builder = builder } };
2398 }2392 }
23992393
...@@ -4833,29 +4827,23 @@ pub const Function = struct {...@@ -4833,29 +4827,23 @@ pub const Function = struct {
4833 instruction: Instruction.Index,4827 instruction: Instruction.Index,
4834 function: Function.Index,4828 function: Function.Index,
4835 builder: *Builder,4829 builder: *Builder,
4830 flags: FormatFlags,
4836 };4831 };
4837 fn format(4832 fn format(data: FormatData, w: *Writer) Writer.Error!void {
4838 data: FormatData,4833 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;4834 if (data.instruction == .none) return;
4847 try writer.writeByte(',');4835 try w.writeByte(',');
4848 }4836 }
4849 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {4837 if (data.flags.space) {
4850 if (data.instruction == .none) return;4838 if (data.instruction == .none) return;
4851 try writer.writeByte(' ');4839 try w.writeByte(' ');
4852 }4840 }
4853 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null) try writer.print(4841 if (data.flags.percent) try w.print(
4854 "{%} ",4842 "{f} ",
4855 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},4843 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder, .percent)},
4856 );4844 );
4857 assert(data.instruction != .none);4845 assert(data.instruction != .none);
4858 try writer.print("%{}", .{4846 try w.print("%{f}", .{
4859 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),4847 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),
4860 });4848 });
4861 }4849 }
...@@ -4863,8 +4851,14 @@ pub const Function = struct {...@@ -4863,8 +4851,14 @@ pub const Function = struct {
4863 self: Instruction.Index,4851 self: Instruction.Index,
4864 function: Function.Index,4852 function: Function.Index,
4865 builder: *Builder,4853 builder: *Builder,
4866 ) std.fmt.Formatter(format) {4854 flags: FormatFlags,
4867 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };4855 ) std.fmt.Formatter(FormatData, format) {
4856 return .{ .data = .{
4857 .instruction = self,
4858 .function = function,
4859 .builder = builder,
4860 .flags = flags,
4861 } };
4868 }4862 }
4869 };4863 };
48704864
...@@ -6361,10 +6355,10 @@ pub const WipFunction = struct {...@@ -6361,10 +6355,10 @@ pub const WipFunction = struct {
63616355
6362 while (true) {6356 while (true) {
6363 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);6357 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);
6364 const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{6358 const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{
6365 name.fmt(wip_name.builder),6359 name.fmtRaw(wip_name.builder),
6366 sep,6360 sep,
6367 gop.value_ptr.fmt(wip_name.builder),6361 gop.value_ptr.fmtRaw(wip_name.builder),
6368 });6362 });
6369 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);6363 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);
6370 if (!unique_gop.found_existing) {6364 if (!unique_gop.found_existing) {
...@@ -7031,13 +7025,27 @@ pub const MemoryAccessKind = enum(u1) {...@@ -7031,13 +7025,27 @@ pub const MemoryAccessKind = enum(u1) {
7031 normal,7025 normal,
7032 @"volatile",7026 @"volatile",
70337027
7034 pub fn format(7028 pub fn format(memory_access_kind: MemoryAccessKind, w: *Writer) Writer.Error!void {
7035 self: MemoryAccessKind,7029 return Prefixed.format(.{ .memory_access_kind = memory_access_kind, .prefix = "" }, w);
7036 comptime prefix: []const u8,7030 }
7037 _: std.fmt.FormatOptions,7031
7038 writer: anytype,7032 pub const Prefixed = struct {
7039 ) @TypeOf(writer).Error!void {7033 memory_access_kind: MemoryAccessKind,
7040 if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) });7034 prefix: []const u8,
7035
7036 pub fn format(p: Prefixed, w: *Writer) Writer.Error!void {
7037 switch (p.memory_access_kind) {
7038 .normal => return,
7039 .@"volatile" => {
7040 var vecs: [2][]const u8 = .{ p.prefix, "volatile" };
7041 return w.writeVecAll(&vecs);
7042 },
7043 }
7044 }
7045 };
7046
7047 pub fn fmt(memory_access_kind: MemoryAccessKind, prefix: []const u8) Prefixed {
7048 return .{ .memory_access_kind = memory_access_kind, .prefix = prefix };
7041 }7049 }
7042};7050};
70437051
...@@ -7045,15 +7053,27 @@ pub const SyncScope = enum(u1) {...@@ -7045,15 +7053,27 @@ pub const SyncScope = enum(u1) {
7045 singlethread,7053 singlethread,
7046 system,7054 system,
70477055
7048 pub fn format(7056 pub fn format(sync_scope: SyncScope, w: *Writer) Writer.Error!void {
7049 self: SyncScope,7057 return Prefixed.format(.{ .sync_scope = sync_scope, .prefix = "" }, w);
7050 comptime prefix: []const u8,7058 }
7051 _: std.fmt.FormatOptions,7059
7052 writer: anytype,7060 pub const Prefixed = struct {
7053 ) @TypeOf(writer).Error!void {7061 sync_scope: SyncScope,
7054 if (self != .system) try writer.print(7062 prefix: []const u8,
7055 \\{s}syncscope("{s}")7063
7056 , .{ prefix, @tagName(self) });7064 pub fn format(p: Prefixed, w: *Writer) Writer.Error!void {
7065 switch (p.sync_scope) {
7066 .system => return,
7067 .singlethread => {
7068 var vecs: [2][]const u8 = .{ p.prefix, "syncscope(\"singlethread\")" };
7069 return w.writeVecAll(&vecs);
7070 },
7071 }
7072 }
7073 };
7074
7075 pub fn fmt(sync_scope: SyncScope, prefix: []const u8) Prefixed {
7076 return .{ .sync_scope = sync_scope, .prefix = prefix };
7057 }7077 }
7058};7078};
70597079
...@@ -7066,13 +7086,27 @@ pub const AtomicOrdering = enum(u3) {...@@ -7066,13 +7086,27 @@ pub const AtomicOrdering = enum(u3) {
7066 acq_rel = 5,7086 acq_rel = 5,
7067 seq_cst = 6,7087 seq_cst = 6,
70687088
7069 pub fn format(7089 pub fn format(atomic_ordering: AtomicOrdering, w: *Writer) Writer.Error!void {
7070 self: AtomicOrdering,7090 return Prefixed.format(.{ .atomic_ordering = atomic_ordering, .prefix = "" }, w);
7071 comptime prefix: []const u8,7091 }
7072 _: std.fmt.FormatOptions,7092
7073 writer: anytype,7093 pub const Prefixed = struct {
7074 ) @TypeOf(writer).Error!void {7094 atomic_ordering: AtomicOrdering,
7075 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });7095 prefix: []const u8,
7096
7097 pub fn format(p: Prefixed, w: *Writer) Writer.Error!void {
7098 switch (p.atomic_ordering) {
7099 .none => return,
7100 else => {
7101 var vecs: [2][]const u8 = .{ p.prefix, @tagName(p.atomic_ordering) };
7102 return w.writeVecAll(&vecs);
7103 },
7104 }
7105 }
7106 };
7107
7108 pub fn fmt(atomic_ordering: AtomicOrdering, prefix: []const u8) Prefixed {
7109 return .{ .atomic_ordering = atomic_ordering, .prefix = prefix };
7076 }7110 }
7077};7111};
70787112
...@@ -7486,27 +7520,21 @@ pub const Constant = enum(u32) {...@@ -7486,27 +7520,21 @@ pub const Constant = enum(u32) {
7486 const FormatData = struct {7520 const FormatData = struct {
7487 constant: Constant,7521 constant: Constant,
7488 builder: *Builder,7522 builder: *Builder,
7523 flags: FormatFlags,
7489 };7524 };
7490 fn format(7525 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7491 data: FormatData,7526 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;7527 if (data.constant == .no_init) return;
7500 try writer.writeByte(',');7528 try w.writeByte(',');
7501 }7529 }
7502 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {7530 if (data.flags.space) {
7503 if (data.constant == .no_init) return;7531 if (data.constant == .no_init) return;
7504 try writer.writeByte(' ');7532 try w.writeByte(' ');
7505 }7533 }
7506 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null)7534 if (data.flags.percent)
7507 try writer.print("{%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});7535 try w.print("{f} ", .{data.constant.typeOf(data.builder).fmt(data.builder, .percent)});
7508 assert(data.constant != .no_init);7536 assert(data.constant != .no_init);
7509 if (std.enums.tagName(Constant, data.constant)) |name| return writer.writeAll(name);7537 if (std.enums.tagName(Constant, data.constant)) |name| return w.writeAll(name);
7510 switch (data.constant.unwrap()) {7538 switch (data.constant.unwrap()) {
7511 .constant => |constant| {7539 .constant => |constant| {
7512 const item = data.builder.constant_items.get(constant);7540 const item = data.builder.constant_items.get(constant);
...@@ -7543,13 +7571,13 @@ pub const Constant = enum(u32) {...@@ -7543,13 +7571,13 @@ pub const Constant = enum(u32) {
7543 var stack align(@alignOf(ExpectedContents)) =7571 var stack align(@alignOf(ExpectedContents)) =
7544 std.heap.stackFallback(@sizeOf(ExpectedContents), data.builder.gpa);7572 std.heap.stackFallback(@sizeOf(ExpectedContents), data.builder.gpa);
7545 const allocator = stack.get();7573 const allocator = stack.get();
7546 const str = try bigint.toStringAlloc(allocator, 10, undefined);7574 const str = bigint.toStringAlloc(allocator, 10, undefined) catch return error.WriteFailed;
7547 defer allocator.free(str);7575 defer allocator.free(str);
7548 try writer.writeAll(str);7576 try w.writeAll(str);
7549 },7577 },
7550 .half,7578 .half,
7551 .bfloat,7579 .bfloat,
7552 => |tag| try writer.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {7580 => |tag| try w.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {
7553 .half => 'H',7581 .half => 'H',
7554 .bfloat => 'R',7582 .bfloat => 'R',
7555 else => unreachable,7583 else => unreachable,
...@@ -7580,7 +7608,7 @@ pub const Constant = enum(u32) {...@@ -7580,7 +7608,7 @@ pub const Constant = enum(u32) {
7580 ) + 1,7608 ) + 1,
7581 else => 0,7609 else => 0,
7582 };7610 };
7583 try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){7611 try w.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){
7584 .mantissa = std.math.shl(7612 .mantissa = std.math.shl(
7585 Mantissa64,7613 Mantissa64,
7586 repr.mantissa,7614 repr.mantissa,
...@@ -7602,13 +7630,13 @@ pub const Constant = enum(u32) {...@@ -7602,13 +7630,13 @@ pub const Constant = enum(u32) {
7602 },7630 },
7603 .double => {7631 .double => {
7604 const extra = data.builder.constantExtraData(Double, item.data);7632 const extra = data.builder.constantExtraData(Double, item.data);
7605 try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });7633 try w.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
7606 },7634 },
7607 .fp128,7635 .fp128,
7608 .ppc_fp128,7636 .ppc_fp128,
7609 => |tag| {7637 => |tag| {
7610 const extra = data.builder.constantExtraData(Fp128, item.data);7638 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}", .{7639 try w.print("0x{c}{X:0>8}{X:0>8}{X:0>8}{X:0>8}", .{
7612 @as(u8, switch (tag) {7640 @as(u8, switch (tag) {
7613 .fp128 => 'L',7641 .fp128 => 'L',
7614 .ppc_fp128 => 'M',7642 .ppc_fp128 => 'M',
...@@ -7622,7 +7650,7 @@ pub const Constant = enum(u32) {...@@ -7622,7 +7650,7 @@ pub const Constant = enum(u32) {
7622 },7650 },
7623 .x86_fp80 => {7651 .x86_fp80 => {
7624 const extra = data.builder.constantExtraData(Fp80, item.data);7652 const extra = data.builder.constantExtraData(Fp80, item.data);
7625 try writer.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{7653 try w.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{
7626 extra.hi, extra.lo_hi, extra.lo_lo,7654 extra.hi, extra.lo_hi, extra.lo_lo,
7627 });7655 });
7628 },7656 },
...@@ -7631,7 +7659,7 @@ pub const Constant = enum(u32) {...@@ -7631,7 +7659,7 @@ pub const Constant = enum(u32) {
7631 .zeroinitializer,7659 .zeroinitializer,
7632 .undef,7660 .undef,
7633 .poison,7661 .poison,
7634 => |tag| try writer.writeAll(@tagName(tag)),7662 => |tag| try w.writeAll(@tagName(tag)),
7635 .structure,7663 .structure,
7636 .packed_structure,7664 .packed_structure,
7637 .array,7665 .array,
...@@ -7640,7 +7668,7 @@ pub const Constant = enum(u32) {...@@ -7640,7 +7668,7 @@ pub const Constant = enum(u32) {
7640 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);7668 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);
7641 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));7669 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));
7642 const vals = extra.trail.next(len, Constant, data.builder);7670 const vals = extra.trail.next(len, Constant, data.builder);
7643 try writer.writeAll(switch (tag) {7671 try w.writeAll(switch (tag) {
7644 .structure => "{ ",7672 .structure => "{ ",
7645 .packed_structure => "<{ ",7673 .packed_structure => "<{ ",
7646 .array => "[",7674 .array => "[",
...@@ -7648,10 +7676,10 @@ pub const Constant = enum(u32) {...@@ -7648,10 +7676,10 @@ pub const Constant = enum(u32) {
7648 else => unreachable,7676 else => unreachable,
7649 });7677 });
7650 for (vals, 0..) |val, index| {7678 for (vals, 0..) |val, index| {
7651 if (index > 0) try writer.writeAll(", ");7679 if (index > 0) try w.writeAll(", ");
7652 try writer.print("{%}", .{val.fmt(data.builder)});7680 try w.print("{f}", .{val.fmt(data.builder, .{ .percent = true })});
7653 }7681 }
7654 try writer.writeAll(switch (tag) {7682 try w.writeAll(switch (tag) {
7655 .structure => " }",7683 .structure => " }",
7656 .packed_structure => " }>",7684 .packed_structure => " }>",
7657 .array => "]",7685 .array => "]",
...@@ -7662,30 +7690,30 @@ pub const Constant = enum(u32) {...@@ -7662,30 +7690,30 @@ pub const Constant = enum(u32) {
7662 .splat => {7690 .splat => {
7663 const extra = data.builder.constantExtraData(Splat, item.data);7691 const extra = data.builder.constantExtraData(Splat, item.data);
7664 const len = extra.type.vectorLen(data.builder);7692 const len = extra.type.vectorLen(data.builder);
7665 try writer.writeByte('<');7693 try w.writeByte('<');
7666 for (0..len) |index| {7694 for (0..len) |index| {
7667 if (index > 0) try writer.writeAll(", ");7695 if (index > 0) try w.writeAll(", ");
7668 try writer.print("{%}", .{extra.value.fmt(data.builder)});7696 try w.print("{f}", .{extra.value.fmt(data.builder, .{ .percent = true })});
7669 }7697 }
7670 try writer.writeByte('>');7698 try w.writeByte('>');
7671 },7699 },
7672 .string => try writer.print("c{\"}", .{7700 .string => try w.print("c{f}", .{
7673 @as(String, @enumFromInt(item.data)).fmt(data.builder),7701 @as(String, @enumFromInt(item.data)).fmtQ(data.builder),
7674 }),7702 }),
7675 .blockaddress => |tag| {7703 .blockaddress => |tag| {
7676 const extra = data.builder.constantExtraData(BlockAddress, item.data);7704 const extra = data.builder.constantExtraData(BlockAddress, item.data);
7677 const function = extra.function.ptrConst(data.builder);7705 const function = extra.function.ptrConst(data.builder);
7678 try writer.print("{s}({}, {})", .{7706 try w.print("{s}({f}, {f})", .{
7679 @tagName(tag),7707 @tagName(tag),
7680 function.global.fmt(data.builder),7708 function.global.fmt(data.builder),
7681 extra.block.toInst(function).fmt(extra.function, data.builder),7709 extra.block.toInst(function).fmt(extra.function, data.builder, .{}),
7682 });7710 });
7683 },7711 },
7684 .dso_local_equivalent,7712 .dso_local_equivalent,
7685 .no_cfi,7713 .no_cfi,
7686 => |tag| {7714 => |tag| {
7687 const function: Function.Index = @enumFromInt(item.data);7715 const function: Function.Index = @enumFromInt(item.data);
7688 try writer.print("{s} {}", .{7716 try w.print("{s} {f}", .{
7689 @tagName(tag),7717 @tagName(tag),
7690 function.ptrConst(data.builder).global.fmt(data.builder),7718 function.ptrConst(data.builder).global.fmt(data.builder),
7691 });7719 });
...@@ -7697,10 +7725,10 @@ pub const Constant = enum(u32) {...@@ -7697,10 +7725,10 @@ pub const Constant = enum(u32) {
7697 .addrspacecast,7725 .addrspacecast,
7698 => |tag| {7726 => |tag| {
7699 const extra = data.builder.constantExtraData(Cast, item.data);7727 const extra = data.builder.constantExtraData(Cast, item.data);
7700 try writer.print("{s} ({%} to {%})", .{7728 try w.print("{s} ({f} to {f})", .{
7701 @tagName(tag),7729 @tagName(tag),
7702 extra.val.fmt(data.builder),7730 extra.val.fmt(data.builder, .{ .percent = true }),
7703 extra.type.fmt(data.builder),7731 extra.type.fmt(data.builder, .percent),
7704 });7732 });
7705 },7733 },
7706 .getelementptr,7734 .getelementptr,
...@@ -7709,13 +7737,13 @@ pub const Constant = enum(u32) {...@@ -7709,13 +7737,13 @@ pub const Constant = enum(u32) {
7709 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);7737 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);
7710 const indices =7738 const indices =
7711 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);7739 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);
7712 try writer.print("{s} ({%}, {%}", .{7740 try w.print("{s} ({f}, {f}", .{
7713 @tagName(tag),7741 @tagName(tag),
7714 extra.data.type.fmt(data.builder),7742 extra.data.type.fmt(data.builder, .percent),
7715 extra.data.base.fmt(data.builder),7743 extra.data.base.fmt(data.builder, .{ .percent = true }),
7716 });7744 });
7717 for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});7745 for (indices) |index| try w.print(", {f}", .{index.fmt(data.builder, .{ .percent = true })});
7718 try writer.writeByte(')');7746 try w.writeByte(')');
7719 },7747 },
7720 .add,7748 .add,
7721 .@"add nsw",7749 .@"add nsw",
...@@ -7727,10 +7755,10 @@ pub const Constant = enum(u32) {...@@ -7727,10 +7755,10 @@ pub const Constant = enum(u32) {
7727 .xor,7755 .xor,
7728 => |tag| {7756 => |tag| {
7729 const extra = data.builder.constantExtraData(Binary, item.data);7757 const extra = data.builder.constantExtraData(Binary, item.data);
7730 try writer.print("{s} ({%}, {%})", .{7758 try w.print("{s} ({f}, {f})", .{
7731 @tagName(tag),7759 @tagName(tag),
7732 extra.lhs.fmt(data.builder),7760 extra.lhs.fmt(data.builder, .{ .percent = true }),
7733 extra.rhs.fmt(data.builder),7761 extra.rhs.fmt(data.builder, .{ .percent = true }),
7734 });7762 });
7735 },7763 },
7736 .@"asm",7764 .@"asm",
...@@ -7751,19 +7779,23 @@ pub const Constant = enum(u32) {...@@ -7751,19 +7779,23 @@ pub const Constant = enum(u32) {
7751 .@"asm sideeffect alignstack inteldialect unwind",7779 .@"asm sideeffect alignstack inteldialect unwind",
7752 => |tag| {7780 => |tag| {
7753 const extra = data.builder.constantExtraData(Assembly, item.data);7781 const extra = data.builder.constantExtraData(Assembly, item.data);
7754 try writer.print("{s} {\"}, {\"}", .{7782 try w.print("{s} {f}, {f}", .{
7755 @tagName(tag),7783 @tagName(tag),
7756 extra.assembly.fmt(data.builder),7784 extra.assembly.fmtQ(data.builder),
7757 extra.constraints.fmt(data.builder),7785 extra.constraints.fmtQ(data.builder),
7758 });7786 });
7759 },7787 },
7760 }7788 }
7761 },7789 },
7762 .global => |global| try writer.print("{}", .{global.fmt(data.builder)}),7790 .global => |global| try w.print("{f}", .{global.fmt(data.builder)}),
7763 }7791 }
7764 }7792 }
7765 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {7793 pub fn fmt(self: Constant, builder: *Builder, flags: FormatFlags) std.fmt.Formatter(FormatData, format) {
7766 return .{ .data = .{ .constant = self, .builder = builder } };7794 return .{ .data = .{
7795 .constant = self,
7796 .builder = builder,
7797 .flags = flags,
7798 } };
7767 }7799 }
7768};7800};
77697801
...@@ -7818,28 +7850,26 @@ pub const Value = enum(u32) {...@@ -7818,28 +7850,26 @@ pub const Value = enum(u32) {
7818 value: Value,7850 value: Value,
7819 function: Function.Index,7851 function: Function.Index,
7820 builder: *Builder,7852 builder: *Builder,
7853 flags: FormatFlags,
7821 };7854 };
7822 fn format(7855 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()) {7856 switch (data.value.unwrap()) {
7829 .instruction => |instruction| try Function.Instruction.Index.format(.{7857 .instruction => |instruction| try Function.Instruction.Index.format(.{
7830 .instruction = instruction,7858 .instruction = instruction,
7831 .function = data.function,7859 .function = data.function,
7832 .builder = data.builder,7860 .builder = data.builder,
7833 }, fmt_str, fmt_opts, writer),7861 .flags = data.flags,
7862 }, w),
7834 .constant => |constant| try Constant.format(.{7863 .constant => |constant| try Constant.format(.{
7835 .constant = constant,7864 .constant = constant,
7836 .builder = data.builder,7865 .builder = data.builder,
7837 }, fmt_str, fmt_opts, writer),7866 .flags = data.flags,
7867 }, w),
7838 .metadata => unreachable,7868 .metadata => unreachable,
7839 }7869 }
7840 }7870 }
7841 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) {7871 pub fn fmt(self: Value, function: Function.Index, builder: *Builder, flags: FormatFlags) std.fmt.Formatter(FormatData, format) {
7842 return .{ .data = .{ .value = self, .function = function, .builder = builder } };7872 return .{ .data = .{ .value = self, .function = function, .builder = builder, .flags = flags } };
7843 }7873 }
7844};7874};
78457875
...@@ -7869,15 +7899,10 @@ pub const MetadataString = enum(u32) {...@@ -7869,15 +7899,10 @@ pub const MetadataString = enum(u32) {
7869 metadata_string: MetadataString,7899 metadata_string: MetadataString,
7870 builder: *const Builder,7900 builder: *const Builder,
7871 };7901 };
7872 fn format(7902 fn format(data: FormatData, w: *Writer) Writer.Error!void {
7873 data: FormatData,7903 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 }7904 }
7880 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {7905 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(FormatData, format) {
7881 return .{ .data = .{ .metadata_string = self, .builder = builder } };7906 return .{ .data = .{ .metadata_string = self, .builder = builder } };
7882 }7907 }
7883};7908};
...@@ -8039,29 +8064,24 @@ pub const Metadata = enum(u32) {...@@ -8039,29 +8064,24 @@ pub const Metadata = enum(u32) {
8039 AllCallsDescribed: bool = false,8064 AllCallsDescribed: bool = false,
8040 Unused: u2 = 0,8065 Unused: u2 = 0,
80418066
8042 pub fn format(8067 pub fn format(self: DIFlags, w: *Writer) 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;8068 var need_pipe = false;
8049 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {8069 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {
8050 switch (@typeInfo(field.type)) {8070 switch (@typeInfo(field.type)) {
8051 .bool => if (@field(self, field.name)) {8071 .bool => if (@field(self, field.name)) {
8052 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;8072 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8053 try writer.print("DIFlag{s}", .{field.name});8073 try w.print("DIFlag{s}", .{field.name});
8054 },8074 },
8055 .@"enum" => if (@field(self, field.name) != .Zero) {8075 .@"enum" => if (@field(self, field.name) != .Zero) {
8056 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;8076 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8057 try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))});8077 try w.print("DIFlag{s}", .{@tagName(@field(self, field.name))});
8058 },8078 },
8059 .int => assert(@field(self, field.name) == 0),8079 .int => assert(@field(self, field.name) == 0),
8060 else => @compileError("bad field type: " ++ field.name ++ ": " ++8080 else => @compileError("bad field type: " ++ field.name ++ ": " ++
8061 @typeName(field.type)),8081 @typeName(field.type)),
8062 }8082 }
8063 }8083 }
8064 if (!need_pipe) try writer.writeByte('0');8084 if (!need_pipe) try w.writeByte('0');
8065 }8085 }
8066 };8086 };
80678087
...@@ -8101,29 +8121,24 @@ pub const Metadata = enum(u32) {...@@ -8101,29 +8121,24 @@ pub const Metadata = enum(u32) {
8101 ObjCDirect: bool = false,8121 ObjCDirect: bool = false,
8102 Unused: u20 = 0,8122 Unused: u20 = 0,
81038123
8104 pub fn format(8124 pub fn format(self: DISPFlags, w: *Writer) 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;8125 var need_pipe = false;
8111 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {8126 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {
8112 switch (@typeInfo(field.type)) {8127 switch (@typeInfo(field.type)) {
8113 .bool => if (@field(self, field.name)) {8128 .bool => if (@field(self, field.name)) {
8114 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;8129 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8115 try writer.print("DISPFlag{s}", .{field.name});8130 try w.print("DISPFlag{s}", .{field.name});
8116 },8131 },
8117 .@"enum" => if (@field(self, field.name) != .Zero) {8132 .@"enum" => if (@field(self, field.name) != .Zero) {
8118 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;8133 if (need_pipe) try w.writeAll(" | ") else need_pipe = true;
8119 try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});8134 try w.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});
8120 },8135 },
8121 .int => assert(@field(self, field.name) == 0),8136 .int => assert(@field(self, field.name) == 0),
8122 else => @compileError("bad field type: " ++ field.name ++ ": " ++8137 else => @compileError("bad field type: " ++ field.name ++ ": " ++
8123 @typeName(field.type)),8138 @typeName(field.type)),
8124 }8139 }
8125 }8140 }
8126 if (!need_pipe) try writer.writeByte('0');8141 if (!need_pipe) try w.writeByte('0');
8127 }8142 }
8128 };8143 };
81298144
...@@ -8298,6 +8313,7 @@ pub const Metadata = enum(u32) {...@@ -8298,6 +8313,7 @@ pub const Metadata = enum(u32) {
8298 formatter: *Formatter,8313 formatter: *Formatter,
8299 prefix: []const u8 = "",8314 prefix: []const u8 = "",
8300 node: Node,8315 node: Node,
8316 specialized: ?FormatFlags,
83018317
8302 const Node = union(enum) {8318 const Node = union(enum) {
8303 none,8319 none,
...@@ -8323,20 +8339,14 @@ pub const Metadata = enum(u32) {...@@ -8323,20 +8339,14 @@ pub const Metadata = enum(u32) {
8323 };8339 };
8324 };8340 };
8325 };8341 };
8326 fn format(8342 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;8343 if (data.node == .none) return;
83338344
8334 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';8345 const is_specialized = data.specialized != null;
8335 const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str;
83368346
8337 if (data.formatter.need_comma) try writer.writeAll(", ");8347 if (data.formatter.need_comma) try w.writeAll(", ");
8338 defer data.formatter.need_comma = true;8348 defer data.formatter.need_comma = true;
8339 try writer.writeAll(data.prefix);8349 try w.writeAll(data.prefix);
83408350
8341 const builder = data.formatter.builder;8351 const builder = data.formatter.builder;
8342 switch (data.node) {8352 switch (data.node) {
...@@ -8351,54 +8361,57 @@ pub const Metadata = enum(u32) {...@@ -8351,54 +8361,57 @@ pub const Metadata = enum(u32) {
8351 .expression => {8361 .expression => {
8352 var extra = builder.metadataExtraDataTrail(Expression, item.data);8362 var extra = builder.metadataExtraDataTrail(Expression, item.data);
8353 const elements = extra.trail.next(extra.data.elements_len, u32, builder);8363 const elements = extra.trail.next(extra.data.elements_len, u32, builder);
8354 try writer.writeAll("!DIExpression(");8364 try w.writeAll("!DIExpression(");
8355 for (elements) |element| try format(.{8365 for (elements) |element| try format(.{
8356 .formatter = data.formatter,8366 .formatter = data.formatter,
8357 .node = .{ .u64 = element },8367 .node = .{ .u64 = element },
8358 }, "%", fmt_opts, writer);8368 .specialized = .{ .percent = true },
8359 try writer.writeByte(')');8369 }, w);
8370 try w.writeByte(')');
8360 },8371 },
8361 .constant => try Constant.format(.{8372 .constant => try Constant.format(.{
8362 .constant = @enumFromInt(item.data),8373 .constant = @enumFromInt(item.data),
8363 .builder = builder,8374 .builder = builder,
8364 }, recurse_fmt_str, fmt_opts, writer),8375 .flags = data.specialized orelse .{},
8376 }, w),
8365 else => unreachable,8377 else => unreachable,
8366 }8378 }
8367 },8379 },
8368 .index => |node| try writer.print("!{d}", .{node}),8380 .index => |node| try w.print("!{d}", .{node}),
8369 inline .local_value, .local_metadata => |node, tag| try Value.format(.{8381 inline .local_value, .local_metadata => |node, tag| try Value.format(.{
8370 .value = node.value,8382 .value = node.value,
8371 .function = node.function,8383 .function = node.function,
8372 .builder = builder,8384 .builder = builder,
8373 }, switch (tag) {8385 .flags = switch (tag) {
8374 .local_value => recurse_fmt_str,8386 .local_value => data.specialized orelse .{},
8375 .local_metadata => "%",8387 .local_metadata => .{ .percent = true },
8376 else => unreachable,8388 else => unreachable,
8377 }, fmt_opts, writer),8389 },
8390 }, w),
8378 inline .local_inline, .local_index => |node, tag| {8391 inline .local_inline, .local_index => |node, tag| {
8379 if (comptime std.mem.eql(u8, recurse_fmt_str, "%"))8392 if (data.specialized) |flags| {
8380 try writer.print("{%} ", .{Type.metadata.fmt(builder)});8393 if (flags.onlyPercent()) {
8394 try w.print("{f} ", .{Type.metadata.fmt(builder, .percent)});
8395 }
8396 }
8381 try format(.{8397 try format(.{
8382 .formatter = data.formatter,8398 .formatter = data.formatter,
8383 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),8399 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),
8384 }, "%", fmt_opts, writer);8400 .specialized = .{ .percent = true },
8401 }, w);
8385 },8402 },
8386 .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{8403 .string => |node| try w.print("{s}{f}", .{
8387 node.fmt(builder),8404 @as([]const u8, if (is_specialized) "" else "!"), node.fmt(builder),
8388 }),8405 }),
8389 inline .bool,8406 inline .bool, .u32, .u64 => |node| try w.print("{}", .{node}),
8390 .u32,8407 inline .di_flags, .sp_flags => |node| try w.print("{f}", .{node}),
8391 .u64,8408 .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 }8409 }
8397 }8410 }
8398 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {8411 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype, special: ?FormatFlags) switch (@TypeOf(node)) {
8399 Metadata => Allocator.Error,8412 Metadata => Allocator.Error,
8400 else => error{},8413 else => error{},
8401 }!std.fmt.Formatter(format) {8414 }!std.fmt.Formatter(FormatData, format) {
8402 const Node = @TypeOf(node);8415 const Node = @TypeOf(node);
8403 const MaybeNode = switch (@typeInfo(Node)) {8416 const MaybeNode = switch (@typeInfo(Node)) {
8404 .optional => Node,8417 .optional => Node,
...@@ -8435,6 +8448,7 @@ pub const Metadata = enum(u32) {...@@ -8435,6 +8448,7 @@ pub const Metadata = enum(u32) {
8435 .optional, .null => .none,8448 .optional, .null => .none,
8436 else => unreachable,8449 else => unreachable,
8437 },8450 },
8451 .specialized = special,
8438 } };8452 } };
8439 }8453 }
8440 inline fn fmtLocal(8454 inline fn fmtLocal(
...@@ -8442,7 +8456,7 @@ pub const Metadata = enum(u32) {...@@ -8442,7 +8456,7 @@ pub const Metadata = enum(u32) {
8442 prefix: []const u8,8456 prefix: []const u8,
8443 value: Value,8457 value: Value,
8444 function: Function.Index,8458 function: Function.Index,
8445 ) Allocator.Error!std.fmt.Formatter(format) {8459 ) Allocator.Error!std.fmt.Formatter(FormatData, format) {
8446 return .{ .data = .{8460 return .{ .data = .{
8447 .formatter = formatter,8461 .formatter = formatter,
8448 .prefix = prefix,8462 .prefix = prefix,
...@@ -8467,6 +8481,7 @@ pub const Metadata = enum(u32) {...@@ -8467,6 +8481,7 @@ pub const Metadata = enum(u32) {
8467 };8481 };
8468 },8482 },
8469 },8483 },
8484 .specialized = null,
8470 } };8485 } };
8471 }8486 }
8472 fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node {8487 fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node {
...@@ -8506,7 +8521,7 @@ pub const Metadata = enum(u32) {...@@ -8506,7 +8521,7 @@ pub const Metadata = enum(u32) {
8506 DIGlobalVariableExpression,8521 DIGlobalVariableExpression,
8507 },8522 },
8508 nodes: anytype,8523 nodes: anytype,
8509 writer: anytype,8524 w: *Writer,
8510 ) !void {8525 ) !void {
8511 comptime var fmt_str: []const u8 = "";8526 comptime var fmt_str: []const u8 = "";
8512 const names = comptime std.meta.fieldNames(@TypeOf(nodes));8527 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
...@@ -8523,10 +8538,10 @@ pub const Metadata = enum(u32) {...@@ -8523,10 +8538,10 @@ pub const Metadata = enum(u32) {
8523 }8538 }
8524 fmt_str = fmt_str ++ "(";8539 fmt_str = fmt_str ++ "(";
8525 inline for (fields[2..], names) |*field, name| {8540 inline for (fields[2..], names) |*field, name| {
8526 fmt_str = fmt_str ++ "{[" ++ name ++ "]S}";8541 fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
8527 field.* = .{8542 field.* = .{
8528 .name = name,8543 .name = name,
8529 .type = std.fmt.Formatter(format),8544 .type = std.fmt.Formatter(FormatData, format),
8530 .default_value_ptr = null,8545 .default_value_ptr = null,
8531 .is_comptime = false,8546 .is_comptime = false,
8532 .alignment = 0,8547 .alignment = 0,
...@@ -8545,8 +8560,9 @@ pub const Metadata = enum(u32) {...@@ -8545,8 +8560,9 @@ pub const Metadata = enum(u32) {
8545 inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(8560 inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(
8546 name ++ ": ",8561 name ++ ": ",
8547 @field(nodes, name),8562 @field(nodes, name),
8563 null,
8548 );8564 );
8549 try writer.print(fmt_str, fmt_args);8565 try w.print(fmt_str, fmt_args);
8550 }8566 }
8551 };8567 };
8552};8568};
...@@ -8636,7 +8652,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8636,7 +8652,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8636 inline for (.{ 0, 4 }) |addr_space_index| {8652 inline for (.{ 0, 4 }) |addr_space_index| {
8637 const addr_space: AddrSpace = @enumFromInt(addr_space_index);8653 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8638 assert(self.ptrTypeAssumeCapacity(addr_space) ==8654 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8639 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));8655 @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")})));
8640 }8656 }
8641 }8657 }
86428658
...@@ -8759,16 +8775,8 @@ pub fn deinit(self: *Builder) void {...@@ -8759,16 +8775,8 @@ pub fn deinit(self: *Builder) void {
8759 self.* = undefined;8775 self.* = undefined;
8760}8776}
87618777
8762pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {8778pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {
8763 self.module_asm.clearRetainingCapacity();8779 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')8780 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')
8773 try self.module_asm.append(self.gpa, '\n');8781 try self.module_asm.append(self.gpa, '\n');
8774}8782}
...@@ -8804,7 +8812,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo...@@ -8804,7 +8812,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo
8804}8812}
88058813
8806pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {8814pub 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;8815 self.string_bytes.printAssumeCapacity(fmt_str, fmt_args);
8808 return self.trailingStringAssumeCapacity();8816 return self.trailingStringAssumeCapacity();
8809}8817}
88108818
...@@ -9076,9 +9084,13 @@ pub fn getIntrinsic(...@@ -9076,9 +9084,13 @@ pub fn getIntrinsic(
9076 const allocator = stack.get();9084 const allocator = stack.get();
90779085
9078 const name = name: {9086 const name = name: {
9079 const writer = self.strtab_string_bytes.writer(self.gpa);9087 {
9080 try writer.print("llvm.{s}", .{@tagName(id)});9088 var aw: Writer.Allocating = .fromArrayList(self.gpa, &self.strtab_string_bytes);
9081 for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)});9089 const w = &aw.writer;
9090 defer self.strtab_string_bytes = aw.toArrayList();
9091 w.print("llvm.{s}", .{@tagName(id)}) catch return error.OutOfMemory;
9092 for (overload) |ty| w.print(".{f}", .{ty.fmt(self, .m)}) catch return error.OutOfMemory;
9093 }
9082 break :name try self.trailingStrtabString();9094 break :name try self.trailingStrtabString();
9083 };9095 };
9084 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;9096 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
...@@ -9492,139 +9504,105 @@ pub fn asmValue(...@@ -9492,139 +9504,105 @@ pub fn asmValue(
9492 return (try self.asmConst(ty, info, assembly, constraints)).toValue();9504 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
9493}9505}
94949506
9495pub fn dump(self: *Builder) void {9507pub fn dump(b: *Builder) void {
9496 self.print(std.io.getStdErr().writer()) catch {};9508 var buffer: [4000]u8 = undefined;
9509 const stderr: std.fs.File = .stderr();
9510 b.printToFile(stderr, &buffer) catch {};
9497}9511}
94989512
9499pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool {9513pub fn printToFilePath(b: *Builder, dir: std.fs.Dir, path: []const u8) !void {
9500 var file = std.fs.cwd().createFile(path, .{}) catch |err| {9514 var buffer: [4000]u8 = undefined;
9501 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });9515 const file = try dir.createFile(path, .{});
9502 return false;
9503 };
9504 defer file.close();9516 defer file.close();
9505 self.print(file.writer()) catch |err| {9517 try b.printToFile(file, &buffer);
9506 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9507 return false;
9508 };
9509 return true;
9510}9518}
95119519
9512pub fn print(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator.Error)!void {9520pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void {
9513 var bw = std.io.bufferedWriter(writer);9521 var fw = file.writer(buffer);
9514 try self.printUnbuffered(bw.writer());9522 try print(b, &fw.interface);
9515 try bw.flush();9523 try fw.interface.flush();
9516}9524}
95179525
9518fn WriterWithErrors(comptime BackingWriter: type, comptime ExtraErrors: type) type {9526pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void {
9519 return struct {
9520 backing_writer: BackingWriter,
9521
9522 pub const Error = BackingWriter.Error || ExtraErrors;
9523 pub const Writer = std.io.Writer(*const Self, Error, write);
9524
9525 const Self = @This();
9526
9527 pub fn writer(self: *const Self) Writer {
9528 return .{ .context = self };
9529 }
9530
9531 pub fn write(self: *const Self, bytes: []const u8) Error!usize {
9532 return self.backing_writer.write(bytes);
9533 }
9534 };
9535}
9536fn writerWithErrors(
9537 backing_writer: anytype,
9538 comptime ExtraErrors: type,
9539) WriterWithErrors(@TypeOf(backing_writer), ExtraErrors) {
9540 return .{ .backing_writer = backing_writer };
9541}
9542
9543pub fn printUnbuffered(
9544 self: *Builder,
9545 backing_writer: anytype,
9546) (@TypeOf(backing_writer).Error || Allocator.Error)!void {
9547 const writer_with_errors = writerWithErrors(backing_writer, Allocator.Error);
9548 const writer = writer_with_errors.writer();
9549
9550 var need_newline = false;9527 var need_newline = false;
9551 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };9528 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
9552 defer metadata_formatter.map.deinit(self.gpa);9529 defer metadata_formatter.map.deinit(self.gpa);
95539530
9554 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {9531 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
9555 if (need_newline) try writer.writeByte('\n') else need_newline = true;9532 if (need_newline) try w.writeByte('\n') else need_newline = true;
9556 if (self.source_filename != .none) try writer.print(9533 if (self.source_filename != .none) try w.print(
9557 \\; ModuleID = '{s}'9534 \\; ModuleID = '{s}'
9558 \\source_filename = {"}9535 \\source_filename = {f}
9559 \\9536 \\
9560 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });9537 , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) });
9561 if (self.data_layout != .none) try writer.print(9538 if (self.data_layout != .none) try w.print(
9562 \\target datalayout = {"}9539 \\target datalayout = {f}
9563 \\9540 \\
9564 , .{self.data_layout.fmt(self)});9541 , .{self.data_layout.fmtQ(self)});
9565 if (self.target_triple != .none) try writer.print(9542 if (self.target_triple != .none) try w.print(
9566 \\target triple = {"}9543 \\target triple = {f}
9567 \\9544 \\
9568 , .{self.target_triple.fmt(self)});9545 , .{self.target_triple.fmtQ(self)});
9569 }9546 }
95709547
9571 if (self.module_asm.items.len > 0) {9548 if (self.module_asm.items.len > 0) {
9572 if (need_newline) try writer.writeByte('\n') else need_newline = true;9549 if (need_newline) try w.writeByte('\n') else need_newline = true;
9573 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');9550 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
9574 while (line_it.next()) |line| {9551 while (line_it.next()) |line| {
9575 try writer.writeAll("module asm ");9552 try w.writeAll("module asm ");
9576 try printEscapedString(line, .always_quote, writer);9553 try printEscapedString(line, .always_quote, w);
9577 try writer.writeByte('\n');9554 try w.writeByte('\n');
9578 }9555 }
9579 }9556 }
95809557
9581 if (self.types.count() > 0) {9558 if (self.types.count() > 0) {
9582 if (need_newline) try writer.writeByte('\n') else need_newline = true;9559 if (need_newline) try w.writeByte('\n') else need_newline = true;
9583 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(9560 for (self.types.keys(), self.types.values()) |id, ty| try w.print(
9584 \\%{} = type {}9561 \\%{f} = type {f}
9585 \\9562 \\
9586 , .{ id.fmt(self), ty.fmt(self) });9563 , .{ id.fmt(self), ty.fmt(self, .default) });
9587 }9564 }
95889565
9589 if (self.variables.items.len > 0) {9566 if (self.variables.items.len > 0) {
9590 if (need_newline) try writer.writeByte('\n') else need_newline = true;9567 if (need_newline) try w.writeByte('\n') else need_newline = true;
9591 for (self.variables.items) |variable| {9568 for (self.variables.items) |variable| {
9592 if (variable.global.getReplacement(self) != .none) continue;9569 if (variable.global.getReplacement(self) != .none) continue;
9593 const global = variable.global.ptrConst(self);9570 const global = variable.global.ptrConst(self);
9594 metadata_formatter.need_comma = true;9571 metadata_formatter.need_comma = true;
9595 defer metadata_formatter.need_comma = undefined;9572 defer metadata_formatter.need_comma = undefined;
9596 try writer.print(9573 try w.print(
9597 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{}9574 \\{f} ={f}{f}{f}{f}{f}{f}{f}{f} {s} {f}{f}{f}{f}
9598 \\9575 \\
9599 , .{9576 , .{
9600 variable.global.fmt(self),9577 variable.global.fmt(self),
9601 Linkage.fmtOptional(if (global.linkage == .external and9578 Linkage.fmtOptional(
9602 variable.init != .no_init) null else global.linkage),9579 if (global.linkage == .external and variable.init != .no_init) null else global.linkage,
9580 ),
9603 global.preemption,9581 global.preemption,
9604 global.visibility,9582 global.visibility,
9605 global.dll_storage_class,9583 global.dll_storage_class,
9606 variable.thread_local,9584 variable.thread_local.fmt(" "),
9607 global.unnamed_addr,9585 global.unnamed_addr,
9608 global.addr_space,9586 global.addr_space.fmt(" "),
9609 global.externally_initialized,9587 global.externally_initialized,
9610 @tagName(variable.mutability),9588 @tagName(variable.mutability),
9611 global.type.fmt(self),9589 global.type.fmt(self, .percent),
9612 variable.init.fmt(self),9590 variable.init.fmt(self, .{ .space = true }),
9613 variable.alignment,9591 variable.alignment.fmt(", "),
9614 try metadata_formatter.fmt("!dbg ", global.dbg),9592 try metadata_formatter.fmt("!dbg ", global.dbg, null),
9615 });9593 });
9616 }9594 }
9617 }9595 }
96189596
9619 if (self.aliases.items.len > 0) {9597 if (self.aliases.items.len > 0) {
9620 if (need_newline) try writer.writeByte('\n') else need_newline = true;9598 if (need_newline) try w.writeByte('\n') else need_newline = true;
9621 for (self.aliases.items) |alias| {9599 for (self.aliases.items) |alias| {
9622 if (alias.global.getReplacement(self) != .none) continue;9600 if (alias.global.getReplacement(self) != .none) continue;
9623 const global = alias.global.ptrConst(self);9601 const global = alias.global.ptrConst(self);
9624 metadata_formatter.need_comma = true;9602 metadata_formatter.need_comma = true;
9625 defer metadata_formatter.need_comma = undefined;9603 defer metadata_formatter.need_comma = undefined;
9626 try writer.print(9604 try w.print(
9627 \\{} ={}{}{}{}{ }{} alias {%}, {%}{}9605 \\{f} ={f}{f}{f}{f}{f}{f} alias {f}, {f}{f}
9628 \\9606 \\
9629 , .{9607 , .{
9630 alias.global.fmt(self),9608 alias.global.fmt(self),
...@@ -9632,11 +9610,11 @@ pub fn printUnbuffered(...@@ -9632,11 +9610,11 @@ pub fn printUnbuffered(
9632 global.preemption,9610 global.preemption,
9633 global.visibility,9611 global.visibility,
9634 global.dll_storage_class,9612 global.dll_storage_class,
9635 alias.thread_local,9613 alias.thread_local.fmt(" "),
9636 global.unnamed_addr,9614 global.unnamed_addr,
9637 global.type.fmt(self),9615 global.type.fmt(self, .percent),
9638 alias.aliasee.fmt(self),9616 alias.aliasee.fmt(self, .{ .percent = true }),
9639 try metadata_formatter.fmt("!dbg ", global.dbg),9617 try metadata_formatter.fmt("!dbg ", global.dbg, null),
9640 });9618 });
9641 }9619 }
9642 }9620 }
...@@ -9646,17 +9624,17 @@ pub fn printUnbuffered(...@@ -9646,17 +9624,17 @@ pub fn printUnbuffered(
96469624
9647 for (0.., self.functions.items) |function_i, function| {9625 for (0.., self.functions.items) |function_i, function| {
9648 if (function.global.getReplacement(self) != .none) continue;9626 if (function.global.getReplacement(self) != .none) continue;
9649 if (need_newline) try writer.writeByte('\n') else need_newline = true;9627 if (need_newline) try w.writeByte('\n') else need_newline = true;
9650 const function_index: Function.Index = @enumFromInt(function_i);9628 const function_index: Function.Index = @enumFromInt(function_i);
9651 const global = function.global.ptrConst(self);9629 const global = function.global.ptrConst(self);
9652 const params_len = global.type.functionParameters(self).len;9630 const params_len = global.type.functionParameters(self).len;
9653 const function_attributes = function.attributes.func(self);9631 const function_attributes = function.attributes.func(self);
9654 if (function_attributes != .none) try writer.print(9632 if (function_attributes != .none) try w.print(
9655 \\; Function Attrs:{}9633 \\; Function Attrs:{f}
9656 \\9634 \\
9657 , .{function_attributes.fmt(self)});9635 , .{function_attributes.fmt(self, .{})});
9658 try writer.print(9636 try w.print(
9659 \\{s}{}{}{}{}{}{"} {%} {}(9637 \\{s}{f}{f}{f}{f}{f}{f} {f} {f}(
9660 , .{9638 , .{
9661 if (function.instructions.len > 0) "define" else "declare",9639 if (function.instructions.len > 0) "define" else "declare",
9662 global.linkage,9640 global.linkage,
...@@ -9664,45 +9642,45 @@ pub fn printUnbuffered(...@@ -9664,45 +9642,45 @@ pub fn printUnbuffered(
9664 global.visibility,9642 global.visibility,
9665 global.dll_storage_class,9643 global.dll_storage_class,
9666 function.call_conv,9644 function.call_conv,
9667 function.attributes.ret(self).fmt(self),9645 function.attributes.ret(self).fmt(self, .{}),
9668 global.type.functionReturn(self).fmt(self),9646 global.type.functionReturn(self).fmt(self, .percent),
9669 function.global.fmt(self),9647 function.global.fmt(self),
9670 });9648 });
9671 for (0..params_len) |arg| {9649 for (0..params_len) |arg| {
9672 if (arg > 0) try writer.writeAll(", ");9650 if (arg > 0) try w.writeAll(", ");
9673 try writer.print(9651 try w.print(
9674 \\{%}{"}9652 \\{f}{f}
9675 , .{9653 , .{
9676 global.type.functionParameters(self)[arg].fmt(self),9654 global.type.functionParameters(self)[arg].fmt(self, .percent),
9677 function.attributes.param(arg, self).fmt(self),9655 function.attributes.param(arg, self).fmt(self, .{}),
9678 });9656 });
9679 if (function.instructions.len > 0)9657 if (function.instructions.len > 0)
9680 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})9658 try w.print(" {f}", .{function.arg(@intCast(arg)).fmt(function_index, self, .{})})
9681 else9659 else
9682 try writer.print(" %{d}", .{arg});9660 try w.print(" %{d}", .{arg});
9683 }9661 }
9684 switch (global.type.functionKind(self)) {9662 switch (global.type.functionKind(self)) {
9685 .normal => {},9663 .normal => {},
9686 .vararg => {9664 .vararg => {
9687 if (params_len > 0) try writer.writeAll(", ");9665 if (params_len > 0) try w.writeAll(", ");
9688 try writer.writeAll("...");9666 try w.writeAll("...");
9689 },9667 },
9690 }9668 }
9691 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });9669 try w.print("){f}{f}", .{ global.unnamed_addr, global.addr_space.fmt(" ") });
9692 if (function_attributes != .none) try writer.print(" #{d}", .{9670 if (function_attributes != .none) try w.print(" #{d}", .{
9693 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,9671 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9694 });9672 });
9695 {9673 {
9696 metadata_formatter.need_comma = false;9674 metadata_formatter.need_comma = false;
9697 defer metadata_formatter.need_comma = undefined;9675 defer metadata_formatter.need_comma = undefined;
9698 try writer.print("{ }{}", .{9676 try w.print("{f}{f}", .{
9699 function.alignment,9677 function.alignment.fmt(" "),
9700 try metadata_formatter.fmt(" !dbg ", global.dbg),9678 try metadata_formatter.fmt(" !dbg ", global.dbg, null),
9701 });9679 });
9702 }9680 }
9703 if (function.instructions.len > 0) {9681 if (function.instructions.len > 0) {
9704 var block_incoming_len: u32 = undefined;9682 var block_incoming_len: u32 = undefined;
9705 try writer.writeAll(" {\n");9683 try w.writeAll(" {\n");
9706 var maybe_dbg_index: ?u32 = null;9684 var maybe_dbg_index: ?u32 = null;
9707 for (params_len..function.instructions.len) |instruction_i| {9685 for (params_len..function.instructions.len) |instruction_i| {
9708 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);9686 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
...@@ -9800,11 +9778,11 @@ pub fn printUnbuffered(...@@ -9800,11 +9778,11 @@ pub fn printUnbuffered(
9800 .xor,9778 .xor,
9801 => |tag| {9779 => |tag| {
9802 const extra = function.extraData(Function.Instruction.Binary, instruction.data);9780 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9803 try writer.print(" %{} = {s} {%}, {}", .{9781 try w.print(" %{f} = {s} {f}, {f}", .{
9804 instruction_index.name(&function).fmt(self),9782 instruction_index.name(&function).fmt(self),
9805 @tagName(tag),9783 @tagName(tag),
9806 extra.lhs.fmt(function_index, self),9784 extra.lhs.fmt(function_index, self, .{ .percent = true }),
9807 extra.rhs.fmt(function_index, self),9785 extra.rhs.fmt(function_index, self, .{ .percent = true }),
9808 });9786 });
9809 },9787 },
9810 .addrspacecast,9788 .addrspacecast,
...@@ -9822,73 +9800,76 @@ pub fn printUnbuffered(...@@ -9822,73 +9800,76 @@ pub fn printUnbuffered(
9822 .zext,9800 .zext,
9823 => |tag| {9801 => |tag| {
9824 const extra = function.extraData(Function.Instruction.Cast, instruction.data);9802 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9825 try writer.print(" %{} = {s} {%} to {%}", .{9803 try w.print(" %{f} = {s} {f} to {f}", .{
9826 instruction_index.name(&function).fmt(self),9804 instruction_index.name(&function).fmt(self),
9827 @tagName(tag),9805 @tagName(tag),
9828 extra.val.fmt(function_index, self),9806 extra.val.fmt(function_index, self, .{ .percent = true }),
9829 extra.type.fmt(self),9807 extra.type.fmt(self, .percent),
9830 });9808 });
9831 },9809 },
9832 .alloca,9810 .alloca,
9833 .@"alloca inalloca",9811 .@"alloca inalloca",
9834 => |tag| {9812 => |tag| {
9835 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);9813 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9836 try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{9814 try w.print(" %{f} = {s} {f}{f}{f}{f}", .{
9837 instruction_index.name(&function).fmt(self),9815 instruction_index.name(&function).fmt(self),
9838 @tagName(tag),9816 @tagName(tag),
9839 extra.type.fmt(self),9817 extra.type.fmt(self, .percent),
9840 Value.fmt(switch (extra.len) {9818 Value.fmt(switch (extra.len) {
9841 .@"1" => .none,9819 .@"1" => .none,
9842 else => extra.len,9820 else => extra.len,
9843 }, function_index, self),9821 }, function_index, self, .{
9844 extra.info.alignment,9822 .comma = true,
9845 extra.info.addr_space,9823 .percent = true,
9824 }),
9825 extra.info.alignment.fmt(", "),
9826 extra.info.addr_space.fmt(", "),
9846 });9827 });
9847 },9828 },
9848 .arg => unreachable,9829 .arg => unreachable,
9849 .atomicrmw => |tag| {9830 .atomicrmw => |tag| {
9850 const extra =9831 const extra =
9851 function.extraData(Function.Instruction.AtomicRmw, instruction.data);9832 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9852 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{9833 try w.print(" %{f} = {t}{f} {t} {f}, {f}{f}{f}{f}", .{
9853 instruction_index.name(&function).fmt(self),9834 instruction_index.name(&function).fmt(self),
9854 @tagName(tag),9835 tag,
9855 extra.info.access_kind,9836 extra.info.access_kind.fmt(" "),
9856 @tagName(extra.info.atomic_rmw_operation),9837 extra.info.atomic_rmw_operation,
9857 extra.ptr.fmt(function_index, self),9838 extra.ptr.fmt(function_index, self, .{ .percent = true }),
9858 extra.val.fmt(function_index, self),9839 extra.val.fmt(function_index, self, .{ .percent = true }),
9859 extra.info.sync_scope,9840 extra.info.sync_scope.fmt(" "),
9860 extra.info.success_ordering,9841 extra.info.success_ordering.fmt(" "),
9861 extra.info.alignment,9842 extra.info.alignment.fmt(", "),
9862 });9843 });
9863 },9844 },
9864 .block => {9845 .block => {
9865 block_incoming_len = instruction.data;9846 block_incoming_len = instruction.data;
9866 const name = instruction_index.name(&function);9847 const name = instruction_index.name(&function);
9867 if (@intFromEnum(instruction_index) > params_len)9848 if (@intFromEnum(instruction_index) > params_len)
9868 try writer.writeByte('\n');9849 try w.writeByte('\n');
9869 try writer.print("{}:\n", .{name.fmt(self)});9850 try w.print("{f}:\n", .{name.fmt(self)});
9870 continue;9851 continue;
9871 },9852 },
9872 .br => |tag| {9853 .br => |tag| {
9873 const target: Function.Block.Index = @enumFromInt(instruction.data);9854 const target: Function.Block.Index = @enumFromInt(instruction.data);
9874 try writer.print(" {s} {%}", .{9855 try w.print(" {s} {f}", .{
9875 @tagName(tag), target.toInst(&function).fmt(function_index, self),9856 @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }),
9876 });9857 });
9877 },9858 },
9878 .br_cond => {9859 .br_cond => {
9879 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);9860 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9880 try writer.print(" br {%}, {%}, {%}", .{9861 try w.print(" br {f}, {f}, {f}", .{
9881 extra.cond.fmt(function_index, self),9862 extra.cond.fmt(function_index, self, .{ .percent = true }),
9882 extra.then.toInst(&function).fmt(function_index, self),9863 extra.then.toInst(&function).fmt(function_index, self, .{ .percent = true }),
9883 extra.@"else".toInst(&function).fmt(function_index, self),9864 extra.@"else".toInst(&function).fmt(function_index, self, .{ .percent = true }),
9884 });9865 });
9885 metadata_formatter.need_comma = true;9866 metadata_formatter.need_comma = true;
9886 defer metadata_formatter.need_comma = undefined;9867 defer metadata_formatter.need_comma = undefined;
9887 switch (extra.weights) {9868 switch (extra.weights) {
9888 .none => {},9869 .none => {},
9889 .unpredictable => try writer.writeAll("!unpredictable !{}"),9870 .unpredictable => try w.writeAll("!unpredictable !{}"),
9890 _ => try writer.print("{}", .{9871 _ => try w.print("{f}", .{
9891 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),9872 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights))), null),
9892 }),9873 }),
9893 }9874 }
9894 },9875 },
...@@ -9904,42 +9885,42 @@ pub fn printUnbuffered(...@@ -9904,42 +9885,42 @@ pub fn printUnbuffered(
9904 var extra =9885 var extra =
9905 function.extraDataTrail(Function.Instruction.Call, instruction.data);9886 function.extraDataTrail(Function.Instruction.Call, instruction.data);
9906 const args = extra.trail.next(extra.data.args_len, Value, &function);9887 const args = extra.trail.next(extra.data.args_len, Value, &function);
9907 try writer.writeAll(" ");9888 try w.writeAll(" ");
9908 const ret_ty = extra.data.ty.functionReturn(self);9889 const ret_ty = extra.data.ty.functionReturn(self);
9909 switch (ret_ty) {9890 switch (ret_ty) {
9910 .void => {},9891 .void => {},
9911 else => try writer.print("%{} = ", .{9892 else => try w.print("%{f} = ", .{
9912 instruction_index.name(&function).fmt(self),9893 instruction_index.name(&function).fmt(self),
9913 }),9894 }),
9914 .none => unreachable,9895 .none => unreachable,
9915 }9896 }
9916 try writer.print("{s}{}{}{} {%} {}(", .{9897 try w.print("{t}{f}{f}{f} {f} {f}(", .{
9917 @tagName(tag),9898 tag,
9918 extra.data.info.call_conv,9899 extra.data.info.call_conv,
9919 extra.data.attributes.ret(self).fmt(self),9900 extra.data.attributes.ret(self).fmt(self, .{}),
9920 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),9901 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
9921 switch (extra.data.ty.functionKind(self)) {9902 switch (extra.data.ty.functionKind(self)) {
9922 .normal => ret_ty,9903 .normal => ret_ty,
9923 .vararg => extra.data.ty,9904 .vararg => extra.data.ty,
9924 }.fmt(self),9905 }.fmt(self, .percent),
9925 extra.data.callee.fmt(function_index, self),9906 extra.data.callee.fmt(function_index, self, .{}),
9926 });9907 });
9927 for (0.., args) |arg_index, arg| {9908 for (0.., args) |arg_index, arg| {
9928 if (arg_index > 0) try writer.writeAll(", ");9909 if (arg_index > 0) try w.writeAll(", ");
9929 metadata_formatter.need_comma = false;9910 metadata_formatter.need_comma = false;
9930 defer metadata_formatter.need_comma = undefined;9911 defer metadata_formatter.need_comma = undefined;
9931 try writer.print("{%}{}{}", .{9912 try w.print("{f}{f}{f}", .{
9932 arg.typeOf(function_index, self).fmt(self),9913 arg.typeOf(function_index, self).fmt(self, .percent),
9933 extra.data.attributes.param(arg_index, self).fmt(self),9914 extra.data.attributes.param(arg_index, self).fmt(self, .{}),
9934 try metadata_formatter.fmtLocal(" ", arg, function_index),9915 try metadata_formatter.fmtLocal(" ", arg, function_index),
9935 });9916 });
9936 }9917 }
9937 try writer.writeByte(')');9918 try w.writeByte(')');
9938 if (extra.data.info.has_op_bundle_cold) {9919 if (extra.data.info.has_op_bundle_cold) {
9939 try writer.writeAll(" [ \"cold\"() ]");9920 try w.writeAll(" [ \"cold\"() ]");
9940 }9921 }
9941 const call_function_attributes = extra.data.attributes.func(self);9922 const call_function_attributes = extra.data.attributes.func(self);
9942 if (call_function_attributes != .none) try writer.print(" #{d}", .{9923 if (call_function_attributes != .none) try w.print(" #{d}", .{
9943 (try attribute_groups.getOrPutValue(9924 (try attribute_groups.getOrPutValue(
9944 self.gpa,9925 self.gpa,
9945 call_function_attributes,9926 call_function_attributes,
...@@ -9952,27 +9933,27 @@ pub fn printUnbuffered(...@@ -9952,27 +9933,27 @@ pub fn printUnbuffered(
9952 => |tag| {9933 => |tag| {
9953 const extra =9934 const extra =
9954 function.extraData(Function.Instruction.CmpXchg, instruction.data);9935 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9955 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{9936 try w.print(" %{f} = {t}{f} {f}, {f}, {f}{f}{f}{f}{f}", .{
9956 instruction_index.name(&function).fmt(self),9937 instruction_index.name(&function).fmt(self),
9957 @tagName(tag),9938 tag,
9958 extra.info.access_kind,9939 extra.info.access_kind.fmt(" "),
9959 extra.ptr.fmt(function_index, self),9940 extra.ptr.fmt(function_index, self, .{ .percent = true }),
9960 extra.cmp.fmt(function_index, self),9941 extra.cmp.fmt(function_index, self, .{ .percent = true }),
9961 extra.new.fmt(function_index, self),9942 extra.new.fmt(function_index, self, .{ .percent = true }),
9962 extra.info.sync_scope,9943 extra.info.sync_scope.fmt(" "),
9963 extra.info.success_ordering,9944 extra.info.success_ordering.fmt(" "),
9964 extra.info.failure_ordering,9945 extra.info.failure_ordering.fmt(" "),
9965 extra.info.alignment,9946 extra.info.alignment.fmt(", "),
9966 });9947 });
9967 },9948 },
9968 .extractelement => |tag| {9949 .extractelement => |tag| {
9969 const extra =9950 const extra =
9970 function.extraData(Function.Instruction.ExtractElement, instruction.data);9951 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9971 try writer.print(" %{} = {s} {%}, {%}", .{9952 try w.print(" %{f} = {s} {f}, {f}", .{
9972 instruction_index.name(&function).fmt(self),9953 instruction_index.name(&function).fmt(self),
9973 @tagName(tag),9954 @tagName(tag),
9974 extra.val.fmt(function_index, self),9955 extra.val.fmt(function_index, self, .{ .percent = true }),
9975 extra.index.fmt(function_index, self),9956 extra.index.fmt(function_index, self, .{ .percent = true }),
9976 });9957 });
9977 },9958 },
9978 .extractvalue => |tag| {9959 .extractvalue => |tag| {
...@@ -9981,29 +9962,29 @@ pub fn printUnbuffered(...@@ -9981,29 +9962,29 @@ pub fn printUnbuffered(
9981 instruction.data,9962 instruction.data,
9982 );9963 );
9983 const indices = extra.trail.next(extra.data.indices_len, u32, &function);9964 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9984 try writer.print(" %{} = {s} {%}", .{9965 try w.print(" %{f} = {s} {f}", .{
9985 instruction_index.name(&function).fmt(self),9966 instruction_index.name(&function).fmt(self),
9986 @tagName(tag),9967 @tagName(tag),
9987 extra.data.val.fmt(function_index, self),9968 extra.data.val.fmt(function_index, self, .{ .percent = true }),
9988 });9969 });
9989 for (indices) |index| try writer.print(", {d}", .{index});9970 for (indices) |index| try w.print(", {d}", .{index});
9990 },9971 },
9991 .fence => |tag| {9972 .fence => |tag| {
9992 const info: MemoryAccessInfo = @bitCast(instruction.data);9973 const info: MemoryAccessInfo = @bitCast(instruction.data);
9993 try writer.print(" {s}{ }{ }", .{9974 try w.print(" {t}{f}{f}", .{
9994 @tagName(tag),9975 tag,
9995 info.sync_scope,9976 info.sync_scope.fmt(" "),
9996 info.success_ordering,9977 info.success_ordering.fmt(" "),
9997 });9978 });
9998 },9979 },
9999 .fneg,9980 .fneg,
10000 .@"fneg fast",9981 .@"fneg fast",
10001 => |tag| {9982 => |tag| {
10002 const val: Value = @enumFromInt(instruction.data);9983 const val: Value = @enumFromInt(instruction.data);
10003 try writer.print(" %{} = {s} {%}", .{9984 try w.print(" %{f} = {s} {f}", .{
10004 instruction_index.name(&function).fmt(self),9985 instruction_index.name(&function).fmt(self),
10005 @tagName(tag),9986 @tagName(tag),
10006 val.fmt(function_index, self),9987 val.fmt(function_index, self, .{ .percent = true }),
10007 });9988 });
10008 },9989 },
10009 .getelementptr,9990 .getelementptr,
...@@ -10014,14 +9995,14 @@ pub fn printUnbuffered(...@@ -10014,14 +9995,14 @@ pub fn printUnbuffered(
10014 instruction.data,9995 instruction.data,
10015 );9996 );
10016 const indices = extra.trail.next(extra.data.indices_len, Value, &function);9997 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
10017 try writer.print(" %{} = {s} {%}, {%}", .{9998 try w.print(" %{f} = {s} {f}, {f}", .{
10018 instruction_index.name(&function).fmt(self),9999 instruction_index.name(&function).fmt(self),
10019 @tagName(tag),10000 @tagName(tag),
10020 extra.data.type.fmt(self),10001 extra.data.type.fmt(self, .percent),
10021 extra.data.base.fmt(function_index, self),10002 extra.data.base.fmt(function_index, self, .{ .percent = true }),
10022 });10003 });
10023 for (indices) |index| try writer.print(", {%}", .{10004 for (indices) |index| try w.print(", {f}", .{
10024 index.fmt(function_index, self),10005 index.fmt(function_index, self, .{ .percent = true }),
10025 });10006 });
10026 },10007 },
10027 .indirectbr => |tag| {10008 .indirectbr => |tag| {
...@@ -10029,54 +10010,54 @@ pub fn printUnbuffered(...@@ -10029,54 +10010,54 @@ pub fn printUnbuffered(
10029 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);10010 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);
10030 const targets =10011 const targets =
10031 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);10012 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);
10032 try writer.print(" {s} {%}, [", .{10013 try w.print(" {s} {f}, [", .{
10033 @tagName(tag),10014 @tagName(tag),
10034 extra.data.addr.fmt(function_index, self),10015 extra.data.addr.fmt(function_index, self, .{ .percent = true }),
10035 });10016 });
10036 for (0.., targets) |target_index, target| {10017 for (0.., targets) |target_index, target| {
10037 if (target_index > 0) try writer.writeAll(", ");10018 if (target_index > 0) try w.writeAll(", ");
10038 try writer.print("{%}", .{10019 try w.print("{f}", .{
10039 target.toInst(&function).fmt(function_index, self),10020 target.toInst(&function).fmt(function_index, self, .{ .percent = true }),
10040 });10021 });
10041 }10022 }
10042 try writer.writeByte(']');10023 try w.writeByte(']');
10043 },10024 },
10044 .insertelement => |tag| {10025 .insertelement => |tag| {
10045 const extra =10026 const extra =
10046 function.extraData(Function.Instruction.InsertElement, instruction.data);10027 function.extraData(Function.Instruction.InsertElement, instruction.data);
10047 try writer.print(" %{} = {s} {%}, {%}, {%}", .{10028 try w.print(" %{f} = {s} {f}, {f}, {f}", .{
10048 instruction_index.name(&function).fmt(self),10029 instruction_index.name(&function).fmt(self),
10049 @tagName(tag),10030 @tagName(tag),
10050 extra.val.fmt(function_index, self),10031 extra.val.fmt(function_index, self, .{ .percent = true }),
10051 extra.elem.fmt(function_index, self),10032 extra.elem.fmt(function_index, self, .{ .percent = true }),
10052 extra.index.fmt(function_index, self),10033 extra.index.fmt(function_index, self, .{ .percent = true }),
10053 });10034 });
10054 },10035 },
10055 .insertvalue => |tag| {10036 .insertvalue => |tag| {
10056 var extra =10037 var extra =
10057 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);10038 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
10058 const indices = extra.trail.next(extra.data.indices_len, u32, &function);10039 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
10059 try writer.print(" %{} = {s} {%}, {%}", .{10040 try w.print(" %{f} = {s} {f}, {f}", .{
10060 instruction_index.name(&function).fmt(self),10041 instruction_index.name(&function).fmt(self),
10061 @tagName(tag),10042 @tagName(tag),
10062 extra.data.val.fmt(function_index, self),10043 extra.data.val.fmt(function_index, self, .{ .percent = true }),
10063 extra.data.elem.fmt(function_index, self),10044 extra.data.elem.fmt(function_index, self, .{ .percent = true }),
10064 });10045 });
10065 for (indices) |index| try writer.print(", {d}", .{index});10046 for (indices) |index| try w.print(", {d}", .{index});
10066 },10047 },
10067 .load,10048 .load,
10068 .@"load atomic",10049 .@"load atomic",
10069 => |tag| {10050 => |tag| {
10070 const extra = function.extraData(Function.Instruction.Load, instruction.data);10051 const extra = function.extraData(Function.Instruction.Load, instruction.data);
10071 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{10052 try w.print(" %{f} = {t}{f} {f}, {f}{f}{f}{f}", .{
10072 instruction_index.name(&function).fmt(self),10053 instruction_index.name(&function).fmt(self),
10073 @tagName(tag),10054 tag,
10074 extra.info.access_kind,10055 extra.info.access_kind.fmt(" "),
10075 extra.type.fmt(self),10056 extra.type.fmt(self, .percent),
10076 extra.ptr.fmt(function_index, self),10057 extra.ptr.fmt(function_index, self, .{ .percent = true }),
10077 extra.info.sync_scope,10058 extra.info.sync_scope.fmt(" "),
10078 extra.info.success_ordering,10059 extra.info.success_ordering.fmt(" "),
10079 extra.info.alignment,10060 extra.info.alignment.fmt(", "),
10080 });10061 });
10081 },10062 },
10082 .phi,10063 .phi,
...@@ -10086,64 +10067,64 @@ pub fn printUnbuffered(...@@ -10086,64 +10067,64 @@ pub fn printUnbuffered(
10086 const vals = extra.trail.next(block_incoming_len, Value, &function);10067 const vals = extra.trail.next(block_incoming_len, Value, &function);
10087 const blocks =10068 const blocks =
10088 extra.trail.next(block_incoming_len, Function.Block.Index, &function);10069 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
10089 try writer.print(" %{} = {s} {%} ", .{10070 try w.print(" %{f} = {s} {f} ", .{
10090 instruction_index.name(&function).fmt(self),10071 instruction_index.name(&function).fmt(self),
10091 @tagName(tag),10072 @tagName(tag),
10092 vals[0].typeOf(function_index, self).fmt(self),10073 vals[0].typeOf(function_index, self).fmt(self, .percent),
10093 });10074 });
10094 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {10075 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
10095 if (incoming_index > 0) try writer.writeAll(", ");10076 if (incoming_index > 0) try w.writeAll(", ");
10096 try writer.print("[ {}, {} ]", .{10077 try w.print("[ {f}, {f} ]", .{
10097 incoming_val.fmt(function_index, self),10078 incoming_val.fmt(function_index, self, .{}),
10098 incoming_block.toInst(&function).fmt(function_index, self),10079 incoming_block.toInst(&function).fmt(function_index, self, .{}),
10099 });10080 });
10100 }10081 }
10101 },10082 },
10102 .ret => |tag| {10083 .ret => |tag| {
10103 const val: Value = @enumFromInt(instruction.data);10084 const val: Value = @enumFromInt(instruction.data);
10104 try writer.print(" {s} {%}", .{10085 try w.print(" {s} {f}", .{
10105 @tagName(tag),10086 @tagName(tag),
10106 val.fmt(function_index, self),10087 val.fmt(function_index, self, .{ .percent = true }),
10107 });10088 });
10108 },10089 },
10109 .@"ret void",10090 .@"ret void",
10110 .@"unreachable",10091 .@"unreachable",
10111 => |tag| try writer.print(" {s}", .{@tagName(tag)}),10092 => |tag| try w.print(" {s}", .{@tagName(tag)}),
10112 .select,10093 .select,
10113 .@"select fast",10094 .@"select fast",
10114 => |tag| {10095 => |tag| {
10115 const extra = function.extraData(Function.Instruction.Select, instruction.data);10096 const extra = function.extraData(Function.Instruction.Select, instruction.data);
10116 try writer.print(" %{} = {s} {%}, {%}, {%}", .{10097 try w.print(" %{f} = {s} {f}, {f}, {f}", .{
10117 instruction_index.name(&function).fmt(self),10098 instruction_index.name(&function).fmt(self),
10118 @tagName(tag),10099 @tagName(tag),
10119 extra.cond.fmt(function_index, self),10100 extra.cond.fmt(function_index, self, .{ .percent = true }),
10120 extra.lhs.fmt(function_index, self),10101 extra.lhs.fmt(function_index, self, .{ .percent = true }),
10121 extra.rhs.fmt(function_index, self),10102 extra.rhs.fmt(function_index, self, .{ .percent = true }),
10122 });10103 });
10123 },10104 },
10124 .shufflevector => |tag| {10105 .shufflevector => |tag| {
10125 const extra =10106 const extra =
10126 function.extraData(Function.Instruction.ShuffleVector, instruction.data);10107 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
10127 try writer.print(" %{} = {s} {%}, {%}, {%}", .{10108 try w.print(" %{f} = {s} {f}, {f}, {f}", .{
10128 instruction_index.name(&function).fmt(self),10109 instruction_index.name(&function).fmt(self),
10129 @tagName(tag),10110 @tagName(tag),
10130 extra.lhs.fmt(function_index, self),10111 extra.lhs.fmt(function_index, self, .{ .percent = true }),
10131 extra.rhs.fmt(function_index, self),10112 extra.rhs.fmt(function_index, self, .{ .percent = true }),
10132 extra.mask.fmt(function_index, self),10113 extra.mask.fmt(function_index, self, .{ .percent = true }),
10133 });10114 });
10134 },10115 },
10135 .store,10116 .store,
10136 .@"store atomic",10117 .@"store atomic",
10137 => |tag| {10118 => |tag| {
10138 const extra = function.extraData(Function.Instruction.Store, instruction.data);10119 const extra = function.extraData(Function.Instruction.Store, instruction.data);
10139 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{10120 try w.print(" {t}{f} {f}, {f}{f}{f}{f}", .{
10140 @tagName(tag),10121 tag,
10141 extra.info.access_kind,10122 extra.info.access_kind.fmt(" "),
10142 extra.val.fmt(function_index, self),10123 extra.val.fmt(function_index, self, .{ .percent = true }),
10143 extra.ptr.fmt(function_index, self),10124 extra.ptr.fmt(function_index, self, .{ .percent = true }),
10144 extra.info.sync_scope,10125 extra.info.sync_scope.fmt(" "),
10145 extra.info.success_ordering,10126 extra.info.success_ordering.fmt(" "),
10146 extra.info.alignment,10127 extra.info.alignment.fmt(", "),
10147 });10128 });
10148 },10129 },
10149 .@"switch" => |tag| {10130 .@"switch" => |tag| {
...@@ -10152,80 +10133,80 @@ pub fn printUnbuffered(...@@ -10152,80 +10133,80 @@ pub fn printUnbuffered(
10152 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);10133 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
10153 const blocks =10134 const blocks =
10154 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);10135 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
10155 try writer.print(" {s} {%}, {%} [\n", .{10136 try w.print(" {s} {f}, {f} [\n", .{
10156 @tagName(tag),10137 @tagName(tag),
10157 extra.data.val.fmt(function_index, self),10138 extra.data.val.fmt(function_index, self, .{ .percent = true }),
10158 extra.data.default.toInst(&function).fmt(function_index, self),10139 extra.data.default.toInst(&function).fmt(function_index, self, .{ .percent = true }),
10159 });10140 });
10160 for (vals, blocks) |case_val, case_block| try writer.print(10141 for (vals, blocks) |case_val, case_block| try w.print(
10161 " {%}, {%}\n",10142 " {f}, {f}\n",
10162 .{10143 .{
10163 case_val.fmt(self),10144 case_val.fmt(self, .{ .percent = true }),
10164 case_block.toInst(&function).fmt(function_index, self),10145 case_block.toInst(&function).fmt(function_index, self, .{ .percent = true }),
10165 },10146 },
10166 );10147 );
10167 try writer.writeAll(" ]");10148 try w.writeAll(" ]");
10168 metadata_formatter.need_comma = true;10149 metadata_formatter.need_comma = true;
10169 defer metadata_formatter.need_comma = undefined;10150 defer metadata_formatter.need_comma = undefined;
10170 switch (extra.data.weights) {10151 switch (extra.data.weights) {
10171 .none => {},10152 .none => {},
10172 .unpredictable => try writer.writeAll("!unpredictable !{}"),10153 .unpredictable => try w.writeAll("!unpredictable !{}"),
10173 _ => try writer.print("{}", .{10154 _ => try w.print("{f}", .{
10174 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),10155 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights))), null),
10175 }),10156 }),
10176 }10157 }
10177 },10158 },
10178 .va_arg => |tag| {10159 .va_arg => |tag| {
10179 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);10160 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
10180 try writer.print(" %{} = {s} {%}, {%}", .{10161 try w.print(" %{f} = {s} {f}, {f}", .{
10181 instruction_index.name(&function).fmt(self),10162 instruction_index.name(&function).fmt(self),
10182 @tagName(tag),10163 @tagName(tag),
10183 extra.list.fmt(function_index, self),10164 extra.list.fmt(function_index, self, .{ .percent = true }),
10184 extra.type.fmt(self),10165 extra.type.fmt(self, .percent),
10185 });10166 });
10186 },10167 },
10187 }10168 }
1018810169
10189 if (maybe_dbg_index) |dbg_index| {10170 if (maybe_dbg_index) |dbg_index| {
10190 try writer.print(", !dbg !{}", .{dbg_index});10171 try w.print(", !dbg !{d}", .{dbg_index});
10191 }10172 }
10192 try writer.writeByte('\n');10173 try w.writeByte('\n');
10193 }10174 }
10194 try writer.writeByte('}');10175 try w.writeByte('}');
10195 }10176 }
10196 try writer.writeByte('\n');10177 try w.writeByte('\n');
10197 }10178 }
1019810179
10199 if (attribute_groups.count() > 0) {10180 if (attribute_groups.count() > 0) {
10200 if (need_newline) try writer.writeByte('\n') else need_newline = true;10181 if (need_newline) try w.writeByte('\n') else need_newline = true;
10201 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|10182 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
10202 try writer.print(10183 try w.print(
10203 \\attributes #{d} = {{{#"} }}10184 \\attributes #{d} = {{{f} }}
10204 \\10185 \\
10205 , .{ attribute_group_index, attribute_group.fmt(self) });10186 , .{ attribute_group_index, attribute_group.fmt(self, .{ .pound = true, .quote = true }) });
10206 }10187 }
1020710188
10208 if (self.metadata_named.count() > 0) {10189 if (self.metadata_named.count() > 0) {
10209 if (need_newline) try writer.writeByte('\n') else need_newline = true;10190 if (need_newline) try w.writeByte('\n') else need_newline = true;
10210 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {10191 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {
10211 const elements: []const Metadata =10192 const elements: []const Metadata =
10212 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);10193 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);
10213 try writer.writeByte('!');10194 try w.writeByte('!');
10214 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer);10195 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, w);
10215 try writer.writeAll(" = !{");10196 try w.writeAll(" = !{");
10216 metadata_formatter.need_comma = false;10197 metadata_formatter.need_comma = false;
10217 defer metadata_formatter.need_comma = undefined;10198 defer metadata_formatter.need_comma = undefined;
10218 for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)});10199 for (elements) |element| try w.print("{f}", .{try metadata_formatter.fmt("", element, null)});
10219 try writer.writeAll("}\n");10200 try w.writeAll("}\n");
10220 }10201 }
10221 }10202 }
1022210203
10223 if (metadata_formatter.map.count() > 0) {10204 if (metadata_formatter.map.count() > 0) {
10224 if (need_newline) try writer.writeByte('\n') else need_newline = true;10205 if (need_newline) try w.writeByte('\n') else need_newline = true;
10225 var metadata_index: usize = 0;10206 var metadata_index: usize = 0;
10226 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {10207 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
10227 @setEvalBranchQuota(10_000);10208 @setEvalBranchQuota(10_000);
10228 try writer.print("!{} = ", .{metadata_index});10209 try w.print("!{d} = ", .{metadata_index});
10229 metadata_formatter.need_comma = false;10210 metadata_formatter.need_comma = false;
10230 defer metadata_formatter.need_comma = undefined;10211 defer metadata_formatter.need_comma = undefined;
1023110212
...@@ -10238,7 +10219,7 @@ pub fn printUnbuffered(...@@ -10238,7 +10219,7 @@ pub fn printUnbuffered(
10238 .scope = location.scope,10219 .scope = location.scope,
10239 .inlinedAt = location.inlined_at,10220 .inlinedAt = location.inlined_at,
10240 .isImplicitCode = false,10221 .isImplicitCode = false,
10241 }, writer);10222 }, w);
10242 continue;10223 continue;
10243 },10224 },
10244 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),10225 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),
...@@ -10254,7 +10235,7 @@ pub fn printUnbuffered(...@@ -10254,7 +10235,7 @@ pub fn printUnbuffered(
10254 .checksumkind = null,10235 .checksumkind = null,
10255 .checksum = null,10236 .checksum = null,
10256 .source = null,10237 .source = null,
10257 }, writer);10238 }, w);
10258 },10239 },
10259 .compile_unit,10240 .compile_unit,
10260 .@"compile_unit optimized",10241 .@"compile_unit optimized",
...@@ -10285,7 +10266,7 @@ pub fn printUnbuffered(...@@ -10285,7 +10266,7 @@ pub fn printUnbuffered(
10285 .rangesBaseAddress = null,10266 .rangesBaseAddress = null,
10286 .sysroot = null,10267 .sysroot = null,
10287 .sdk = null,10268 .sdk = null,
10288 }, writer);10269 }, w);
10289 },10270 },
10290 .subprogram,10271 .subprogram,
10291 .@"subprogram local",10272 .@"subprogram local",
...@@ -10319,7 +10300,7 @@ pub fn printUnbuffered(...@@ -10319,7 +10300,7 @@ pub fn printUnbuffered(
10319 .thrownTypes = null,10300 .thrownTypes = null,
10320 .annotations = null,10301 .annotations = null,
10321 .targetFuncName = null,10302 .targetFuncName = null,
10322 }, writer);10303 }, w);
10323 },10304 },
10324 .lexical_block => {10305 .lexical_block => {
10325 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);10306 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);
...@@ -10328,7 +10309,7 @@ pub fn printUnbuffered(...@@ -10328,7 +10309,7 @@ pub fn printUnbuffered(
10328 .file = extra.file,10309 .file = extra.file,
10329 .line = extra.line,10310 .line = extra.line,
10330 .column = extra.column,10311 .column = extra.column,
10331 }, writer);10312 }, w);
10332 },10313 },
10333 .location => {10314 .location => {
10334 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);10315 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);
...@@ -10338,7 +10319,7 @@ pub fn printUnbuffered(...@@ -10338,7 +10319,7 @@ pub fn printUnbuffered(
10338 .scope = extra.scope,10319 .scope = extra.scope,
10339 .inlinedAt = extra.inlined_at,10320 .inlinedAt = extra.inlined_at,
10340 .isImplicitCode = false,10321 .isImplicitCode = false,
10341 }, writer);10322 }, w);
10342 },10323 },
10343 .basic_bool_type,10324 .basic_bool_type,
10344 .basic_unsigned_type,10325 .basic_unsigned_type,
...@@ -10367,7 +10348,7 @@ pub fn printUnbuffered(...@@ -10367,7 +10348,7 @@ pub fn printUnbuffered(
10367 else => unreachable,10348 else => unreachable,
10368 }),10349 }),
10369 .flags = null,10350 .flags = null,
10370 }, writer);10351 }, w);
10371 },10352 },
10372 .composite_struct_type,10353 .composite_struct_type,
10373 .composite_union_type,10354 .composite_union_type,
...@@ -10412,7 +10393,7 @@ pub fn printUnbuffered(...@@ -10412,7 +10393,7 @@ pub fn printUnbuffered(
10412 .allocated = null,10393 .allocated = null,
10413 .rank = null,10394 .rank = null,
10414 .annotations = null,10395 .annotations = null,
10415 }, writer);10396 }, w);
10416 },10397 },
10417 .derived_pointer_type,10398 .derived_pointer_type,
10418 .derived_member_type,10399 .derived_member_type,
...@@ -10445,7 +10426,7 @@ pub fn printUnbuffered(...@@ -10445,7 +10426,7 @@ pub fn printUnbuffered(
10445 .extraData = null,10426 .extraData = null,
10446 .dwarfAddressSpace = null,10427 .dwarfAddressSpace = null,
10447 .annotations = null,10428 .annotations = null,
10448 }, writer);10429 }, w);
10449 },10430 },
10450 .subroutine_type => {10431 .subroutine_type => {
10451 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);10432 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
...@@ -10453,7 +10434,7 @@ pub fn printUnbuffered(...@@ -10453,7 +10434,7 @@ pub fn printUnbuffered(
10453 .flags = null,10434 .flags = null,
10454 .cc = null,10435 .cc = null,
10455 .types = extra.types_tuple,10436 .types = extra.types_tuple,
10456 }, writer);10437 }, w);
10457 },10438 },
10458 .enumerator_unsigned,10439 .enumerator_unsigned,
10459 .enumerator_signed_positive,10440 .enumerator_signed_positive,
...@@ -10503,7 +10484,7 @@ pub fn printUnbuffered(...@@ -10503,7 +10484,7 @@ pub fn printUnbuffered(
10503 => false,10484 => false,
10504 else => unreachable,10485 else => unreachable,
10505 },10486 },
10506 }, writer);10487 }, w);
10507 },10488 },
10508 .subrange => {10489 .subrange => {
10509 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);10490 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);
...@@ -10512,34 +10493,34 @@ pub fn printUnbuffered(...@@ -10512,34 +10493,34 @@ pub fn printUnbuffered(
10512 .lowerBound = extra.lower_bound,10493 .lowerBound = extra.lower_bound,
10513 .upperBound = null,10494 .upperBound = null,
10514 .stride = null,10495 .stride = null,
10515 }, writer);10496 }, w);
10516 },10497 },
10517 .tuple => {10498 .tuple => {
10518 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);10499 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);
10519 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);10500 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10520 try writer.writeAll("!{");10501 try w.writeAll("!{");
10521 for (elements) |element| try writer.print("{[element]%}", .{10502 for (elements) |element| try w.print("{[element]f}", .{
10522 .element = try metadata_formatter.fmt("", element),10503 .element = try metadata_formatter.fmt("", element, .{ .percent = true }),
10523 });10504 });
10524 try writer.writeAll("}\n");10505 try w.writeAll("}\n");
10525 },10506 },
10526 .str_tuple => {10507 .str_tuple => {
10527 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);10508 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);
10528 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);10509 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10529 try writer.print("!{{{[str]%}", .{10510 try w.print("!{{{[str]f}", .{
10530 .str = try metadata_formatter.fmt("", extra.data.str),10511 .str = try metadata_formatter.fmt("", extra.data.str, .{ .percent = true }),
10531 });10512 });
10532 for (elements) |element| try writer.print("{[element]%}", .{10513 for (elements) |element| try w.print("{[element]f}", .{
10533 .element = try metadata_formatter.fmt("", element),10514 .element = try metadata_formatter.fmt("", element, .{ .percent = true }),
10534 });10515 });
10535 try writer.writeAll("}\n");10516 try w.writeAll("}\n");
10536 },10517 },
10537 .module_flag => {10518 .module_flag => {
10538 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);10519 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);
10539 try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{10520 try w.print("!{{{[behavior]f}{[name]f}{[constant]f}}}\n", .{
10540 .behavior = try metadata_formatter.fmt("", extra.behavior),10521 .behavior = try metadata_formatter.fmt("", extra.behavior, .{ .percent = true }),
10541 .name = try metadata_formatter.fmt("", extra.name),10522 .name = try metadata_formatter.fmt("", extra.name, .{ .percent = true }),
10542 .constant = try metadata_formatter.fmt("", extra.constant),10523 .constant = try metadata_formatter.fmt("", extra.constant, .{ .percent = true }),
10543 });10524 });
10544 },10525 },
10545 .local_var => {10526 .local_var => {
...@@ -10554,7 +10535,7 @@ pub fn printUnbuffered(...@@ -10554,7 +10535,7 @@ pub fn printUnbuffered(
10554 .flags = null,10535 .flags = null,
10555 .@"align" = null,10536 .@"align" = null,
10556 .annotations = null,10537 .annotations = null,
10557 }, writer);10538 }, w);
10558 },10539 },
10559 .parameter => {10540 .parameter => {
10560 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);10541 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);
...@@ -10568,7 +10549,7 @@ pub fn printUnbuffered(...@@ -10568,7 +10549,7 @@ pub fn printUnbuffered(
10568 .flags = null,10549 .flags = null,
10569 .@"align" = null,10550 .@"align" = null,
10570 .annotations = null,10551 .annotations = null,
10571 }, writer);10552 }, w);
10572 },10553 },
10573 .global_var,10554 .global_var,
10574 .@"global_var local",10555 .@"global_var local",
...@@ -10591,7 +10572,7 @@ pub fn printUnbuffered(...@@ -10591,7 +10572,7 @@ pub fn printUnbuffered(
10591 .templateParams = null,10572 .templateParams = null,
10592 .@"align" = null,10573 .@"align" = null,
10593 .annotations = null,10574 .annotations = null,
10594 }, writer);10575 }, w);
10595 },10576 },
10596 .global_var_expression => {10577 .global_var_expression => {
10597 const extra =10578 const extra =
...@@ -10599,7 +10580,7 @@ pub fn printUnbuffered(...@@ -10599,7 +10580,7 @@ pub fn printUnbuffered(
10599 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{10580 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{
10600 .@"var" = extra.variable,10581 .@"var" = extra.variable,
10601 .expr = extra.expression,10582 .expr = extra.expression,
10602 }, writer);10583 }, w);
10603 },10584 },
10604 }10585 }
10605 }10586 }
...@@ -10618,22 +10599,18 @@ fn isValidIdentifier(id: []const u8) bool {...@@ -10618,22 +10599,18 @@ fn isValidIdentifier(id: []const u8) bool {
10618}10599}
1061910600
10620const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };10601const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };
10621fn printEscapedString(10602fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, w: *Writer) Writer.Error!void {
10622 slice: []const u8,
10623 quotes: QuoteBehavior,
10624 writer: anytype,
10625) @TypeOf(writer).Error!void {
10626 const need_quotes = switch (quotes) {10603 const need_quotes = switch (quotes) {
10627 .always_quote => true,10604 .always_quote => true,
10628 .quote_unless_valid_identifier => !isValidIdentifier(slice),10605 .quote_unless_valid_identifier => !isValidIdentifier(slice),
10629 };10606 };
10630 if (need_quotes) try writer.writeByte('"');10607 if (need_quotes) try w.writeByte('"');
10631 for (slice) |byte| switch (byte) {10608 for (slice) |byte| switch (byte) {
10632 '\\' => try writer.writeAll("\\\\"),10609 '\\' => try w.writeAll("\\\\"),
10633 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(byte),10610 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try w.writeByte(byte),
10634 else => try writer.print("\\{X:0>2}", .{byte}),10611 else => try w.print("\\{X:0>2}", .{byte}),
10635 };10612 };
10636 if (need_quotes) try writer.writeByte('"');10613 if (need_quotes) try w.writeByte('"');
10637}10614}
1063810615
10639fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {10616fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {
...@@ -12018,7 +11995,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:...@@ -12018,7 +11995,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:
12018}11995}
1201911996
12020pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {11997pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {
12021 self.metadata_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;11998 self.metadata_string_bytes.printAssumeCapacity(fmt_str, fmt_args);
12022 return self.trailingMetadataStringAssumeCapacity();11999 return self.trailingMetadataStringAssumeCapacity();
12023}12000}
1202412001
...@@ -15261,12 +15238,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -15261,12 +15238,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
15261 return bitcode.toOwnedSlice();15238 return bitcode.toOwnedSlice();
15262}15239}
1526315240
15264const Allocator = std.mem.Allocator;15241const FormatFlags = struct {
15265const assert = std.debug.assert;15242 comma: bool = false,
15266const bitcode_writer = @import("bitcode_writer.zig");15243 space: bool = false,
15267const Builder = @This();15244 percent: bool = false,
15268const builtin = @import("builtin");15245
15269const DW = std.dwarf;15246 fn onlyPercent(f: FormatFlags) bool {
15270const ir = @import("ir.zig");15247 return !f.comma and !f.space and f.percent;
15271const log = std.log.scoped(.llvm);15248 }
15272const std = @import("../../std.zig");15249};
lib/std/zig/parser_test.zig+11-11
...@@ -1,3 +1,9 @@...@@ -1,3 +1,9 @@
1const std = @import("std");
2const mem = std.mem;
3const print = std.debug.print;
4const io = std.io;
5const maxInt = std.math.maxInt;
6
1test "zig fmt: remove extra whitespace at start and end of file with comment between" {7test "zig fmt: remove extra whitespace at start and end of file with comment between" {
2 try testTransform(8 try testTransform(
3 \\9 \\
...@@ -2738,11 +2744,11 @@ test "zig fmt: preserve spacing" {...@@ -2738,11 +2744,11 @@ test "zig fmt: preserve spacing" {
2738 \\const std = @import("std");2744 \\const std = @import("std");
2739 \\2745 \\
2740 \\pub fn main() !void {2746 \\pub fn main() !void {
2741 \\ var stdout_file = std.io.getStdOut;2747 \\ var stdout_file = std.lol.abcd;
2742 \\ var stdout_file = std.io.getStdOut;2748 \\ var stdout_file = std.lol.abcd;
2743 \\2749 \\
2744 \\ var stdout_file = std.io.getStdOut;2750 \\ var stdout_file = std.lol.abcd;
2745 \\ var stdout_file = std.io.getStdOut;2751 \\ var stdout_file = std.lol.abcd;
2746 \\}2752 \\}
2747 \\2753 \\
2748 );2754 );
...@@ -6315,16 +6321,10 @@ test "ampersand" {...@@ -6315,16 +6321,10 @@ test "ampersand" {
6315 , &.{});6321 , &.{});
6316}6322}
63176323
6318const std = @import("std");
6319const mem = std.mem;
6320const print = std.debug.print;
6321const io = std.io;
6322const maxInt = std.math.maxInt;
6323
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 = io.getStdErr().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+2-2
...@@ -22,8 +22,8 @@ pub fn main() !void {...@@ -22,8 +22,8 @@ pub fn main() !void {
22 const bytes_per_sec_float = @as(f64, @floatFromInt(source.len * iterations)) / elapsed_s;22 const bytes_per_sec_float = @as(f64, @floatFromInt(source.len * iterations)) / elapsed_s;
23 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));23 const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float)));
2424
25 var stdout_file = std.io.getStdOut();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+4-4
...@@ -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.format(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.format(writer, "{f}", .{std.zig.fmtString(&buf)});
2888 pos += 1;2888 pos += 1;
2889 },2889 },
2890 0x80...0xff => {2890 0x80...0xff => {
...@@ -3245,7 +3245,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {...@@ -3245,7 +3245,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
3245 return struct {3245 return struct {
3246 const Self = @This();3246 const Self = @This();
3247 pub const WriteError = UnderlyingWriter.Error;3247 pub const WriteError = UnderlyingWriter.Error;
3248 pub const Writer = std.io.Writer(*Self, WriteError, write);3248 pub const Writer = std.io.GenericWriter(*Self, WriteError, write);
32493249
3250 pub const IndentType = enum {3250 pub const IndentType = enum {
3251 normal,3251 normal,
lib/std/zig/string_literal.zig+3-10
...@@ -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,
...@@ -322,7 +315,7 @@ test parseCharLiteral {...@@ -322,7 +315,7 @@ test parseCharLiteral {
322 );315 );
323}316}
324317
325/// Parses `bytes` as a Zig string literal and writes the result to the std.io.Writer type.318/// Parses `bytes` as a Zig string literal and writes the result to the `std.io.GenericWriter` type.
326/// Asserts `bytes` has '"' at beginning and end.319/// Asserts `bytes` has '"' at beginning and end.
327pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result {320pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result {
328 assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"');321 assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"');
lib/std/zig/system/linux.zig+4-4
...@@ -391,7 +391,7 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {...@@ -391,7 +391,7 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
391 const current_arch = builtin.cpu.arch;391 const current_arch = builtin.cpu.arch;
392 switch (current_arch) {392 switch (current_arch) {
393 .arm, .armeb, .thumb, .thumbeb => {393 .arm, .armeb, .thumb, .thumbeb => {
394 return ArmCpuinfoParser.parse(current_arch, f.reader()) catch null;394 return ArmCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
395 },395 },
396 .aarch64, .aarch64_be => {396 .aarch64, .aarch64_be => {
397 const registers = [12]u64{397 const registers = [12]u64{
...@@ -413,13 +413,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {...@@ -413,13 +413,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
413 return core;413 return core;
414 },414 },
415 .sparc64 => {415 .sparc64 => {
416 return SparcCpuinfoParser.parse(current_arch, f.reader()) catch null;416 return SparcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
417 },417 },
418 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {418 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
419 return PowerpcCpuinfoParser.parse(current_arch, f.reader()) catch null;419 return PowerpcCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
420 },420 },
421 .riscv64, .riscv32 => {421 .riscv64, .riscv32 => {
422 return RiscvCpuinfoParser.parse(current_arch, f.reader()) catch null;422 return RiscvCpuinfoParser.parse(current_arch, f.deprecatedReader()) catch null;
423 },423 },
424 else => {},424 else => {},
425 }425 }
lib/std/zip.zig+12-12
...@@ -106,7 +106,7 @@ pub const EndRecord = extern struct {...@@ -106,7 +106,7 @@ pub const EndRecord = extern struct {
106/// Find and return the end record for the given seekable zip stream.106/// Find and return the end record for the given seekable zip stream.
107/// Note that `seekable_stream` must be an instance of `std.io.SeekableStream` and107/// Note that `seekable_stream` must be an instance of `std.io.SeekableStream` and
108/// its context must also have a `.reader()` method that returns an instance of108/// its context must also have a `.reader()` method that returns an instance of
109/// `std.io.Reader`.109/// `std.io.GenericReader`.
110pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord {110pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord {
111 var buf: [@sizeOf(EndRecord) + std.math.maxInt(u16)]u8 = undefined;111 var buf: [@sizeOf(EndRecord) + std.math.maxInt(u16)]u8 = undefined;
112 const record_len_max = @min(stream_len, buf.len);112 const record_len_max = @min(stream_len, buf.len);
...@@ -124,7 +124,7 @@ pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord {...@@ -124,7 +124,7 @@ pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord {
124124
125 try seekable_stream.seekTo(stream_len - @as(u64, new_loaded_len));125 try seekable_stream.seekTo(stream_len - @as(u64, new_loaded_len));
126 const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len];126 const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len];
127 const len = try seekable_stream.context.reader().readAll(read_buf);127 const len = try (if (@TypeOf(seekable_stream.context) == std.fs.File) seekable_stream.context.deprecatedReader() else seekable_stream.context.reader()).readAll(read_buf);
128 if (len != read_len)128 if (len != read_len)
129 return error.ZipTruncated;129 return error.ZipTruncated;
130 loaded_len = new_loaded_len;130 loaded_len = new_loaded_len;
...@@ -295,7 +295,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -295,7 +295,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
295 if (locator_end_offset > stream_len)295 if (locator_end_offset > stream_len)
296 return error.ZipTruncated;296 return error.ZipTruncated;
297 try stream.seekTo(stream_len - locator_end_offset);297 try stream.seekTo(stream_len - locator_end_offset);
298 const locator = try stream.context.reader().readStructEndian(EndLocator64, .little);298 const locator = try (if (@TypeOf(stream.context) == std.fs.File) stream.context.deprecatedReader() else stream.context.reader()).readStructEndian(EndLocator64, .little);
299 if (!std.mem.eql(u8, &locator.signature, &end_locator64_sig))299 if (!std.mem.eql(u8, &locator.signature, &end_locator64_sig))
300 return error.ZipBadLocatorSig;300 return error.ZipBadLocatorSig;
301 if (locator.zip64_disk_count != 0)301 if (locator.zip64_disk_count != 0)
...@@ -305,7 +305,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -305,7 +305,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
305305
306 try stream.seekTo(locator.record_file_offset);306 try stream.seekTo(locator.record_file_offset);
307307
308 const record64 = try stream.context.reader().readStructEndian(EndRecord64, .little);308 const record64 = try (if (@TypeOf(stream.context) == std.fs.File) stream.context.deprecatedReader() else stream.context.reader()).readStructEndian(EndRecord64, .little);
309309
310 if (!std.mem.eql(u8, &record64.signature, &end_record64_sig))310 if (!std.mem.eql(u8, &record64.signature, &end_record64_sig))
311 return error.ZipBadEndRecord64Sig;311 return error.ZipBadEndRecord64Sig;
...@@ -357,7 +357,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -357,7 +357,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
357357
358 const header_zip_offset = self.cd_zip_offset + self.cd_record_offset;358 const header_zip_offset = self.cd_zip_offset + self.cd_record_offset;
359 try self.stream.seekTo(header_zip_offset);359 try self.stream.seekTo(header_zip_offset);
360 const header = try self.stream.context.reader().readStructEndian(CentralDirectoryFileHeader, .little);360 const header = try (if (@TypeOf(self.stream.context) == std.fs.File) self.stream.context.deprecatedReader() else self.stream.context.reader()).readStructEndian(CentralDirectoryFileHeader, .little);
361 if (!std.mem.eql(u8, &header.signature, &central_file_header_sig))361 if (!std.mem.eql(u8, &header.signature, &central_file_header_sig))
362 return error.ZipBadCdOffset;362 return error.ZipBadCdOffset;
363363
...@@ -386,7 +386,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -386,7 +386,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
386386
387 {387 {
388 try self.stream.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len);388 try self.stream.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len);
389 const len = try self.stream.context.reader().readAll(extra);389 const len = try (if (@TypeOf(self.stream.context) == std.fs.File) self.stream.context.deprecatedReader() else self.stream.context.reader()).readAll(extra);
390 if (len != extra.len)390 if (len != extra.len)
391 return error.ZipTruncated;391 return error.ZipTruncated;
392 }392 }
...@@ -449,7 +449,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -449,7 +449,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
449 try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader));449 try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader));
450450
451 {451 {
452 const len = try stream.context.reader().readAll(filename);452 const len = try (if (@TypeOf(stream.context) == std.fs.File) stream.context.deprecatedReader() else stream.context.reader()).readAll(filename);
453 if (len != filename.len)453 if (len != filename.len)
454 return error.ZipBadFileOffset;454 return error.ZipBadFileOffset;
455 }455 }
...@@ -457,7 +457,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -457,7 +457,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
457 const local_data_header_offset: u64 = local_data_header_offset: {457 const local_data_header_offset: u64 = local_data_header_offset: {
458 const local_header = blk: {458 const local_header = blk: {
459 try stream.seekTo(self.file_offset);459 try stream.seekTo(self.file_offset);
460 break :blk try stream.context.reader().readStructEndian(LocalFileHeader, .little);460 break :blk try (if (@TypeOf(stream.context) == std.fs.File) stream.context.deprecatedReader() else stream.context.reader()).readStructEndian(LocalFileHeader, .little);
461 };461 };
462 if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig))462 if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig))
463 return error.ZipBadFileOffset;463 return error.ZipBadFileOffset;
...@@ -483,7 +483,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -483,7 +483,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
483483
484 {484 {
485 try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len);485 try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len);
486 const len = try stream.context.reader().readAll(extra);486 const len = try (if (@TypeOf(stream.context) == std.fs.File) stream.context.deprecatedReader() else stream.context.reader()).readAll(extra);
487 if (len != extra.len)487 if (len != extra.len)
488 return error.ZipTruncated;488 return error.ZipTruncated;
489 }489 }
...@@ -552,12 +552,12 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -552,12 +552,12 @@ pub fn Iterator(comptime SeekableStream: type) type {
552 @as(u64, @sizeOf(LocalFileHeader)) +552 @as(u64, @sizeOf(LocalFileHeader)) +
553 local_data_header_offset;553 local_data_header_offset;
554 try stream.seekTo(local_data_file_offset);554 try stream.seekTo(local_data_file_offset);
555 var limited_reader = std.io.limitedReader(stream.context.reader(), self.compressed_size);555 var limited_reader = std.io.limitedReader((if (@TypeOf(stream.context) == std.fs.File) stream.context.deprecatedReader() else stream.context.reader()), self.compressed_size);
556 const crc = try decompress(556 const crc = try decompress(
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;
...@@ -617,7 +617,7 @@ pub const ExtractOptions = struct {...@@ -617,7 +617,7 @@ pub const ExtractOptions = struct {
617/// Extract the zipped files inside `seekable_stream` to the given `dest` directory.617/// Extract the zipped files inside `seekable_stream` to the given `dest` directory.
618/// Note that `seekable_stream` must be an instance of `std.io.SeekableStream` and618/// Note that `seekable_stream` must be an instance of `std.io.SeekableStream` and
619/// its context must also have a `.reader()` method that returns an instance of619/// its context must also have a `.reader()` method that returns an instance of
620/// `std.io.Reader`.620/// `std.io.GenericReader`.
621pub fn extract(dest: std.fs.Dir, seekable_stream: anytype, options: ExtractOptions) !void {621pub fn extract(dest: std.fs.Dir, seekable_stream: anytype, options: ExtractOptions) !void {
622 const SeekableStream = @TypeOf(seekable_stream);622 const SeekableStream = @TypeOf(seekable_stream);
623 var iter = try Iterator(SeekableStream).init(seekable_stream);623 var iter = try Iterator(SeekableStream).init(seekable_stream);
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+111-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,18 @@ pub const Diagnostics = struct {...@@ -241,25 +226,18 @@ 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) std.io.Writer.Error!void {
245 self: *const @This(),
246 comptime fmt: []const u8,
247 options: std.fmt.FormatOptions,
248 writer: anytype,
249 ) !void {
250 _ = fmt;
251 _ = options;
252 var errors = self.iterateErrors();230 var errors = self.iterateErrors();
253 while (errors.next()) |err| {231 while (errors.next()) |err| {
254 const loc = err.getLocation(self);232 const loc = err.getLocation(self);
255 const msg = err.fmtMessage(self);233 const msg = err.fmtMessage(self);
256 try writer.print("{}:{}: error: {}\n", .{ loc.line + 1, loc.column + 1, msg });234 try w.print("{d}:{d}: error: {f}\n", .{ loc.line + 1, loc.column + 1, msg });
257235
258 var notes = err.iterateNotes(self);236 var notes = err.iterateNotes(self);
259 while (notes.next()) |note| {237 while (notes.next()) |note| {
260 const note_loc = note.getLocation(self);238 const note_loc = note.getLocation(self);
261 const note_msg = note.fmtMessage(self);239 const note_msg = note.fmtMessage(self);
262 try writer.print("{}:{}: note: {s}\n", .{240 try w.print("{d}:{d}: note: {f}\n", .{
263 note_loc.line + 1,241 note_loc.line + 1,
264 note_loc.column + 1,242 note_loc.column + 1,
265 note_msg,243 note_msg,
...@@ -646,7 +624,7 @@ const Parser = struct {...@@ -646,7 +624,7 @@ const Parser = struct {
646 .failure => |err| {624 .failure => |err| {
647 const token = self.ast.nodeMainToken(ast_node);625 const token = self.ast.nodeMainToken(ast_node);
648 const raw_string = self.ast.tokenSlice(token);626 const raw_string = self.ast.tokenSlice(token);
649 return self.failTokenFmt(token, @intCast(err.offset()), "{s}", .{err.fmt(raw_string)});627 return self.failTokenFmt(token, @intCast(err.offset()), "{f}", .{err.fmt(raw_string)});
650 },628 },
651 }629 }
652630
...@@ -1087,7 +1065,10 @@ const Parser = struct {...@@ -1087,7 +1065,10 @@ const Parser = struct {
1087 try writer.writeAll(msg);1065 try writer.writeAll(msg);
1088 inline for (info.fields, 0..) |field_info, i| {1066 inline for (info.fields, 0..) |field_info, i| {
1089 if (i != 0) try writer.writeAll(", ");1067 if (i != 0) try writer.writeAll(", ");
1090 try writer.print("'{p_}'", .{std.zig.fmtId(field_info.name)});1068 try writer.print("'{f}'", .{std.zig.fmtIdFlags(field_info.name, .{
1069 .allow_primitive = true,
1070 .allow_underscore = true,
1071 })});
1091 }1072 }
1092 break :b .{1073 break :b .{
1093 .token = token,1074 .token = token,
...@@ -1298,7 +1279,7 @@ test "std.zon ast errors" {...@@ -1298,7 +1279,7 @@ test "std.zon ast errors" {
1298 error.ParseZon,1279 error.ParseZon,
1299 fromSlice(struct {}, gpa, ".{.x = 1 .y = 2}", &diag, .{}),1280 fromSlice(struct {}, gpa, ".{.x = 1 .y = 2}", &diag, .{}),
1300 );1281 );
1301 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{}", .{diag});1282 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{diag});
1302}1283}
13031284
1304test "std.zon comments" {1285test "std.zon comments" {
...@@ -1320,7 +1301,7 @@ test "std.zon comments" {...@@ -1320,7 +1301,7 @@ test "std.zon comments" {
1320 , &diag, .{}));1301 , &diag, .{}));
1321 try std.testing.expectFmt(1302 try std.testing.expectFmt(
1322 "1:1: error: expected expression, found 'a document comment'\n",1303 "1:1: error: expected expression, found 'a document comment'\n",
1323 "{}",1304 "{f}",
1324 .{diag},1305 .{diag},
1325 );1306 );
1326 }1307 }
...@@ -1341,7 +1322,7 @@ test "std.zon failure/oom formatting" {...@@ -1341,7 +1322,7 @@ test "std.zon failure/oom formatting" {
1341 &diag,1322 &diag,
1342 .{},1323 .{},
1343 ));1324 ));
1344 try std.testing.expectFmt("", "{}", .{diag});1325 try std.testing.expectFmt("", "{f}", .{diag});
1345}1326}
13461327
1347test "std.zon fromSlice syntax error" {1328test "std.zon fromSlice syntax error" {
...@@ -1421,7 +1402,7 @@ test "std.zon unions" {...@@ -1421,7 +1402,7 @@ test "std.zon unions" {
1421 \\1:4: note: supported: 'x', 'y'1402 \\1:4: note: supported: 'x', 'y'
1422 \\1403 \\
1423 ,1404 ,
1424 "{}",1405 "{f}",
1425 .{diag},1406 .{diag},
1426 );1407 );
1427 }1408 }
...@@ -1435,7 +1416,7 @@ test "std.zon unions" {...@@ -1435,7 +1416,7 @@ test "std.zon unions" {
1435 error.ParseZon,1416 error.ParseZon,
1436 fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),1417 fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),
1437 );1418 );
1438 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{}", .{diag});1419 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
1439 }1420 }
14401421
1441 // Extra field1422 // Extra field
...@@ -1447,7 +1428,7 @@ test "std.zon unions" {...@@ -1447,7 +1428,7 @@ test "std.zon unions" {
1447 error.ParseZon,1428 error.ParseZon,
1448 fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),1429 fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
1449 );1430 );
1450 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});1431 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
1451 }1432 }
14521433
1453 // No fields1434 // No fields
...@@ -1459,7 +1440,7 @@ test "std.zon unions" {...@@ -1459,7 +1440,7 @@ test "std.zon unions" {
1459 error.ParseZon,1440 error.ParseZon,
1460 fromSlice(Union, gpa, ".{}", &diag, .{}),1441 fromSlice(Union, gpa, ".{}", &diag, .{}),
1461 );1442 );
1462 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});1443 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
1463 }1444 }
14641445
1465 // Enum literals cannot coerce into untagged unions1446 // Enum literals cannot coerce into untagged unions
...@@ -1468,7 +1449,7 @@ test "std.zon unions" {...@@ -1468,7 +1449,7 @@ test "std.zon unions" {
1468 var diag: Diagnostics = .{};1449 var diag: Diagnostics = .{};
1469 defer diag.deinit(gpa);1450 defer diag.deinit(gpa);
1470 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));1451 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
1471 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});1452 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
1472 }1453 }
14731454
1474 // Unknown field for enum literal coercion1455 // Unknown field for enum literal coercion
...@@ -1482,7 +1463,7 @@ test "std.zon unions" {...@@ -1482,7 +1463,7 @@ test "std.zon unions" {
1482 \\1:2: note: supported: 'x'1463 \\1:2: note: supported: 'x'
1483 \\1464 \\
1484 ,1465 ,
1485 "{}",1466 "{f}",
1486 .{diag},1467 .{diag},
1487 );1468 );
1488 }1469 }
...@@ -1493,7 +1474,7 @@ test "std.zon unions" {...@@ -1493,7 +1474,7 @@ test "std.zon unions" {
1493 var diag: Diagnostics = .{};1474 var diag: Diagnostics = .{};
1494 defer diag.deinit(gpa);1475 defer diag.deinit(gpa);
1495 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));1476 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
1496 try std.testing.expectFmt("1:2: error: expected union\n", "{}", .{diag});1477 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
1497 }1478 }
1498}1479}
14991480
...@@ -1549,7 +1530,7 @@ test "std.zon structs" {...@@ -1549,7 +1530,7 @@ test "std.zon structs" {
1549 \\1:12: note: supported: 'x', 'y'1530 \\1:12: note: supported: 'x', 'y'
1550 \\1531 \\
1551 ,1532 ,
1552 "{}",1533 "{f}",
1553 .{diag},1534 .{diag},
1554 );1535 );
1555 }1536 }
...@@ -1567,7 +1548,7 @@ test "std.zon structs" {...@@ -1567,7 +1548,7 @@ test "std.zon structs" {
1567 \\1:4: error: duplicate struct field name1548 \\1:4: error: duplicate struct field name
1568 \\1:12: note: duplicate name here1549 \\1:12: note: duplicate name here
1569 \\1550 \\
1570 , "{}", .{diag});1551 , "{f}", .{diag});
1571 }1552 }
15721553
1573 // Ignore unknown fields1554 // Ignore unknown fields
...@@ -1592,7 +1573,7 @@ test "std.zon structs" {...@@ -1592,7 +1573,7 @@ test "std.zon structs" {
1592 \\1:4: error: unexpected field 'x'1573 \\1:4: error: unexpected field 'x'
1593 \\1:4: note: none expected1574 \\1:4: note: none expected
1594 \\1575 \\
1595 , "{}", .{diag});1576 , "{f}", .{diag});
1596 }1577 }
15971578
1598 // Missing field1579 // Missing field
...@@ -1604,7 +1585,7 @@ test "std.zon structs" {...@@ -1604,7 +1585,7 @@ test "std.zon structs" {
1604 error.ParseZon,1585 error.ParseZon,
1605 fromSlice(Vec2, gpa, ".{.x=1.5}", &diag, .{}),1586 fromSlice(Vec2, gpa, ".{.x=1.5}", &diag, .{}),
1606 );1587 );
1607 try std.testing.expectFmt("1:2: error: missing required field y\n", "{}", .{diag});1588 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{diag});
1608 }1589 }
16091590
1610 // Default field1591 // Default field
...@@ -1631,7 +1612,7 @@ test "std.zon structs" {...@@ -1631,7 +1612,7 @@ test "std.zon structs" {
1631 try std.testing.expectFmt(1612 try std.testing.expectFmt(
1632 \\1:18: error: cannot initialize comptime field1613 \\1:18: error: cannot initialize comptime field
1633 \\1614 \\
1634 , "{}", .{diag});1615 , "{f}", .{diag});
1635 }1616 }
16361617
1637 // Enum field (regression test, we were previously getting the field name in an1618 // Enum field (regression test, we were previously getting the field name in an
...@@ -1661,7 +1642,7 @@ test "std.zon structs" {...@@ -1661,7 +1642,7 @@ test "std.zon structs" {
1661 \\1:1: error: types are not available in ZON1642 \\1:1: error: types are not available in ZON
1662 \\1:1: note: replace the type with '.'1643 \\1:1: note: replace the type with '.'
1663 \\1644 \\
1664 , "{}", .{diag});1645 , "{f}", .{diag});
1665 }1646 }
16661647
1667 // Arrays1648 // Arrays
...@@ -1674,7 +1655,7 @@ test "std.zon structs" {...@@ -1674,7 +1655,7 @@ test "std.zon structs" {
1674 \\1:1: error: types are not available in ZON1655 \\1:1: error: types are not available in ZON
1675 \\1:1: note: replace the type with '.'1656 \\1:1: note: replace the type with '.'
1676 \\1657 \\
1677 , "{}", .{diag});1658 , "{f}", .{diag});
1678 }1659 }
16791660
1680 // Slices1661 // Slices
...@@ -1687,7 +1668,7 @@ test "std.zon structs" {...@@ -1687,7 +1668,7 @@ test "std.zon structs" {
1687 \\1:1: error: types are not available in ZON1668 \\1:1: error: types are not available in ZON
1688 \\1:1: note: replace the type with '.'1669 \\1:1: note: replace the type with '.'
1689 \\1670 \\
1690 , "{}", .{diag});1671 , "{f}", .{diag});
1691 }1672 }
16921673
1693 // Tuples1674 // Tuples
...@@ -1706,7 +1687,7 @@ test "std.zon structs" {...@@ -1706,7 +1687,7 @@ test "std.zon structs" {
1706 \\1:1: error: types are not available in ZON1687 \\1:1: error: types are not available in ZON
1707 \\1:1: note: replace the type with '.'1688 \\1:1: note: replace the type with '.'
1708 \\1689 \\
1709 , "{}", .{diag});1690 , "{f}", .{diag});
1710 }1691 }
17111692
1712 // Nested1693 // Nested
...@@ -1719,7 +1700,7 @@ test "std.zon structs" {...@@ -1719,7 +1700,7 @@ test "std.zon structs" {
1719 \\1:9: error: types are not available in ZON1700 \\1:9: error: types are not available in ZON
1720 \\1:9: note: replace the type with '.'1701 \\1:9: note: replace the type with '.'
1721 \\1702 \\
1722 , "{}", .{diag});1703 , "{f}", .{diag});
1723 }1704 }
1724 }1705 }
1725}1706}
...@@ -1764,7 +1745,7 @@ test "std.zon tuples" {...@@ -1764,7 +1745,7 @@ test "std.zon tuples" {
1764 error.ParseZon,1745 error.ParseZon,
1765 fromSlice(Tuple, gpa, ".{0.5, true, 123}", &diag, .{}),1746 fromSlice(Tuple, gpa, ".{0.5, true, 123}", &diag, .{}),
1766 );1747 );
1767 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{}", .{diag});1748 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{diag});
1768 }1749 }
17691750
1770 // Extra field1751 // Extra field
...@@ -1778,7 +1759,7 @@ test "std.zon tuples" {...@@ -1778,7 +1759,7 @@ test "std.zon tuples" {
1778 );1759 );
1779 try std.testing.expectFmt(1760 try std.testing.expectFmt(
1780 "1:2: error: missing tuple field with index 1\n",1761 "1:2: error: missing tuple field with index 1\n",
1781 "{}",1762 "{f}",
1782 .{diag},1763 .{diag},
1783 );1764 );
1784 }1765 }
...@@ -1792,7 +1773,7 @@ test "std.zon tuples" {...@@ -1792,7 +1773,7 @@ test "std.zon tuples" {
1792 error.ParseZon,1773 error.ParseZon,
1793 fromSlice(Tuple, gpa, ".{.foo = 10.0}", &diag, .{}),1774 fromSlice(Tuple, gpa, ".{.foo = 10.0}", &diag, .{}),
1794 );1775 );
1795 try std.testing.expectFmt("1:2: error: expected tuple\n", "{}", .{diag});1776 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{diag});
1796 }1777 }
17971778
1798 // Struct with missing field names1779 // Struct with missing field names
...@@ -1804,7 +1785,7 @@ test "std.zon tuples" {...@@ -1804,7 +1785,7 @@ test "std.zon tuples" {
1804 error.ParseZon,1785 error.ParseZon,
1805 fromSlice(Struct, gpa, ".{10.0}", &diag, .{}),1786 fromSlice(Struct, gpa, ".{10.0}", &diag, .{}),
1806 );1787 );
1807 try std.testing.expectFmt("1:2: error: expected struct\n", "{}", .{diag});1788 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{diag});
1808 }1789 }
18091790
1810 // Comptime field1791 // Comptime field
...@@ -1824,7 +1805,7 @@ test "std.zon tuples" {...@@ -1824,7 +1805,7 @@ test "std.zon tuples" {
1824 try std.testing.expectFmt(1805 try std.testing.expectFmt(
1825 \\1:9: error: cannot initialize comptime field1806 \\1:9: error: cannot initialize comptime field
1826 \\1807 \\
1827 , "{}", .{diag});1808 , "{f}", .{diag});
1828 }1809 }
1829}1810}
18301811
...@@ -1936,7 +1917,7 @@ test "std.zon arrays and slices" {...@@ -1936,7 +1917,7 @@ test "std.zon arrays and slices" {
1936 );1917 );
1937 try std.testing.expectFmt(1918 try std.testing.expectFmt(
1938 "1:3: error: index 0 outside of array of length 0\n",1919 "1:3: error: index 0 outside of array of length 0\n",
1939 "{}",1920 "{f}",
1940 .{diag},1921 .{diag},
1941 );1922 );
1942 }1923 }
...@@ -1951,7 +1932,7 @@ test "std.zon arrays and slices" {...@@ -1951,7 +1932,7 @@ test "std.zon arrays and slices" {
1951 );1932 );
1952 try std.testing.expectFmt(1933 try std.testing.expectFmt(
1953 "1:8: error: index 1 outside of array of length 1\n",1934 "1:8: error: index 1 outside of array of length 1\n",
1954 "{}",1935 "{f}",
1955 .{diag},1936 .{diag},
1956 );1937 );
1957 }1938 }
...@@ -1966,7 +1947,7 @@ test "std.zon arrays and slices" {...@@ -1966,7 +1947,7 @@ test "std.zon arrays and slices" {
1966 );1947 );
1967 try std.testing.expectFmt(1948 try std.testing.expectFmt(
1968 "1:2: error: expected 2 array elements; found 1\n",1949 "1:2: error: expected 2 array elements; found 1\n",
1969 "{}",1950 "{f}",
1970 .{diag},1951 .{diag},
1971 );1952 );
1972 }1953 }
...@@ -1981,7 +1962,7 @@ test "std.zon arrays and slices" {...@@ -1981,7 +1962,7 @@ test "std.zon arrays and slices" {
1981 );1962 );
1982 try std.testing.expectFmt(1963 try std.testing.expectFmt(
1983 "1:2: error: expected 3 array elements; found 0\n",1964 "1:2: error: expected 3 array elements; found 0\n",
1984 "{}",1965 "{f}",
1985 .{diag},1966 .{diag},
1986 );1967 );
1987 }1968 }
...@@ -1996,7 +1977,7 @@ test "std.zon arrays and slices" {...@@ -1996,7 +1977,7 @@ test "std.zon arrays and slices" {
1996 error.ParseZon,1977 error.ParseZon,
1997 fromSlice([3]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),1978 fromSlice([3]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
1998 );1979 );
1999 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{}", .{diag});1980 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
2000 }1981 }
20011982
2002 // Slice1983 // Slice
...@@ -2007,7 +1988,7 @@ test "std.zon arrays and slices" {...@@ -2007,7 +1988,7 @@ test "std.zon arrays and slices" {
2007 error.ParseZon,1988 error.ParseZon,
2008 fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),1989 fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
2009 );1990 );
2010 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{}", .{diag});1991 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
2011 }1992 }
2012 }1993 }
20131994
...@@ -2021,7 +2002,7 @@ test "std.zon arrays and slices" {...@@ -2021,7 +2002,7 @@ test "std.zon arrays and slices" {
2021 error.ParseZon,2002 error.ParseZon,
2022 fromSlice([3]u8, gpa, "'a'", &diag, .{}),2003 fromSlice([3]u8, gpa, "'a'", &diag, .{}),
2023 );2004 );
2024 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2005 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2025 }2006 }
20262007
2027 // Slice2008 // Slice
...@@ -2032,7 +2013,7 @@ test "std.zon arrays and slices" {...@@ -2032,7 +2013,7 @@ test "std.zon arrays and slices" {
2032 error.ParseZon,2013 error.ParseZon,
2033 fromSlice([]u8, gpa, "'a'", &diag, .{}),2014 fromSlice([]u8, gpa, "'a'", &diag, .{}),
2034 );2015 );
2035 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2016 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2036 }2017 }
2037 }2018 }
20382019
...@@ -2046,7 +2027,7 @@ test "std.zon arrays and slices" {...@@ -2046,7 +2027,7 @@ test "std.zon arrays and slices" {
2046 );2027 );
2047 try std.testing.expectFmt(2028 try std.testing.expectFmt(
2048 "1:3: error: pointers are not available in ZON\n",2029 "1:3: error: pointers are not available in ZON\n",
2049 "{}",2030 "{f}",
2050 .{diag},2031 .{diag},
2051 );2032 );
2052 }2033 }
...@@ -2085,7 +2066,7 @@ test "std.zon string literal" {...@@ -2085,7 +2066,7 @@ test "std.zon string literal" {
2085 error.ParseZon,2066 error.ParseZon,
2086 fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),2067 fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),
2087 );2068 );
2088 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2069 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2089 }2070 }
20902071
2091 {2072 {
...@@ -2095,7 +2076,7 @@ test "std.zon string literal" {...@@ -2095,7 +2076,7 @@ test "std.zon string literal" {
2095 error.ParseZon,2076 error.ParseZon,
2096 fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),2077 fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),
2097 );2078 );
2098 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2079 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2099 }2080 }
2100 }2081 }
21012082
...@@ -2112,7 +2093,7 @@ test "std.zon string literal" {...@@ -2112,7 +2093,7 @@ test "std.zon string literal" {
2112 error.ParseZon,2093 error.ParseZon,
2113 fromSlice([4:0]u8, gpa, "\"abcd\"", &diag, .{}),2094 fromSlice([4:0]u8, gpa, "\"abcd\"", &diag, .{}),
2114 );2095 );
2115 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2096 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2116 }2097 }
21172098
2118 {2099 {
...@@ -2122,7 +2103,7 @@ test "std.zon string literal" {...@@ -2122,7 +2103,7 @@ test "std.zon string literal" {
2122 error.ParseZon,2103 error.ParseZon,
2123 fromSlice([4:0]u8, gpa, "\\\\abcd", &diag, .{}),2104 fromSlice([4:0]u8, gpa, "\\\\abcd", &diag, .{}),
2124 );2105 );
2125 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2106 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2126 }2107 }
2127 }2108 }
21282109
...@@ -2164,7 +2145,7 @@ test "std.zon string literal" {...@@ -2164,7 +2145,7 @@ test "std.zon string literal" {
2164 error.ParseZon,2145 error.ParseZon,
2165 fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),2146 fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),
2166 );2147 );
2167 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2148 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2168 }2149 }
21692150
2170 {2151 {
...@@ -2174,7 +2155,7 @@ test "std.zon string literal" {...@@ -2174,7 +2155,7 @@ test "std.zon string literal" {
2174 error.ParseZon,2155 error.ParseZon,
2175 fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),2156 fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),
2176 );2157 );
2177 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2158 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2178 }2159 }
2179 }2160 }
21802161
...@@ -2186,7 +2167,7 @@ test "std.zon string literal" {...@@ -2186,7 +2167,7 @@ test "std.zon string literal" {
2186 error.ParseZon,2167 error.ParseZon,
2187 fromSlice([]const u8, gpa, "true", &diag, .{}),2168 fromSlice([]const u8, gpa, "true", &diag, .{}),
2188 );2169 );
2189 try std.testing.expectFmt("1:1: error: expected string\n", "{}", .{diag});2170 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
2190 }2171 }
21912172
2192 // Expecting string literal, getting an incompatible tuple2173 // Expecting string literal, getting an incompatible tuple
...@@ -2197,7 +2178,7 @@ test "std.zon string literal" {...@@ -2197,7 +2178,7 @@ test "std.zon string literal" {
2197 error.ParseZon,2178 error.ParseZon,
2198 fromSlice([]const u8, gpa, ".{false}", &diag, .{}),2179 fromSlice([]const u8, gpa, ".{false}", &diag, .{}),
2199 );2180 );
2200 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{}", .{diag});2181 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
2201 }2182 }
22022183
2203 // Invalid string literal2184 // Invalid string literal
...@@ -2208,7 +2189,7 @@ test "std.zon string literal" {...@@ -2208,7 +2189,7 @@ test "std.zon string literal" {
2208 error.ParseZon,2189 error.ParseZon,
2209 fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),2190 fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),
2210 );2191 );
2211 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{}", .{diag});2192 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
2212 }2193 }
22132194
2214 // Slice wrong child type2195 // Slice wrong child type
...@@ -2220,7 +2201,7 @@ test "std.zon string literal" {...@@ -2220,7 +2201,7 @@ test "std.zon string literal" {
2220 error.ParseZon,2201 error.ParseZon,
2221 fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),2202 fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),
2222 );2203 );
2223 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2204 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2224 }2205 }
22252206
2226 {2207 {
...@@ -2230,7 +2211,7 @@ test "std.zon string literal" {...@@ -2230,7 +2211,7 @@ test "std.zon string literal" {
2230 error.ParseZon,2211 error.ParseZon,
2231 fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),2212 fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),
2232 );2213 );
2233 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2214 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2234 }2215 }
2235 }2216 }
22362217
...@@ -2243,7 +2224,7 @@ test "std.zon string literal" {...@@ -2243,7 +2224,7 @@ test "std.zon string literal" {
2243 error.ParseZon,2224 error.ParseZon,
2244 fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),2225 fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
2245 );2226 );
2246 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2227 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2247 }2228 }
22482229
2249 {2230 {
...@@ -2253,7 +2234,7 @@ test "std.zon string literal" {...@@ -2253,7 +2234,7 @@ test "std.zon string literal" {
2253 error.ParseZon,2234 error.ParseZon,
2254 fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),2235 fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
2255 );2236 );
2256 try std.testing.expectFmt("1:1: error: expected array\n", "{}", .{diag});2237 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
2257 }2238 }
2258 }2239 }
22592240
...@@ -2327,7 +2308,7 @@ test "std.zon enum literals" {...@@ -2327,7 +2308,7 @@ test "std.zon enum literals" {
2327 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2308 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2328 \\2309 \\
2329 ,2310 ,
2330 "{}",2311 "{f}",
2331 .{diag},2312 .{diag},
2332 );2313 );
2333 }2314 }
...@@ -2345,7 +2326,7 @@ test "std.zon enum literals" {...@@ -2345,7 +2326,7 @@ test "std.zon enum literals" {
2345 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2326 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2346 \\2327 \\
2347 ,2328 ,
2348 "{}",2329 "{f}",
2349 .{diag},2330 .{diag},
2350 );2331 );
2351 }2332 }
...@@ -2358,7 +2339,7 @@ test "std.zon enum literals" {...@@ -2358,7 +2339,7 @@ test "std.zon enum literals" {
2358 error.ParseZon,2339 error.ParseZon,
2359 fromSlice(Enum, gpa, "true", &diag, .{}),2340 fromSlice(Enum, gpa, "true", &diag, .{}),
2360 );2341 );
2361 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{}", .{diag});2342 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{diag});
2362 }2343 }
23632344
2364 // Test embedded nulls in an identifier2345 // Test embedded nulls in an identifier
...@@ -2371,7 +2352,7 @@ test "std.zon enum literals" {...@@ -2371,7 +2352,7 @@ test "std.zon enum literals" {
2371 );2352 );
2372 try std.testing.expectFmt(2353 try std.testing.expectFmt(
2373 "1:2: error: identifier cannot contain null bytes\n",2354 "1:2: error: identifier cannot contain null bytes\n",
2374 "{}",2355 "{f}",
2375 .{diag},2356 .{diag},
2376 );2357 );
2377 }2358 }
...@@ -2397,13 +2378,13 @@ test "std.zon parse bool" {...@@ -2397,13 +2378,13 @@ test "std.zon parse bool" {
2397 \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'2378 \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
2398 \\1:2: note: precede identifier with '.' for an enum literal2379 \\1:2: note: precede identifier with '.' for an enum literal
2399 \\2380 \\
2400 , "{}", .{diag});2381 , "{f}", .{diag});
2401 }2382 }
2402 {2383 {
2403 var diag: Diagnostics = .{};2384 var diag: Diagnostics = .{};
2404 defer diag.deinit(gpa);2385 defer diag.deinit(gpa);
2405 try std.testing.expectError(error.ParseZon, fromSlice(bool, gpa, "123", &diag, .{}));2386 try std.testing.expectError(error.ParseZon, fromSlice(bool, gpa, "123", &diag, .{}));
2406 try std.testing.expectFmt("1:1: error: expected type 'bool'\n", "{}", .{diag});2387 try std.testing.expectFmt("1:1: error: expected type 'bool'\n", "{f}", .{diag});
2407 }2388 }
2408}2389}
24092390
...@@ -2476,7 +2457,7 @@ test "std.zon parse int" {...@@ -2476,7 +2457,7 @@ test "std.zon parse int" {
2476 ));2457 ));
2477 try std.testing.expectFmt(2458 try std.testing.expectFmt(
2478 "1:1: error: type 'i66' cannot represent value\n",2459 "1:1: error: type 'i66' cannot represent value\n",
2479 "{}",2460 "{f}",
2480 .{diag},2461 .{diag},
2481 );2462 );
2482 }2463 }
...@@ -2492,7 +2473,7 @@ test "std.zon parse int" {...@@ -2492,7 +2473,7 @@ test "std.zon parse int" {
2492 ));2473 ));
2493 try std.testing.expectFmt(2474 try std.testing.expectFmt(
2494 "1:1: error: type 'i66' cannot represent value\n",2475 "1:1: error: type 'i66' cannot represent value\n",
2495 "{}",2476 "{f}",
2496 .{diag},2477 .{diag},
2497 );2478 );
2498 }2479 }
...@@ -2581,7 +2562,7 @@ test "std.zon parse int" {...@@ -2581,7 +2562,7 @@ test "std.zon parse int" {
2581 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{}));2562 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{}));
2582 try std.testing.expectFmt(2563 try std.testing.expectFmt(
2583 "1:3: error: invalid digit 'a' for decimal base\n",2564 "1:3: error: invalid digit 'a' for decimal base\n",
2584 "{}",2565 "{f}",
2585 .{diag},2566 .{diag},
2586 );2567 );
2587 }2568 }
...@@ -2591,7 +2572,7 @@ test "std.zon parse int" {...@@ -2591,7 +2572,7 @@ test "std.zon parse int" {
2591 var diag: Diagnostics = .{};2572 var diag: Diagnostics = .{};
2592 defer diag.deinit(gpa);2573 defer diag.deinit(gpa);
2593 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "true", &diag, .{}));2574 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "true", &diag, .{}));
2594 try std.testing.expectFmt("1:1: error: expected type 'u8'\n", "{}", .{diag});2575 try std.testing.expectFmt("1:1: error: expected type 'u8'\n", "{f}", .{diag});
2595 }2576 }
25962577
2597 // Failing because an int is out of range2578 // Failing because an int is out of range
...@@ -2601,7 +2582,7 @@ test "std.zon parse int" {...@@ -2601,7 +2582,7 @@ test "std.zon parse int" {
2601 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{}));2582 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{}));
2602 try std.testing.expectFmt(2583 try std.testing.expectFmt(
2603 "1:1: error: type 'u8' cannot represent value\n",2584 "1:1: error: type 'u8' cannot represent value\n",
2604 "{}",2585 "{f}",
2605 .{diag},2586 .{diag},
2606 );2587 );
2607 }2588 }
...@@ -2613,7 +2594,7 @@ test "std.zon parse int" {...@@ -2613,7 +2594,7 @@ test "std.zon parse int" {
2613 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{}));2594 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{}));
2614 try std.testing.expectFmt(2595 try std.testing.expectFmt(
2615 "1:1: error: type 'i8' cannot represent value\n",2596 "1:1: error: type 'i8' cannot represent value\n",
2616 "{}",2597 "{f}",
2617 .{diag},2598 .{diag},
2618 );2599 );
2619 }2600 }
...@@ -2625,7 +2606,7 @@ test "std.zon parse int" {...@@ -2625,7 +2606,7 @@ test "std.zon parse int" {
2625 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{}));2606 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{}));
2626 try std.testing.expectFmt(2607 try std.testing.expectFmt(
2627 "1:1: error: type 'u8' cannot represent value\n",2608 "1:1: error: type 'u8' cannot represent value\n",
2628 "{}",2609 "{f}",
2629 .{diag},2610 .{diag},
2630 );2611 );
2631 }2612 }
...@@ -2637,7 +2618,7 @@ test "std.zon parse int" {...@@ -2637,7 +2618,7 @@ test "std.zon parse int" {
2637 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{}));2618 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{}));
2638 try std.testing.expectFmt(2619 try std.testing.expectFmt(
2639 "1:1: error: type 'u8' cannot represent value\n",2620 "1:1: error: type 'u8' cannot represent value\n",
2640 "{}",2621 "{f}",
2641 .{diag},2622 .{diag},
2642 );2623 );
2643 }2624 }
...@@ -2649,7 +2630,7 @@ test "std.zon parse int" {...@@ -2649,7 +2630,7 @@ test "std.zon parse int" {
2649 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{}));2630 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{}));
2650 try std.testing.expectFmt(2631 try std.testing.expectFmt(
2651 "1:1: error: type 'u8' cannot represent value\n",2632 "1:1: error: type 'u8' cannot represent value\n",
2652 "{}",2633 "{f}",
2653 .{diag},2634 .{diag},
2654 );2635 );
2655 }2636 }
...@@ -2664,7 +2645,7 @@ test "std.zon parse int" {...@@ -2664,7 +2645,7 @@ test "std.zon parse int" {
2664 \\1:2: note: use '0' for an integer zero2645 \\1:2: note: use '0' for an integer zero
2665 \\1:2: note: use '-0.0' for a floating-point signed zero2646 \\1:2: note: use '-0.0' for a floating-point signed zero
2666 \\2647 \\
2667 , "{}", .{diag});2648 , "{f}", .{diag});
2668 }2649 }
26692650
2670 // Negative integer zero casted to float2651 // Negative integer zero casted to float
...@@ -2677,7 +2658,7 @@ test "std.zon parse int" {...@@ -2677,7 +2658,7 @@ test "std.zon parse int" {
2677 \\1:2: note: use '0' for an integer zero2658 \\1:2: note: use '0' for an integer zero
2678 \\1:2: note: use '-0.0' for a floating-point signed zero2659 \\1:2: note: use '-0.0' for a floating-point signed zero
2679 \\2660 \\
2680 , "{}", .{diag});2661 , "{f}", .{diag});
2681 }2662 }
26822663
2683 // Negative float 0 is allowed2664 // Negative float 0 is allowed
...@@ -2693,7 +2674,7 @@ test "std.zon parse int" {...@@ -2693,7 +2674,7 @@ test "std.zon parse int" {
2693 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{}));2674 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{}));
2694 try std.testing.expectFmt(2675 try std.testing.expectFmt(
2695 "1:1: error: expected number or 'inf' after '-'\n",2676 "1:1: error: expected number or 'inf' after '-'\n",
2696 "{}",2677 "{f}",
2697 .{diag},2678 .{diag},
2698 );2679 );
2699 }2680 }
...@@ -2707,7 +2688,7 @@ test "std.zon parse int" {...@@ -2707,7 +2688,7 @@ test "std.zon parse int" {
2707 );2688 );
2708 try std.testing.expectFmt(2689 try std.testing.expectFmt(
2709 "1:1: error: expected number or 'inf' after '-'\n",2690 "1:1: error: expected number or 'inf' after '-'\n",
2710 "{}",2691 "{f}",
2711 .{diag},2692 .{diag},
2712 );2693 );
2713 }2694 }
...@@ -2717,7 +2698,7 @@ test "std.zon parse int" {...@@ -2717,7 +2698,7 @@ test "std.zon parse int" {
2717 var diag: Diagnostics = .{};2698 var diag: Diagnostics = .{};
2718 defer diag.deinit(gpa);2699 defer diag.deinit(gpa);
2719 try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "0xg", &diag, .{}));2700 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});2701 try std.testing.expectFmt("1:3: error: invalid digit 'g' for hex base\n", "{f}", .{diag});
2721 }2702 }
27222703
2723 // Notes on invalid int literal2704 // Notes on invalid int literal
...@@ -2729,7 +2710,7 @@ test "std.zon parse int" {...@@ -2729,7 +2710,7 @@ test "std.zon parse int" {
2729 \\1:1: error: number '0123' has leading zero2710 \\1:1: error: number '0123' has leading zero
2730 \\1:1: note: use '0o' prefix for octal literals2711 \\1:1: note: use '0o' prefix for octal literals
2731 \\2712 \\
2732 , "{}", .{diag});2713 , "{f}", .{diag});
2733 }2714 }
2734}2715}
27352716
...@@ -2742,7 +2723,7 @@ test "std.zon negative char" {...@@ -2742,7 +2723,7 @@ test "std.zon negative char" {
2742 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{}));2723 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{}));
2743 try std.testing.expectFmt(2724 try std.testing.expectFmt(
2744 "1:1: error: expected number or 'inf' after '-'\n",2725 "1:1: error: expected number or 'inf' after '-'\n",
2745 "{}",2726 "{f}",
2746 .{diag},2727 .{diag},
2747 );2728 );
2748 }2729 }
...@@ -2752,7 +2733,7 @@ test "std.zon negative char" {...@@ -2752,7 +2733,7 @@ test "std.zon negative char" {
2752 try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{}));2733 try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{}));
2753 try std.testing.expectFmt(2734 try std.testing.expectFmt(
2754 "1:1: error: expected number or 'inf' after '-'\n",2735 "1:1: error: expected number or 'inf' after '-'\n",
2755 "{}",2736 "{f}",
2756 .{diag},2737 .{diag},
2757 );2738 );
2758 }2739 }
...@@ -2841,7 +2822,7 @@ test "std.zon parse float" {...@@ -2841,7 +2822,7 @@ test "std.zon parse float" {
2841 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{}));2822 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{}));
2842 try std.testing.expectFmt(2823 try std.testing.expectFmt(
2843 "1:1: error: expected number or 'inf' after '-'\n",2824 "1:1: error: expected number or 'inf' after '-'\n",
2844 "{}",2825 "{f}",
2845 .{diag},2826 .{diag},
2846 );2827 );
2847 }2828 }
...@@ -2851,7 +2832,7 @@ test "std.zon parse float" {...@@ -2851,7 +2832,7 @@ test "std.zon parse float" {
2851 var diag: Diagnostics = .{};2832 var diag: Diagnostics = .{};
2852 defer diag.deinit(gpa);2833 defer diag.deinit(gpa);
2853 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));2834 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));
2854 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});2835 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
2855 }2836 }
28562837
2857 // nan as int not allowed2838 // nan as int not allowed
...@@ -2859,7 +2840,7 @@ test "std.zon parse float" {...@@ -2859,7 +2840,7 @@ test "std.zon parse float" {
2859 var diag: Diagnostics = .{};2840 var diag: Diagnostics = .{};
2860 defer diag.deinit(gpa);2841 defer diag.deinit(gpa);
2861 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));2842 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "nan", &diag, .{}));
2862 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});2843 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
2863 }2844 }
28642845
2865 // inf as int not allowed2846 // inf as int not allowed
...@@ -2867,7 +2848,7 @@ test "std.zon parse float" {...@@ -2867,7 +2848,7 @@ test "std.zon parse float" {
2867 var diag: Diagnostics = .{};2848 var diag: Diagnostics = .{};
2868 defer diag.deinit(gpa);2849 defer diag.deinit(gpa);
2869 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "inf", &diag, .{}));2850 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "inf", &diag, .{}));
2870 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});2851 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
2871 }2852 }
28722853
2873 // -inf as int not allowed2854 // -inf as int not allowed
...@@ -2875,7 +2856,7 @@ test "std.zon parse float" {...@@ -2875,7 +2856,7 @@ test "std.zon parse float" {
2875 var diag: Diagnostics = .{};2856 var diag: Diagnostics = .{};
2876 defer diag.deinit(gpa);2857 defer diag.deinit(gpa);
2877 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-inf", &diag, .{}));2858 try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-inf", &diag, .{}));
2878 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{}", .{diag});2859 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{diag});
2879 }2860 }
28802861
2881 // Bad identifier as float2862 // Bad identifier as float
...@@ -2888,7 +2869,7 @@ test "std.zon parse float" {...@@ -2888,7 +2869,7 @@ test "std.zon parse float" {
2888 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'2869 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
2889 \\1:1: note: precede identifier with '.' for an enum literal2870 \\1:1: note: precede identifier with '.' for an enum literal
2890 \\2871 \\
2891 , "{}", .{diag});2872 , "{f}", .{diag});
2892 }2873 }
28932874
2894 {2875 {
...@@ -2897,7 +2878,7 @@ test "std.zon parse float" {...@@ -2897,7 +2878,7 @@ test "std.zon parse float" {
2897 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{}));2878 try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{}));
2898 try std.testing.expectFmt(2879 try std.testing.expectFmt(
2899 "1:1: error: expected number or 'inf' after '-'\n",2880 "1:1: error: expected number or 'inf' after '-'\n",
2900 "{}",2881 "{f}",
2901 .{diag},2882 .{diag},
2902 );2883 );
2903 }2884 }
...@@ -2910,7 +2891,7 @@ test "std.zon parse float" {...@@ -2910,7 +2891,7 @@ test "std.zon parse float" {
2910 error.ParseZon,2891 error.ParseZon,
2911 fromSlice(f32, gpa, "\"foo\"", &diag, .{}),2892 fromSlice(f32, gpa, "\"foo\"", &diag, .{}),
2912 );2893 );
2913 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{}", .{diag});2894 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{diag});
2914 }2895 }
2915}2896}
29162897
...@@ -3154,7 +3135,7 @@ test "std.zon vector" {...@@ -3154,7 +3135,7 @@ test "std.zon vector" {
3154 );3135 );
3155 try std.testing.expectFmt(3136 try std.testing.expectFmt(
3156 "1:2: error: expected 2 vector elements; found 1\n",3137 "1:2: error: expected 2 vector elements; found 1\n",
3157 "{}",3138 "{f}",
3158 .{diag},3139 .{diag},
3159 );3140 );
3160 }3141 }
...@@ -3169,7 +3150,7 @@ test "std.zon vector" {...@@ -3169,7 +3150,7 @@ test "std.zon vector" {
3169 );3150 );
3170 try std.testing.expectFmt(3151 try std.testing.expectFmt(
3171 "1:2: error: expected 2 vector elements; found 3\n",3152 "1:2: error: expected 2 vector elements; found 3\n",
3172 "{}",3153 "{f}",
3173 .{diag},3154 .{diag},
3174 );3155 );
3175 }3156 }
...@@ -3184,7 +3165,7 @@ test "std.zon vector" {...@@ -3184,7 +3165,7 @@ test "std.zon vector" {
3184 );3165 );
3185 try std.testing.expectFmt(3166 try std.testing.expectFmt(
3186 "1:8: error: expected type 'f32'\n",3167 "1:8: error: expected type 'f32'\n",
3187 "{}",3168 "{f}",
3188 .{diag},3169 .{diag},
3189 );3170 );
3190 }3171 }
...@@ -3197,7 +3178,7 @@ test "std.zon vector" {...@@ -3197,7 +3178,7 @@ test "std.zon vector" {
3197 error.ParseZon,3178 error.ParseZon,
3198 fromSlice(@Vector(3, u8), gpa, "true", &diag, .{}),3179 fromSlice(@Vector(3, u8), gpa, "true", &diag, .{}),
3199 );3180 );
3200 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{}", .{diag});3181 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{diag});
3201 }3182 }
32023183
3203 // Elements should get freed on error3184 // Elements should get freed on error
...@@ -3208,7 +3189,7 @@ test "std.zon vector" {...@@ -3208,7 +3189,7 @@ test "std.zon vector" {
3208 error.ParseZon,3189 error.ParseZon,
3209 fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),3190 fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
3210 );3191 );
3211 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{}", .{diag});3192 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{f}", .{diag});
3212 }3193 }
3213}3194}
32143195
...@@ -3332,7 +3313,7 @@ test "std.zon add pointers" {...@@ -3332,7 +3313,7 @@ test "std.zon add pointers" {
3332 error.ParseZon,3313 error.ParseZon,
3333 fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),3314 fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),
3334 );3315 );
3335 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{}", .{diag});3316 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
3336 }3317 }
33373318
3338 {3319 {
...@@ -3342,7 +3323,7 @@ test "std.zon add pointers" {...@@ -3342,7 +3323,7 @@ test "std.zon add pointers" {
3342 error.ParseZon,3323 error.ParseZon,
3343 fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),3324 fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),
3344 );3325 );
3345 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{}", .{diag});3326 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
3346 }3327 }
33473328
3348 {3329 {
...@@ -3352,7 +3333,7 @@ test "std.zon add pointers" {...@@ -3352,7 +3333,7 @@ test "std.zon add pointers" {
3352 error.ParseZon,3333 error.ParseZon,
3353 fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),3334 fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
3354 );3335 );
3355 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{}", .{diag});3336 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{f}", .{diag});
3356 }3337 }
33573338
3358 {3339 {
...@@ -3362,7 +3343,7 @@ test "std.zon add pointers" {...@@ -3362,7 +3343,7 @@ test "std.zon add pointers" {
3362 error.ParseZon,3343 error.ParseZon,
3363 fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),3344 fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),
3364 );3345 );
3365 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{}", .{diag});3346 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
3366 }3347 }
33673348
3368 {3349 {
...@@ -3372,7 +3353,7 @@ test "std.zon add pointers" {...@@ -3372,7 +3353,7 @@ test "std.zon add pointers" {
3372 error.ParseZon,3353 error.ParseZon,
3373 fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),3354 fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
3374 );3355 );
3375 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{}", .{diag});3356 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
3376 }3357 }
33773358
3378 {3359 {
...@@ -3382,7 +3363,7 @@ test "std.zon add pointers" {...@@ -3382,7 +3363,7 @@ test "std.zon add pointers" {
3382 error.ParseZon,3363 error.ParseZon,
3383 fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),3364 fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
3384 );3365 );
3385 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{}", .{diag});3366 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
3386 }3367 }
33873368
3388 {3369 {
...@@ -3392,7 +3373,7 @@ test "std.zon add pointers" {...@@ -3392,7 +3373,7 @@ test "std.zon add pointers" {
3392 error.ParseZon,3373 error.ParseZon,
3393 fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),3374 fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
3394 );3375 );
3395 try std.testing.expectFmt("1:1: error: expected optional union\n", "{}", .{diag});3376 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
3396 }3377 }
33973378
3398 {3379 {
...@@ -3402,7 +3383,7 @@ test "std.zon add pointers" {...@@ -3402,7 +3383,7 @@ test "std.zon add pointers" {
3402 error.ParseZon,3383 error.ParseZon,
3403 fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),3384 fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),
3404 );3385 );
3405 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});3386 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
3406 }3387 }
34073388
3408 {3389 {
...@@ -3412,7 +3393,7 @@ test "std.zon add pointers" {...@@ -3412,7 +3393,7 @@ test "std.zon add pointers" {
3412 error.ParseZon,3393 error.ParseZon,
3413 fromSlice(?[3]u8, gpa, "true", &diag, .{}),3394 fromSlice(?[3]u8, gpa, "true", &diag, .{}),
3414 );3395 );
3415 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});3396 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
3416 }3397 }
34173398
3418 {3399 {
...@@ -3422,7 +3403,7 @@ test "std.zon add pointers" {...@@ -3422,7 +3403,7 @@ test "std.zon add pointers" {
3422 error.ParseZon,3403 error.ParseZon,
3423 fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),3404 fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),
3424 );3405 );
3425 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});3406 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
3426 }3407 }
34273408
3428 {3409 {
...@@ -3432,7 +3413,7 @@ test "std.zon add pointers" {...@@ -3432,7 +3413,7 @@ test "std.zon add pointers" {
3432 error.ParseZon,3413 error.ParseZon,
3433 fromSlice(?[]u8, gpa, "true", &diag, .{}),3414 fromSlice(?[]u8, gpa, "true", &diag, .{}),
3434 );3415 );
3435 try std.testing.expectFmt("1:1: error: expected optional array\n", "{}", .{diag});3416 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
3436 }3417 }
34373418
3438 {3419 {
...@@ -3442,7 +3423,7 @@ test "std.zon add pointers" {...@@ -3442,7 +3423,7 @@ test "std.zon add pointers" {
3442 error.ParseZon,3423 error.ParseZon,
3443 fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),3424 fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),
3444 );3425 );
3445 try std.testing.expectFmt("1:1: error: expected optional string\n", "{}", .{diag});3426 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
3446 }3427 }
34473428
3448 {3429 {
...@@ -3452,7 +3433,7 @@ test "std.zon add pointers" {...@@ -3452,7 +3433,7 @@ test "std.zon add pointers" {
3452 error.ParseZon,3433 error.ParseZon,
3453 fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),3434 fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
3454 );3435 );
3455 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{}", .{diag});3436 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
3456 }3437 }
3457}3438}
34583439
lib/std/zon/stringify.zig+5-4
...@@ -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.printInt(val, 10, .lower, .{});
619 try std.fmt.format(self.writer, "{d}", .{val});
619 }620 }
620621
621 /// Serialize a float.622 /// Serialize a float.
...@@ -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.format(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.format(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-60
...@@ -119,14 +119,7 @@ const Value = extern struct {...@@ -119,14 +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) 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);
129
130 // Work around x86_64 backend limitation.123 // Work around x86_64 backend limitation.
131 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) {124 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) {
132 try writer.writeAll("(unknown)");125 try writer.writeAll("(unknown)");
...@@ -136,12 +129,12 @@ const Value = extern struct {...@@ -136,12 +129,12 @@ const Value = extern struct {
136 switch (value.td.kind) {129 switch (value.td.kind) {
137 .integer => {130 .integer => {
138 if (value.td.isSigned()) {131 if (value.td.isSigned()) {
139 try writer.print("{}", .{value.getSignedInteger()});132 try writer.print("{d}", .{value.getSignedInteger()});
140 } else {133 } else {
141 try writer.print("{}", .{value.getUnsignedInteger()});134 try writer.print("{d}", .{value.getUnsignedInteger()});
142 }135 }
143 },136 },
144 .float => try writer.print("{}", .{value.getFloat()}),137 .float => try writer.print("{d}", .{value.getFloat()}),
145 .unknown => try writer.writeAll("(unknown)"),138 .unknown => try writer.writeAll("(unknown)"),
146 }139 }
147 }140 }
...@@ -172,17 +165,12 @@ fn overflowHandler(...@@ -172,17 +165,12 @@ fn overflowHandler(
172 ) callconv(.c) noreturn {165 ) callconv(.c) noreturn {
173 const lhs: Value = .{ .handle = lhs_handle, .td = data.td };166 const lhs: Value = .{ .handle = lhs_handle, .td = data.td };
174 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };167 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
175168 const signed_str = if (data.td.isSigned()) "signed" else "unsigned";
176 const is_signed = data.td.isSigned();169 panic(
177 const fmt = "{s} integer overflow: " ++ "{} " ++170 @returnAddress(),
178 operator ++ " {} cannot be represented in type {s}";171 "{s} integer overflow: {f} " ++ operator ++ " {f} cannot be represented in type {s}",
179172 .{ signed_str, lhs, rhs, data.td.getName() },
180 panic(@returnAddress(), fmt, .{173 );
181 if (is_signed) "signed" else "unsigned",
182 lhs,
183 rhs,
184 data.td.getName(),
185 });
186 }174 }
187 };175 };
188176
...@@ -201,11 +189,9 @@ fn negationHandler(...@@ -201,11 +189,9 @@ fn negationHandler(
201 value_handle: ValueHandle,189 value_handle: ValueHandle,
202) callconv(.c) noreturn {190) callconv(.c) noreturn {
203 const value: Value = .{ .handle = value_handle, .td = data.td };191 const value: Value = .{ .handle = value_handle, .td = data.td };
204 panic(192 panic(@returnAddress(), "negation of {f} cannot be represented in type {s}", .{
205 @returnAddress(),193 value, data.td.getName(),
206 "negation of {} cannot be represented in type {s}",194 });
207 .{ value, data.td.getName() },
208 );
209}195}
210196
211fn divRemHandlerAbort(197fn divRemHandlerAbort(
...@@ -225,11 +211,9 @@ fn divRemHandler(...@@ -225,11 +211,9 @@ fn divRemHandler(
225 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };211 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
226212
227 if (rhs.isMinusOne()) {213 if (rhs.isMinusOne()) {
228 panic(214 panic(@returnAddress(), "division of {f} by -1 cannot be represented in type {s}", .{
229 @returnAddress(),215 lhs, data.td.getName(),
230 "division of {} by -1 cannot be represented in type {s}",216 });
231 .{ lhs, data.td.getName() },
232 );
233 } else panic(@returnAddress(), "division by zero", .{});217 } else panic(@returnAddress(), "division by zero", .{});
234}218}
235219
...@@ -269,8 +253,8 @@ fn alignmentAssumptionHandler(...@@ -269,8 +253,8 @@ fn alignmentAssumptionHandler(
269 if (maybe_offset) |offset| {253 if (maybe_offset) |offset| {
270 panic(254 panic(
271 @returnAddress(),255 @returnAddress(),
272 "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++256 "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",257 "offset address is {d} aligned, misalignment offset is {d} bytes",
274 .{258 .{
275 alignment,259 alignment,
276 @intFromPtr(offset),260 @intFromPtr(offset),
...@@ -282,8 +266,8 @@ fn alignmentAssumptionHandler(...@@ -282,8 +266,8 @@ fn alignmentAssumptionHandler(
282 } else {266 } else {
283 panic(267 panic(
284 @returnAddress(),268 @returnAddress(),
285 "assumption of {} byte alignment for pointer of type {s} failed\n" ++269 "assumption of {f} byte alignment for pointer of type {s} failed\n" ++
286 "address is {} aligned, misalignment offset is {} bytes",270 "address is {d} aligned, misalignment offset is {d} bytes",
287 .{271 .{
288 alignment,272 alignment,
289 data.td.getName(),273 data.td.getName(),
...@@ -320,21 +304,21 @@ fn shiftOob(...@@ -320,21 +304,21 @@ fn shiftOob(
320 rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())304 rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())
321 {305 {
322 if (rhs.isNegative()) {306 if (rhs.isNegative()) {
323 panic(@returnAddress(), "shift exponent {} is negative", .{rhs});307 panic(@returnAddress(), "shift exponent {f} is negative", .{rhs});
324 } else {308 } else {
325 panic(309 panic(
326 @returnAddress(),310 @returnAddress(),
327 "shift exponent {} is too large for {}-bit type {s}",311 "shift exponent {f} is too large for {d}-bit type {s}",
328 .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },312 .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },
329 );313 );
330 }314 }
331 } else {315 } else {
332 if (lhs.isNegative()) {316 if (lhs.isNegative()) {
333 panic(@returnAddress(), "left shift of negative value {}", .{lhs});317 panic(@returnAddress(), "left shift of negative value {f}", .{lhs});
334 } else {318 } else {
335 panic(319 panic(
336 @returnAddress(),320 @returnAddress(),
337 "left shift of {} by {} places cannot be represented in type {s}",321 "left shift of {f} by {f} places cannot be represented in type {s}",
338 .{ lhs, rhs, data.lhs_type.getName() },322 .{ lhs, rhs, data.lhs_type.getName() },
339 );323 );
340 }324 }
...@@ -359,11 +343,10 @@ fn outOfBounds(...@@ -359,11 +343,10 @@ fn outOfBounds(
359 index_handle: ValueHandle,343 index_handle: ValueHandle,
360) callconv(.c) noreturn {344) callconv(.c) noreturn {
361 const index: Value = .{ .handle = index_handle, .td = data.index_type };345 const index: Value = .{ .handle = index_handle, .td = data.index_type };
362 panic(346 panic(@returnAddress(), "index {f} out of bounds for type {s}", .{
363 @returnAddress(),347 index,
364 "index {} out of bounds for type {s}",348 data.array_type.getName(),
365 .{ index, data.array_type.getName() },349 });
366 );
367}350}
368351
369const PointerOverflowData = extern struct {352const PointerOverflowData = extern struct {
...@@ -387,7 +370,7 @@ fn pointerOverflow(...@@ -387,7 +370,7 @@ fn pointerOverflow(
387 if (result == 0) {370 if (result == 0) {
388 panic(@returnAddress(), "applying zero offset to null pointer", .{});371 panic(@returnAddress(), "applying zero offset to null pointer", .{});
389 } else {372 } else {
390 panic(@returnAddress(), "applying non-zero offset {} to null pointer", .{result});373 panic(@returnAddress(), "applying non-zero offset {d} to null pointer", .{result});
391 }374 }
392 } else {375 } else {
393 if (result == 0) {376 if (result == 0) {
...@@ -483,7 +466,7 @@ fn typeMismatch(...@@ -483,7 +466,7 @@ fn typeMismatch(
483 } else if (!std.mem.isAligned(handle, alignment)) {466 } else if (!std.mem.isAligned(handle, alignment)) {
484 panic(467 panic(
485 @returnAddress(),468 @returnAddress(),
486 "{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment",469 "{s} misaligned address 0x{x} for type {s}, which requires {d} byte alignment",
487 .{ data.kind.getName(), handle, data.td.getName(), alignment },470 .{ data.kind.getName(), handle, data.td.getName(), alignment },
488 );471 );
489 } else {472 } else {
...@@ -531,7 +514,7 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn {...@@ -531,7 +514,7 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn {
531fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {514fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
532 panic(515 panic(
533 @returnAddress(),516 @returnAddress(),
534 "null pointer passed as argument {}, which is declared to never be null",517 "null pointer passed as argument {d}, which is declared to never be null",
535 .{data.arg_index},518 .{data.arg_index},
536 );519 );
537}520}
...@@ -553,11 +536,9 @@ fn loadInvalidValue(...@@ -553,11 +536,9 @@ fn loadInvalidValue(
553 value_handle: ValueHandle,536 value_handle: ValueHandle,
554) callconv(.c) noreturn {537) callconv(.c) noreturn {
555 const value: Value = .{ .handle = value_handle, .td = data.td };538 const value: Value = .{ .handle = value_handle, .td = data.td };
556 panic(539 panic(@returnAddress(), "load of value {f}, which is not valid for type {s}", .{
557 @returnAddress(),540 value, data.td.getName(),
558 "load of value {}, which is not valid for type {s}",541 });
559 .{ value, data.td.getName() },
560 );
561}542}
562543
563const InvalidBuiltinData = extern struct {544const InvalidBuiltinData = extern struct {
...@@ -596,11 +577,7 @@ fn vlaBoundNotPositive(...@@ -596,11 +577,7 @@ fn vlaBoundNotPositive(
596 bound_handle: ValueHandle,577 bound_handle: ValueHandle,
597) callconv(.c) noreturn {578) callconv(.c) noreturn {
598 const bound: Value = .{ .handle = bound_handle, .td = data.td };579 const bound: Value = .{ .handle = bound_handle, .td = data.td };
599 panic(580 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}581}
605582
606const FloatCastOverflowData = extern struct {583const FloatCastOverflowData = extern struct {
...@@ -631,13 +608,13 @@ fn floatCastOverflow(...@@ -631,13 +608,13 @@ fn floatCastOverflow(
631 if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {608 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);609 const data: *const FloatCastOverflowData = @ptrCast(data_handle);
633 const from_value: Value = .{ .handle = from_handle, .td = data.from };610 const from_value: Value = .{ .handle = from_handle, .td = data.from };
634 panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{611 panic(@returnAddress(), "{f} is outside the range of representable values of type {s}", .{
635 from_value, data.to.getName(),612 from_value, data.to.getName(),
636 });613 });
637 } else {614 } else {
638 const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);615 const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);
639 const from_value: Value = .{ .handle = from_handle, .td = data.from };616 const from_value: Value = .{ .handle = from_handle, .td = data.from };
640 panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{617 panic(@returnAddress(), "{f} is outside the range of representable values of type {s}", .{
641 from_value, data.to.getName(),618 from_value, data.to.getName(),
642 });619 });
643 }620 }
src/Air.zig+8-9
...@@ -746,7 +746,9 @@ pub const Inst = struct {...@@ -746,7 +746,9 @@ pub const Inst = struct {
746 /// Dest slice may have any alignment; source pointer may have any alignment.746 /// Dest slice may have any alignment; source pointer may have any alignment.
747 /// The two memory regions must not overlap.747 /// The two memory regions must not overlap.
748 /// Result type is always void.748 /// Result type is always void.
749 ///
749 /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer.750 /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer.
751 ///
750 /// If the length is compile-time known (due to the destination or752 /// If the length is compile-time known (due to the destination or
751 /// source being a pointer-to-array), then it is guaranteed to be753 /// source being a pointer-to-array), then it is guaranteed to be
752 /// greater than zero.754 /// greater than zero.
...@@ -758,7 +760,9 @@ pub const Inst = struct {...@@ -758,7 +760,9 @@ pub const Inst = struct {
758 /// Dest slice may have any alignment; source pointer may have any alignment.760 /// Dest slice may have any alignment; source pointer may have any alignment.
759 /// The two memory regions may overlap.761 /// The two memory regions may overlap.
760 /// Result type is always void.762 /// Result type is always void.
763 ///
761 /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer.764 /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer.
765 ///
762 /// If the length is compile-time known (due to the destination or766 /// If the length is compile-time known (due to the destination or
763 /// source being a pointer-to-array), then it is guaranteed to be767 /// source being a pointer-to-array), then it is guaranteed to be
764 /// greater than zero.768 /// greater than zero.
...@@ -957,18 +961,13 @@ pub const Inst = struct {...@@ -957,18 +961,13 @@ pub const Inst = struct {
957 return index.unwrap().target;961 return index.unwrap().target;
958 }962 }
959963
960 pub fn format(964 pub fn format(index: Index, w: *std.io.Writer) std.io.Writer.Error!void {
961 index: Index,965 try w.writeByte('%');
962 comptime _: []const u8,
963 _: std.fmt.FormatOptions,
964 writer: anytype,
965 ) @TypeOf(writer).Error!void {
966 try writer.writeByte('%');
967 switch (index.unwrap()) {966 switch (index.unwrap()) {
968 .ref => {},967 .ref => {},
969 .target => try writer.writeByte('t'),968 .target => try w.writeByte('t'),
970 }969 }
971 try writer.print("{d}", .{@as(u31, @truncate(@intFromEnum(index)))});970 try w.print("{d}", .{@as(u31, @truncate(@intFromEnum(index)))});
972 }971 }
973 };972 };
974973
src/Air/Liveness.zig+25-25
...@@ -1299,10 +1299,10 @@ fn analyzeOperands(...@@ -1299,10 +1299,10 @@ fn analyzeOperands(
12991299
1300 // This logic must synchronize with `will_die_immediately` in `AnalyzeBigOperands.init`.1300 // This logic must synchronize with `will_die_immediately` in `AnalyzeBigOperands.init`.
1301 const immediate_death = if (data.live_set.remove(inst)) blk: {1301 const immediate_death = if (data.live_set.remove(inst)) blk: {
1302 log.debug("[{}] %{}: removed from live set", .{ pass, @intFromEnum(inst) });1302 log.debug("[{}] %{d}: removed from live set", .{ pass, @intFromEnum(inst) });
1303 break :blk false;1303 break :blk false;
1304 } else blk: {1304 } else blk: {
1305 log.debug("[{}] %{}: immediate death", .{ pass, @intFromEnum(inst) });1305 log.debug("[{}] %{d}: immediate death", .{ pass, @intFromEnum(inst) });
1306 break :blk true;1306 break :blk true;
1307 };1307 };
13081308
...@@ -1323,7 +1323,7 @@ fn analyzeOperands(...@@ -1323,7 +1323,7 @@ fn analyzeOperands(
1323 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));1323 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));
13241324
1325 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {1325 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {
1326 log.debug("[{}] %{}: added %{} to live set (operand dies here)", .{ pass, @intFromEnum(inst), operand });1326 log.debug("[{}] %{d}: added %{d} to live set (operand dies here)", .{ pass, @intFromEnum(inst), operand });
1327 tomb_bits |= mask;1327 tomb_bits |= mask;
1328 }1328 }
1329 }1329 }
...@@ -1462,19 +1462,19 @@ fn analyzeInstBlock(...@@ -1462,19 +1462,19 @@ fn analyzeInstBlock(
1462 },1462 },
14631463
1464 .main_analysis => {1464 .main_analysis => {
1465 log.debug("[{}] %{}: block live set is {}", .{ pass, inst, fmtInstSet(&data.live_set) });1465 log.debug("[{}] %{f}: block live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) });
1466 // We can move the live set because the body should have a noreturn1466 // We can move the live set because the body should have a noreturn
1467 // instruction which overrides the set.1467 // instruction which overrides the set.
1468 try data.block_scopes.put(gpa, inst, .{1468 try data.block_scopes.put(gpa, inst, .{
1469 .live_set = data.live_set.move(),1469 .live_set = data.live_set.move(),
1470 });1470 });
1471 defer {1471 defer {
1472 log.debug("[{}] %{}: popped block scope", .{ pass, inst });1472 log.debug("[{}] %{f}: popped block scope", .{ pass, inst });
1473 var scope = data.block_scopes.fetchRemove(inst).?.value;1473 var scope = data.block_scopes.fetchRemove(inst).?.value;
1474 scope.live_set.deinit(gpa);1474 scope.live_set.deinit(gpa);
1475 }1475 }
14761476
1477 log.debug("[{}] %{}: pushed new block scope", .{ pass, inst });1477 log.debug("[{}] %{f}: pushed new block scope", .{ pass, inst });
1478 try analyzeBody(a, pass, data, body);1478 try analyzeBody(a, pass, data, body);
14791479
1480 // If the block is noreturn, block deaths not only aren't useful, they're impossible to1480 // If the block is noreturn, block deaths not only aren't useful, they're impossible to
...@@ -1501,7 +1501,7 @@ fn analyzeInstBlock(...@@ -1501,7 +1501,7 @@ fn analyzeInstBlock(
1501 }1501 }
1502 assert(measured_num == num_deaths); // post-live-set should be a subset of pre-live-set1502 assert(measured_num == num_deaths); // post-live-set should be a subset of pre-live-set
1503 try a.special.put(gpa, inst, extra_index);1503 try a.special.put(gpa, inst, extra_index);
1504 log.debug("[{}] %{}: block deaths are {}", .{1504 log.debug("[{}] %{f}: block deaths are {f}", .{
1505 pass,1505 pass,
1506 inst,1506 inst,
1507 fmtInstList(@ptrCast(a.extra.items[extra_index + 1 ..][0..num_deaths])),1507 fmtInstList(@ptrCast(a.extra.items[extra_index + 1 ..][0..num_deaths])),
...@@ -1538,7 +1538,7 @@ fn writeLoopInfo(...@@ -1538,7 +1538,7 @@ fn writeLoopInfo(
1538 const block_inst = key.*;1538 const block_inst = key.*;
1539 a.extra.appendAssumeCapacity(@intFromEnum(block_inst));1539 a.extra.appendAssumeCapacity(@intFromEnum(block_inst));
1540 }1540 }
1541 log.debug("[{}] %{}: includes breaks to {}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.breaks) });1541 log.debug("[{}] %{f}: includes breaks to {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.breaks) });
15421542
1543 // Now we put the live operands from the loop body in too1543 // Now we put the live operands from the loop body in too
1544 const num_live = data.live_set.count();1544 const num_live = data.live_set.count();
...@@ -1550,7 +1550,7 @@ fn writeLoopInfo(...@@ -1550,7 +1550,7 @@ fn writeLoopInfo(
1550 const alive = key.*;1550 const alive = key.*;
1551 a.extra.appendAssumeCapacity(@intFromEnum(alive));1551 a.extra.appendAssumeCapacity(@intFromEnum(alive));
1552 }1552 }
1553 log.debug("[{}] %{}: maintain liveness of {}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.live_set) });1553 log.debug("[{}] %{f}: maintain liveness of {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.live_set) });
15541554
1555 try a.special.put(gpa, inst, extra_index);1555 try a.special.put(gpa, inst, extra_index);
15561556
...@@ -1591,7 +1591,7 @@ fn resolveLoopLiveSet(...@@ -1591,7 +1591,7 @@ fn resolveLoopLiveSet(
1591 try data.live_set.ensureUnusedCapacity(gpa, @intCast(loop_live.len));1591 try data.live_set.ensureUnusedCapacity(gpa, @intCast(loop_live.len));
1592 for (loop_live) |alive| data.live_set.putAssumeCapacity(alive, {});1592 for (loop_live) |alive| data.live_set.putAssumeCapacity(alive, {});
15931593
1594 log.debug("[{}] %{}: block live set is {}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });1594 log.debug("[{}] %{f}: block live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });
15951595
1596 for (breaks) |block_inst| {1596 for (breaks) |block_inst| {
1597 // We might break to this block, so include every operand that the block needs alive1597 // We might break to this block, so include every operand that the block needs alive
...@@ -1604,7 +1604,7 @@ fn resolveLoopLiveSet(...@@ -1604,7 +1604,7 @@ fn resolveLoopLiveSet(
1604 }1604 }
1605 }1605 }
16061606
1607 log.debug("[{}] %{}: loop live set is {}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });1607 log.debug("[{}] %{f}: loop live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });
1608}1608}
16091609
1610fn analyzeInstLoop(1610fn analyzeInstLoop(
...@@ -1642,7 +1642,7 @@ fn analyzeInstLoop(...@@ -1642,7 +1642,7 @@ fn analyzeInstLoop(
1642 .live_set = data.live_set.move(),1642 .live_set = data.live_set.move(),
1643 });1643 });
1644 defer {1644 defer {
1645 log.debug("[{}] %{}: popped loop block scop", .{ pass, inst });1645 log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst });
1646 var scope = data.block_scopes.fetchRemove(inst).?.value;1646 var scope = data.block_scopes.fetchRemove(inst).?.value;
1647 scope.live_set.deinit(gpa);1647 scope.live_set.deinit(gpa);
1648 }1648 }
...@@ -1743,13 +1743,13 @@ fn analyzeInstCondBr(...@@ -1743,13 +1743,13 @@ fn analyzeInstCondBr(
1743 }1743 }
1744 }1744 }
17451745
1746 log.debug("[{}] %{}: 'then' branch mirrored deaths are {}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) });1746 log.debug("[{}] %{f}: 'then' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) });
1747 log.debug("[{}] %{}: 'else' branch mirrored deaths are {}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) });1747 log.debug("[{}] %{f}: 'else' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) });
17481748
1749 data.live_set.deinit(gpa);1749 data.live_set.deinit(gpa);
1750 data.live_set = then_live.move(); // Really the union of both live sets1750 data.live_set = then_live.move(); // Really the union of both live sets
17511751
1752 log.debug("[{}] %{}: new live set is {}", .{ pass, inst, fmtInstSet(&data.live_set) });1752 log.debug("[{}] %{f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) });
17531753
1754 // Write the mirrored deaths to `extra`1754 // Write the mirrored deaths to `extra`
1755 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));1755 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));
...@@ -1817,7 +1817,7 @@ fn analyzeInstSwitchBr(...@@ -1817,7 +1817,7 @@ fn analyzeInstSwitchBr(
1817 });1817 });
1818 }1818 }
1819 defer if (is_dispatch_loop) {1819 defer if (is_dispatch_loop) {
1820 log.debug("[{}] %{}: popped loop block scop", .{ pass, inst });1820 log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst });
1821 var scope = data.block_scopes.fetchRemove(inst).?.value;1821 var scope = data.block_scopes.fetchRemove(inst).?.value;
1822 scope.live_set.deinit(gpa);1822 scope.live_set.deinit(gpa);
1823 };1823 };
...@@ -1875,13 +1875,13 @@ fn analyzeInstSwitchBr(...@@ -1875,13 +1875,13 @@ fn analyzeInstSwitchBr(
1875 }1875 }
18761876
1877 for (mirrored_deaths, 0..) |mirrored, i| {1877 for (mirrored_deaths, 0..) |mirrored, i| {
1878 log.debug("[{}] %{}: case {} mirrored deaths are {}", .{ pass, inst, i, fmtInstList(mirrored.items) });1878 log.debug("[{}] %{f}: case {} mirrored deaths are {f}", .{ pass, inst, i, fmtInstList(mirrored.items) });
1879 }1879 }
18801880
1881 data.live_set.deinit(gpa);1881 data.live_set.deinit(gpa);
1882 data.live_set = all_alive.move();1882 data.live_set = all_alive.move();
18831883
1884 log.debug("[{}] %{}: new live set is {}", .{ pass, inst, fmtInstSet(&data.live_set) });1884 log.debug("[{}] %{f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) });
1885 }1885 }
18861886
1887 const else_death_count = @as(u32, @intCast(mirrored_deaths[ncases].items.len));1887 const else_death_count = @as(u32, @intCast(mirrored_deaths[ncases].items.len));
...@@ -1980,7 +1980,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1980,7 +1980,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
19801980
1981 .main_analysis => {1981 .main_analysis => {
1982 if ((try big.data.live_set.fetchPut(gpa, operand, {})) == null) {1982 if ((try big.data.live_set.fetchPut(gpa, operand, {})) == null) {
1983 log.debug("[{}] %{}: added %{} to live set (operand dies here)", .{ pass, big.inst, operand });1983 log.debug("[{}] %{f}: added %{f} to live set (operand dies here)", .{ pass, big.inst, operand });
1984 big.extra_tombs[extra_byte] |= @as(u32, 1) << extra_bit;1984 big.extra_tombs[extra_byte] |= @as(u32, 1) << extra_bit;
1985 }1985 }
1986 },1986 },
...@@ -2036,15 +2036,15 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns...@@ -2036,15 +2036,15 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns
2036const FmtInstSet = struct {2036const FmtInstSet = struct {
2037 set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void),2037 set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void),
20382038
2039 pub fn format(val: FmtInstSet, comptime _: []const u8, _: std.fmt.FormatOptions, w: anytype) !void {2039 pub fn format(val: FmtInstSet, w: *std.io.Writer) std.io.Writer.Error!void {
2040 if (val.set.count() == 0) {2040 if (val.set.count() == 0) {
2041 try w.writeAll("[no instructions]");2041 try w.writeAll("[no instructions]");
2042 return;2042 return;
2043 }2043 }
2044 var it = val.set.keyIterator();2044 var it = val.set.keyIterator();
2045 try w.print("%{}", .{it.next().?.*});2045 try w.print("%{f}", .{it.next().?.*});
2046 while (it.next()) |key| {2046 while (it.next()) |key| {
2047 try w.print(" %{}", .{key.*});2047 try w.print(" %{f}", .{key.*});
2048 }2048 }
2049 }2049 }
2050};2050};
...@@ -2056,14 +2056,14 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList {...@@ -2056,14 +2056,14 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList {
2056const FmtInstList = struct {2056const FmtInstList = struct {
2057 list: []const Air.Inst.Index,2057 list: []const Air.Inst.Index,
20582058
2059 pub fn format(val: FmtInstList, comptime _: []const u8, _: std.fmt.FormatOptions, w: anytype) !void {2059 pub fn format(val: FmtInstList, w: *std.io.Writer) std.io.Writer.Error!void {
2060 if (val.list.len == 0) {2060 if (val.list.len == 0) {
2061 try w.writeAll("[no instructions]");2061 try w.writeAll("[no instructions]");
2062 return;2062 return;
2063 }2063 }
2064 try w.print("%{}", .{val.list[0]});2064 try w.print("%{f}", .{val.list[0]});
2065 for (val.list[1..]) |inst| {2065 for (val.list[1..]) |inst| {
2066 try w.print(" %{}", .{inst});2066 try w.print(" %{f}", .{inst});
2067 }2067 }
2068 }2068 }
2069};2069};
src/Air/Liveness/Verify.zig+12-10
...@@ -73,7 +73,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -73,7 +73,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
73 .trap, .unreach => {73 .trap, .unreach => {
74 try self.verifyInstOperands(inst, .{ .none, .none, .none });74 try self.verifyInstOperands(inst, .{ .none, .none, .none });
75 // This instruction terminates the function, so everything should be dead75 // This instruction terminates the function, so everything should be dead
76 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});76 if (self.live.count() > 0) return invalid("%{f}: instructions still alive", .{inst});
77 },77 },
7878
79 // unary79 // unary
...@@ -166,7 +166,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -166,7 +166,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
166 const un_op = data[@intFromEnum(inst)].un_op;166 const un_op = data[@intFromEnum(inst)].un_op;
167 try self.verifyInstOperands(inst, .{ un_op, .none, .none });167 try self.verifyInstOperands(inst, .{ un_op, .none, .none });
168 // This instruction terminates the function, so everything should be dead168 // This instruction terminates the function, so everything should be dead
169 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});169 if (self.live.count() > 0) return invalid("%{f}: instructions still alive", .{inst});
170 },170 },
171 .dbg_var_ptr,171 .dbg_var_ptr,
172 .dbg_var_val,172 .dbg_var_val,
...@@ -450,7 +450,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -450,7 +450,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
450 .repeat => {450 .repeat => {
451 const repeat = data[@intFromEnum(inst)].repeat;451 const repeat = data[@intFromEnum(inst)].repeat;
452 const expected_live = self.loops.get(repeat.loop_inst) orelse452 const expected_live = self.loops.get(repeat.loop_inst) orelse
453 return invalid("%{}: loop %{} not in scope", .{ @intFromEnum(inst), @intFromEnum(repeat.loop_inst) });453 return invalid("%{d}: loop %{d} not in scope", .{ @intFromEnum(inst), @intFromEnum(repeat.loop_inst) });
454454
455 try self.verifyMatchingLiveness(repeat.loop_inst, expected_live);455 try self.verifyMatchingLiveness(repeat.loop_inst, expected_live);
456 },456 },
...@@ -460,7 +460,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -460,7 +460,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
460 try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0));460 try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0));
461461
462 const expected_live = self.loops.get(br.block_inst) orelse462 const expected_live = self.loops.get(br.block_inst) orelse
463 return invalid("%{}: loop %{} not in scope", .{ @intFromEnum(inst), @intFromEnum(br.block_inst) });463 return invalid("%{d}: loop %{d} not in scope", .{ @intFromEnum(inst), @intFromEnum(br.block_inst) });
464464
465 try self.verifyMatchingLiveness(br.block_inst, expected_live);465 try self.verifyMatchingLiveness(br.block_inst, expected_live);
466 },466 },
...@@ -511,7 +511,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -511,7 +511,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
511511
512 // The same stuff should be alive after the loop as before it.512 // The same stuff should be alive after the loop as before it.
513 const gop = try self.loops.getOrPut(self.gpa, inst);513 const gop = try self.loops.getOrPut(self.gpa, inst);
514 if (gop.found_existing) return invalid("%{}: loop already exists", .{@intFromEnum(inst)});514 if (gop.found_existing) return invalid("%{d}: loop already exists", .{@intFromEnum(inst)});
515 defer {515 defer {
516 var live = self.loops.fetchRemove(inst).?;516 var live = self.loops.fetchRemove(inst).?;
517 live.value.deinit(self.gpa);517 live.value.deinit(self.gpa);
...@@ -560,7 +560,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -560,7 +560,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
560 // after the loop as before it.560 // after the loop as before it.
561 {561 {
562 const gop = try self.loops.getOrPut(self.gpa, inst);562 const gop = try self.loops.getOrPut(self.gpa, inst);
563 if (gop.found_existing) return invalid("%{}: loop already exists", .{@intFromEnum(inst)});563 if (gop.found_existing) return invalid("%{d}: loop already exists", .{@intFromEnum(inst)});
564 gop.value_ptr.* = self.live.move();564 gop.value_ptr.* = self.live.move();
565 }565 }
566 defer {566 defer {
...@@ -601,9 +601,11 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies...@@ -601,9 +601,11 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies
601 return;601 return;
602 };602 };
603 if (dies) {603 if (dies) {
604 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });604 if (!self.live.remove(operand)) return invalid("%{f}: dead operand %{f} reused and killed again", .{
605 inst, operand,
606 });
605 } else {607 } else {
606 if (!self.live.contains(operand)) return invalid("%{}: dead operand %{} reused", .{ inst, operand });608 if (!self.live.contains(operand)) return invalid("%{f}: dead operand %{f} reused", .{ inst, operand });
607 }609 }
608}610}
609611
...@@ -628,9 +630,9 @@ fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {...@@ -628,9 +630,9 @@ fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {
628}630}
629631
630fn verifyMatchingLiveness(self: *Verify, block: Air.Inst.Index, live: LiveMap) Error!void {632fn verifyMatchingLiveness(self: *Verify, block: Air.Inst.Index, live: LiveMap) Error!void {
631 if (self.live.count() != live.count()) return invalid("%{}: different deaths across branches", .{block});633 if (self.live.count() != live.count()) return invalid("%{f}: different deaths across branches", .{block});
632 var live_it = self.live.keyIterator();634 var live_it = self.live.keyIterator();
633 while (live_it.next()) |live_inst| if (!live.contains(live_inst.*)) return invalid("%{}: different deaths across branches", .{block});635 while (live_it.next()) |live_inst| if (!live.contains(live_inst.*)) return invalid("%{f}: different deaths across branches", .{block});
634}636}
635637
636fn invalid(comptime fmt: []const u8, args: anytype) error{LivenessInvalid} {638fn invalid(comptime fmt: []const u8, args: anytype) error{LivenessInvalid} {
src/Air/print.zig+104-98
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const Allocator = std.mem.Allocator;2const Allocator = std.mem.Allocator;
3const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
43
5const build_options = @import("build_options");4const build_options = @import("build_options");
6const Zcu = @import("../Zcu.zig");5const Zcu = @import("../Zcu.zig");
...@@ -9,7 +8,7 @@ const Type = @import("../Type.zig");...@@ -9,7 +8,7 @@ const Type = @import("../Type.zig");
9const Air = @import("../Air.zig");8const Air = @import("../Air.zig");
10const InternPool = @import("../InternPool.zig");9const InternPool = @import("../InternPool.zig");
1110
12pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {11pub fn write(air: Air, stream: *std.io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
13 comptime std.debug.assert(build_options.enable_debug_extensions);12 comptime std.debug.assert(build_options.enable_debug_extensions);
14 const instruction_bytes = air.instructions.len *13 const instruction_bytes = air.instructions.len *
15 // Here we don't use @sizeOf(Air.Inst.Data) because it would include14 // Here we don't use @sizeOf(Air.Inst.Data) because it would include
...@@ -25,20 +24,20 @@ pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Livene...@@ -25,20 +24,20 @@ pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Livene
2524
26 // zig fmt: off25 // zig fmt: off
27 stream.print(26 stream.print(
28 \\# Total AIR+Liveness bytes: {}27 \\# Total AIR+Liveness bytes: {Bi}
29 \\# AIR Instructions: {d} ({})28 \\# AIR Instructions: {d} ({Bi})
30 \\# AIR Extra Data: {d} ({})29 \\# AIR Extra Data: {d} ({Bi})
31 \\# Liveness tomb_bits: {}30 \\# Liveness tomb_bits: {Bi}
32 \\# Liveness Extra Data: {d} ({})31 \\# Liveness Extra Data: {d} ({Bi})
33 \\# Liveness special table: {d} ({})32 \\# Liveness special table: {d} ({Bi})
34 \\33 \\
35 , .{34 , .{
36 fmtIntSizeBin(total_bytes),35 total_bytes,
37 air.instructions.len, fmtIntSizeBin(instruction_bytes),36 air.instructions.len, instruction_bytes,
38 air.extra.items.len, fmtIntSizeBin(extra_bytes),37 air.extra.items.len, extra_bytes,
39 fmtIntSizeBin(tomb_bytes),38 tomb_bytes,
40 if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes),39 if (liveness) |l| l.extra.len else 0, liveness_extra_bytes,
41 if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes),40 if (liveness) |l| l.special.count() else 0, liveness_special_bytes,
42 }) catch return;41 }) catch return;
43 // zig fmt: on42 // zig fmt: on
4443
...@@ -55,7 +54,7 @@ pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Livene...@@ -55,7 +54,7 @@ pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Livene
5554
56pub fn writeInst(55pub fn writeInst(
57 air: Air,56 air: Air,
58 stream: anytype,57 stream: *std.io.Writer,
59 inst: Air.Inst.Index,58 inst: Air.Inst.Index,
60 pt: Zcu.PerThread,59 pt: Zcu.PerThread,
61 liveness: ?Air.Liveness,60 liveness: ?Air.Liveness,
...@@ -73,11 +72,15 @@ pub fn writeInst(...@@ -73,11 +72,15 @@ pub fn writeInst(
73}72}
7473
75pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {74pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
76 air.write(std.io.getStdErr().writer(), pt, liveness);75 const stderr_bw = std.debug.lockStderrWriter(&.{});
76 defer std.debug.unlockStderrWriter();
77 air.write(stderr_bw, pt, liveness);
77}78}
7879
79pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {80pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
80 air.writeInst(std.io.getStdErr().writer(), inst, pt, liveness);81 const stderr_bw = std.debug.lockStderrWriter(&.{});
82 defer std.debug.unlockStderrWriter();
83 air.writeInst(stderr_bw, inst, pt, liveness);
81}84}
8285
83const Writer = struct {86const Writer = struct {
...@@ -88,17 +91,19 @@ const Writer = struct {...@@ -88,17 +91,19 @@ const Writer = struct {
88 indent: usize,91 indent: usize,
89 skip_body: bool,92 skip_body: bool,
9093
91 fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void {94 const Error = std.io.Writer.Error;
95
96 fn writeBody(w: *Writer, s: *std.io.Writer, body: []const Air.Inst.Index) Error!void {
92 for (body) |inst| {97 for (body) |inst| {
93 try w.writeInst(s, inst);98 try w.writeInst(s, inst);
94 try s.writeByte('\n');99 try s.writeByte('\n');
95 }100 }
96 }101 }
97102
98 fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {103 fn writeInst(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
99 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];104 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];
100 try s.writeByteNTimes(' ', w.indent);105 try s.splatByteAll(' ', w.indent);
101 try s.print("{}{c}= {s}(", .{106 try s.print("{f}{c}= {s}(", .{
102 inst,107 inst,
103 @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),108 @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),
104 @tagName(tag),109 @tagName(tag),
...@@ -335,47 +340,48 @@ const Writer = struct {...@@ -335,47 +340,48 @@ const Writer = struct {
335 try s.writeByte(')');340 try s.writeByte(')');
336 }341 }
337342
338 fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {343 fn writeBinOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
339 const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;344 const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
340 try w.writeOperand(s, inst, 0, bin_op.lhs);345 try w.writeOperand(s, inst, 0, bin_op.lhs);
341 try s.writeAll(", ");346 try s.writeAll(", ");
342 try w.writeOperand(s, inst, 1, bin_op.rhs);347 try w.writeOperand(s, inst, 1, bin_op.rhs);
343 }348 }
344349
345 fn writeUnOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {350 fn writeUnOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
346 const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op;351 const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
347 try w.writeOperand(s, inst, 0, un_op);352 try w.writeOperand(s, inst, 0, un_op);
348 }353 }
349354
350 fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {355 fn writeNoOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
351 _ = w;356 _ = w;
357 _ = s;
352 _ = inst;358 _ = inst;
353 // no-op, no argument to write359 // no-op, no argument to write
354 }360 }
355361
356 fn writeType(w: *Writer, s: anytype, ty: Type) !void {362 fn writeType(w: *Writer, s: *std.io.Writer, ty: Type) !void {
357 return ty.print(s, w.pt);363 return ty.print(s, w.pt);
358 }364 }
359365
360 fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {366 fn writeTy(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
361 const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty;367 const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty;
362 try w.writeType(s, ty);368 try w.writeType(s, ty);
363 }369 }
364370
365 fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {371 fn writeArg(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
366 const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;372 const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;
367 try w.writeType(s, arg.ty.toType());373 try w.writeType(s, arg.ty.toType());
368 try s.print(", {d}", .{arg.zir_param_index});374 try s.print(", {d}", .{arg.zir_param_index});
369 }375 }
370376
371 fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {377 fn writeTyOp(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
372 const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;378 const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
373 try w.writeType(s, ty_op.ty.toType());379 try w.writeType(s, ty_op.ty.toType());
374 try s.writeAll(", ");380 try s.writeAll(", ");
375 try w.writeOperand(s, inst, 0, ty_op.operand);381 try w.writeOperand(s, inst, 0, ty_op.operand);
376 }382 }
377383
378 fn writeBlock(w: *Writer, s: anytype, tag: Air.Inst.Tag, inst: Air.Inst.Index) @TypeOf(s).Error!void {384 fn writeBlock(w: *Writer, s: *std.io.Writer, tag: Air.Inst.Tag, inst: Air.Inst.Index) Error!void {
379 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;385 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
380 try w.writeType(s, ty_pl.ty.toType());386 try w.writeType(s, ty_pl.ty.toType());
381 const body: []const Air.Inst.Index = @ptrCast(switch (tag) {387 const body: []const Air.Inst.Index = @ptrCast(switch (tag) {
...@@ -408,15 +414,15 @@ const Writer = struct {...@@ -408,15 +414,15 @@ const Writer = struct {
408 w.indent += 2;414 w.indent += 2;
409 try w.writeBody(s, body);415 try w.writeBody(s, body);
410 w.indent = old_indent;416 w.indent = old_indent;
411 try s.writeByteNTimes(' ', w.indent);417 try s.splatByteAll(' ', w.indent);
412 try s.writeAll("}");418 try s.writeAll("}");
413419
414 for (liveness_block.deaths) |operand| {420 for (liveness_block.deaths) |operand| {
415 try s.print(" {}!", .{operand});421 try s.print(" {f}!", .{operand});
416 }422 }
417 }423 }
418424
419 fn writeLoop(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {425 fn writeLoop(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
420 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;426 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
421 const extra = w.air.extraData(Air.Block, ty_pl.payload);427 const extra = w.air.extraData(Air.Block, ty_pl.payload);
422 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);428 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);
...@@ -428,11 +434,11 @@ const Writer = struct {...@@ -428,11 +434,11 @@ const Writer = struct {
428 w.indent += 2;434 w.indent += 2;
429 try w.writeBody(s, body);435 try w.writeBody(s, body);
430 w.indent = old_indent;436 w.indent = old_indent;
431 try s.writeByteNTimes(' ', w.indent);437 try s.splatByteAll(' ', w.indent);
432 try s.writeAll("}");438 try s.writeAll("}");
433 }439 }
434440
435 fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {441 fn writeAggregateInit(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
436 const zcu = w.pt.zcu;442 const zcu = w.pt.zcu;
437 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;443 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
438 const vector_ty = ty_pl.ty.toType();444 const vector_ty = ty_pl.ty.toType();
...@@ -448,7 +454,7 @@ const Writer = struct {...@@ -448,7 +454,7 @@ const Writer = struct {
448 try s.writeAll("]");454 try s.writeAll("]");
449 }455 }
450456
451 fn writeUnionInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {457 fn writeUnionInit(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
452 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;458 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
453 const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data;459 const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data;
454460
...@@ -456,7 +462,7 @@ const Writer = struct {...@@ -456,7 +462,7 @@ const Writer = struct {
456 try w.writeOperand(s, inst, 0, extra.init);462 try w.writeOperand(s, inst, 0, extra.init);
457 }463 }
458464
459 fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {465 fn writeStructField(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
460 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;466 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
461 const extra = w.air.extraData(Air.StructField, ty_pl.payload).data;467 const extra = w.air.extraData(Air.StructField, ty_pl.payload).data;
462468
...@@ -464,7 +470,7 @@ const Writer = struct {...@@ -464,7 +470,7 @@ const Writer = struct {
464 try s.print(", {d}", .{extra.field_index});470 try s.print(", {d}", .{extra.field_index});
465 }471 }
466472
467 fn writeTyPlBin(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {473 fn writeTyPlBin(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
468 const data = w.air.instructions.items(.data);474 const data = w.air.instructions.items(.data);
469 const ty_pl = data[@intFromEnum(inst)].ty_pl;475 const ty_pl = data[@intFromEnum(inst)].ty_pl;
470 const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;476 const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -477,7 +483,7 @@ const Writer = struct {...@@ -477,7 +483,7 @@ const Writer = struct {
477 try w.writeOperand(s, inst, 1, extra.rhs);483 try w.writeOperand(s, inst, 1, extra.rhs);
478 }484 }
479485
480 fn writeCmpxchg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {486 fn writeCmpxchg(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
481 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;487 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
482 const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data;488 const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
483489
...@@ -491,7 +497,7 @@ const Writer = struct {...@@ -491,7 +497,7 @@ const Writer = struct {
491 });497 });
492 }498 }
493499
494 fn writeMulAdd(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {500 fn writeMulAdd(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
495 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;501 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
496 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;502 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
497503
...@@ -502,7 +508,7 @@ const Writer = struct {...@@ -502,7 +508,7 @@ const Writer = struct {
502 try w.writeOperand(s, inst, 2, pl_op.operand);508 try w.writeOperand(s, inst, 2, pl_op.operand);
503 }509 }
504510
505 fn writeShuffleOne(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {511 fn writeShuffleOne(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
506 const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst);512 const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst);
507 try w.writeType(s, unwrapped.result_ty);513 try w.writeType(s, unwrapped.result_ty);
508 try s.writeAll(", ");514 try s.writeAll(", ");
...@@ -512,13 +518,13 @@ const Writer = struct {...@@ -512,13 +518,13 @@ const Writer = struct {
512 if (mask_idx > 0) try s.writeAll(", ");518 if (mask_idx > 0) try s.writeAll(", ");
513 switch (mask_elem.unwrap()) {519 switch (mask_elem.unwrap()) {
514 .elem => |idx| try s.print("elem {d}", .{idx}),520 .elem => |idx| try s.print("elem {d}", .{idx}),
515 .value => |val| try s.print("val {}", .{Value.fromInterned(val).fmtValue(w.pt)}),521 .value => |val| try s.print("val {f}", .{Value.fromInterned(val).fmtValue(w.pt)}),
516 }522 }
517 }523 }
518 try s.writeByte(']');524 try s.writeByte(']');
519 }525 }
520526
521 fn writeShuffleTwo(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {527 fn writeShuffleTwo(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
522 const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst);528 const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst);
523 try w.writeType(s, unwrapped.result_ty);529 try w.writeType(s, unwrapped.result_ty);
524 try s.writeAll(", ");530 try s.writeAll(", ");
...@@ -537,7 +543,7 @@ const Writer = struct {...@@ -537,7 +543,7 @@ const Writer = struct {
537 try s.writeByte(']');543 try s.writeByte(']');
538 }544 }
539545
540 fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {546 fn writeSelect(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
541 const zcu = w.pt.zcu;547 const zcu = w.pt.zcu;
542 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;548 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
543 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;549 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
...@@ -552,14 +558,14 @@ const Writer = struct {...@@ -552,14 +558,14 @@ const Writer = struct {
552 try w.writeOperand(s, inst, 2, extra.rhs);558 try w.writeOperand(s, inst, 2, extra.rhs);
553 }559 }
554560
555 fn writeReduce(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {561 fn writeReduce(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
556 const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce;562 const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
557563
558 try w.writeOperand(s, inst, 0, reduce.operand);564 try w.writeOperand(s, inst, 0, reduce.operand);
559 try s.print(", {s}", .{@tagName(reduce.operation)});565 try s.print(", {s}", .{@tagName(reduce.operation)});
560 }566 }
561567
562 fn writeCmpVector(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {568 fn writeCmpVector(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
563 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;569 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
564 const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;570 const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;
565571
...@@ -569,7 +575,7 @@ const Writer = struct {...@@ -569,7 +575,7 @@ const Writer = struct {
569 try w.writeOperand(s, inst, 1, extra.rhs);575 try w.writeOperand(s, inst, 1, extra.rhs);
570 }576 }
571577
572 fn writeVectorStoreElem(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {578 fn writeVectorStoreElem(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
573 const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem;579 const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem;
574 const extra = w.air.extraData(Air.VectorCmp, data.payload).data;580 const extra = w.air.extraData(Air.VectorCmp, data.payload).data;
575581
...@@ -580,21 +586,21 @@ const Writer = struct {...@@ -580,21 +586,21 @@ const Writer = struct {
580 try w.writeOperand(s, inst, 2, extra.rhs);586 try w.writeOperand(s, inst, 2, extra.rhs);
581 }587 }
582588
583 fn writeRuntimeNavPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {589 fn writeRuntimeNavPtr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
584 const ip = &w.pt.zcu.intern_pool;590 const ip = &w.pt.zcu.intern_pool;
585 const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;591 const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;
586 try w.writeType(s, .fromInterned(ty_nav.ty));592 try w.writeType(s, .fromInterned(ty_nav.ty));
587 try s.print(", '{}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)});593 try s.print(", '{f}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)});
588 }594 }
589595
590 fn writeAtomicLoad(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {596 fn writeAtomicLoad(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
591 const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;597 const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;
592598
593 try w.writeOperand(s, inst, 0, atomic_load.ptr);599 try w.writeOperand(s, inst, 0, atomic_load.ptr);
594 try s.print(", {s}", .{@tagName(atomic_load.order)});600 try s.print(", {s}", .{@tagName(atomic_load.order)});
595 }601 }
596602
597 fn writePrefetch(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {603 fn writePrefetch(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
598 const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;604 const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
599605
600 try w.writeOperand(s, inst, 0, prefetch.ptr);606 try w.writeOperand(s, inst, 0, prefetch.ptr);
...@@ -605,10 +611,10 @@ const Writer = struct {...@@ -605,10 +611,10 @@ const Writer = struct {
605611
606 fn writeAtomicStore(612 fn writeAtomicStore(
607 w: *Writer,613 w: *Writer,
608 s: anytype,614 s: *std.io.Writer,
609 inst: Air.Inst.Index,615 inst: Air.Inst.Index,
610 order: std.builtin.AtomicOrder,616 order: std.builtin.AtomicOrder,
611 ) @TypeOf(s).Error!void {617 ) Error!void {
612 const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;618 const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
613 try w.writeOperand(s, inst, 0, bin_op.lhs);619 try w.writeOperand(s, inst, 0, bin_op.lhs);
614 try s.writeAll(", ");620 try s.writeAll(", ");
...@@ -616,7 +622,7 @@ const Writer = struct {...@@ -616,7 +622,7 @@ const Writer = struct {
616 try s.print(", {s}", .{@tagName(order)});622 try s.print(", {s}", .{@tagName(order)});
617 }623 }
618624
619 fn writeAtomicRmw(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {625 fn writeAtomicRmw(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
620 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;626 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
621 const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data;627 const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data;
622628
...@@ -626,7 +632,7 @@ const Writer = struct {...@@ -626,7 +632,7 @@ const Writer = struct {
626 try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) });632 try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) });
627 }633 }
628634
629 fn writeFieldParentPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {635 fn writeFieldParentPtr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
630 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;636 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
631 const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;637 const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
632638
...@@ -634,7 +640,7 @@ const Writer = struct {...@@ -634,7 +640,7 @@ const Writer = struct {
634 try s.print(", {d}", .{extra.field_index});640 try s.print(", {d}", .{extra.field_index});
635 }641 }
636642
637 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {643 fn writeAssembly(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
638 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;644 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
639 const extra = w.air.extraData(Air.Asm, ty_pl.payload);645 const extra = w.air.extraData(Air.Asm, ty_pl.payload);
640 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;646 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
...@@ -704,22 +710,22 @@ const Writer = struct {...@@ -704,22 +710,22 @@ const Writer = struct {
704 }710 }
705 }711 }
706 const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len];712 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)});713 try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)});
708 }714 }
709715
710 fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {716 fn writeDbgStmt(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
711 const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;717 const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
712 try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });718 try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
713 }719 }
714720
715 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {721 fn writeDbgVar(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
716 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;722 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
717 try w.writeOperand(s, inst, 0, pl_op.operand);723 try w.writeOperand(s, inst, 0, pl_op.operand);
718 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);724 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
719 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});725 try s.print(", \"{f}\"", .{std.zig.fmtString(name.toSlice(w.air))});
720 }726 }
721727
722 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {728 fn writeCall(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
723 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;729 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
724 const extra = w.air.extraData(Air.Call, pl_op.payload);730 const extra = w.air.extraData(Air.Call, pl_op.payload);
725 const args = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra.end..][0..extra.data.args_len]));731 const args = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra.end..][0..extra.data.args_len]));
...@@ -732,19 +738,19 @@ const Writer = struct {...@@ -732,19 +738,19 @@ const Writer = struct {
732 try s.writeAll("]");738 try s.writeAll("]");
733 }739 }
734740
735 fn writeBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {741 fn writeBr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
736 const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br;742 const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br;
737 try w.writeInstIndex(s, br.block_inst, false);743 try w.writeInstIndex(s, br.block_inst, false);
738 try s.writeAll(", ");744 try s.writeAll(", ");
739 try w.writeOperand(s, inst, 0, br.operand);745 try w.writeOperand(s, inst, 0, br.operand);
740 }746 }
741747
742 fn writeRepeat(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {748 fn writeRepeat(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
743 const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat;749 const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
744 try w.writeInstIndex(s, repeat.loop_inst, false);750 try w.writeInstIndex(s, repeat.loop_inst, false);
745 }751 }
746752
747 fn writeTry(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {753 fn writeTry(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
748 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;754 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
749 const extra = w.air.extraData(Air.Try, pl_op.payload);755 const extra = w.air.extraData(Air.Try, pl_op.payload);
750 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);756 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);
...@@ -760,25 +766,25 @@ const Writer = struct {...@@ -760,25 +766,25 @@ const Writer = struct {
760 w.indent += 2;766 w.indent += 2;
761767
762 if (liveness_condbr.else_deaths.len != 0) {768 if (liveness_condbr.else_deaths.len != 0) {
763 try s.writeByteNTimes(' ', w.indent);769 try s.splatByteAll(' ', w.indent);
764 for (liveness_condbr.else_deaths, 0..) |operand, i| {770 for (liveness_condbr.else_deaths, 0..) |operand, i| {
765 if (i != 0) try s.writeAll(" ");771 if (i != 0) try s.writeAll(" ");
766 try s.print("{}!", .{operand});772 try s.print("{f}!", .{operand});
767 }773 }
768 try s.writeAll("\n");774 try s.writeAll("\n");
769 }775 }
770 try w.writeBody(s, body);776 try w.writeBody(s, body);
771777
772 w.indent = old_indent;778 w.indent = old_indent;
773 try s.writeByteNTimes(' ', w.indent);779 try s.splatByteAll(' ', w.indent);
774 try s.writeAll("}");780 try s.writeAll("}");
775781
776 for (liveness_condbr.then_deaths) |operand| {782 for (liveness_condbr.then_deaths) |operand| {
777 try s.print(" {}!", .{operand});783 try s.print(" {f}!", .{operand});
778 }784 }
779 }785 }
780786
781 fn writeTryPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {787 fn writeTryPtr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
782 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;788 const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
783 const extra = w.air.extraData(Air.TryPtr, ty_pl.payload);789 const extra = w.air.extraData(Air.TryPtr, ty_pl.payload);
784 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);790 const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]);
...@@ -797,25 +803,25 @@ const Writer = struct {...@@ -797,25 +803,25 @@ const Writer = struct {
797 w.indent += 2;803 w.indent += 2;
798804
799 if (liveness_condbr.else_deaths.len != 0) {805 if (liveness_condbr.else_deaths.len != 0) {
800 try s.writeByteNTimes(' ', w.indent);806 try s.splatByteAll(' ', w.indent);
801 for (liveness_condbr.else_deaths, 0..) |operand, i| {807 for (liveness_condbr.else_deaths, 0..) |operand, i| {
802 if (i != 0) try s.writeAll(" ");808 if (i != 0) try s.writeAll(" ");
803 try s.print("{}!", .{operand});809 try s.print("{f}!", .{operand});
804 }810 }
805 try s.writeAll("\n");811 try s.writeAll("\n");
806 }812 }
807 try w.writeBody(s, body);813 try w.writeBody(s, body);
808814
809 w.indent = old_indent;815 w.indent = old_indent;
810 try s.writeByteNTimes(' ', w.indent);816 try s.splatByteAll(' ', w.indent);
811 try s.writeAll("}");817 try s.writeAll("}");
812818
813 for (liveness_condbr.then_deaths) |operand| {819 for (liveness_condbr.then_deaths) |operand| {
814 try s.print(" {}!", .{operand});820 try s.print(" {f}!", .{operand});
815 }821 }
816 }822 }
817823
818 fn writeCondBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {824 fn writeCondBr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
819 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;825 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
820 const extra = w.air.extraData(Air.CondBr, pl_op.payload);826 const extra = w.air.extraData(Air.CondBr, pl_op.payload);
821 const then_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.then_body_len]);827 const then_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.then_body_len]);
...@@ -839,16 +845,16 @@ const Writer = struct {...@@ -839,16 +845,16 @@ const Writer = struct {
839 w.indent += 2;845 w.indent += 2;
840846
841 if (liveness_condbr.then_deaths.len != 0) {847 if (liveness_condbr.then_deaths.len != 0) {
842 try s.writeByteNTimes(' ', w.indent);848 try s.splatByteAll(' ', w.indent);
843 for (liveness_condbr.then_deaths, 0..) |operand, i| {849 for (liveness_condbr.then_deaths, 0..) |operand, i| {
844 if (i != 0) try s.writeAll(" ");850 if (i != 0) try s.writeAll(" ");
845 try s.print("{}!", .{operand});851 try s.print("{f}!", .{operand});
846 }852 }
847 try s.writeAll("\n");853 try s.writeAll("\n");
848 }854 }
849855
850 try w.writeBody(s, then_body);856 try w.writeBody(s, then_body);
851 try s.writeByteNTimes(' ', old_indent);857 try s.splatByteAll(' ', old_indent);
852 try s.writeAll("},");858 try s.writeAll("},");
853 if (extra.data.branch_hints.false != .none) {859 if (extra.data.branch_hints.false != .none) {
854 try s.print(" {s}", .{@tagName(extra.data.branch_hints.false)});860 try s.print(" {s}", .{@tagName(extra.data.branch_hints.false)});
...@@ -859,10 +865,10 @@ const Writer = struct {...@@ -859,10 +865,10 @@ const Writer = struct {
859 try s.writeAll(" {\n");865 try s.writeAll(" {\n");
860866
861 if (liveness_condbr.else_deaths.len != 0) {867 if (liveness_condbr.else_deaths.len != 0) {
862 try s.writeByteNTimes(' ', w.indent);868 try s.splatByteAll(' ', w.indent);
863 for (liveness_condbr.else_deaths, 0..) |operand, i| {869 for (liveness_condbr.else_deaths, 0..) |operand, i| {
864 if (i != 0) try s.writeAll(" ");870 if (i != 0) try s.writeAll(" ");
865 try s.print("{}!", .{operand});871 try s.print("{f}!", .{operand});
866 }872 }
867 try s.writeAll("\n");873 try s.writeAll("\n");
868 }874 }
...@@ -870,11 +876,11 @@ const Writer = struct {...@@ -870,11 +876,11 @@ const Writer = struct {
870 try w.writeBody(s, else_body);876 try w.writeBody(s, else_body);
871 w.indent = old_indent;877 w.indent = old_indent;
872878
873 try s.writeByteNTimes(' ', old_indent);879 try s.splatByteAll(' ', old_indent);
874 try s.writeAll("}");880 try s.writeAll("}");
875 }881 }
876882
877 fn writeSwitchBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {883 fn writeSwitchBr(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
878 const switch_br = w.air.unwrapSwitch(inst);884 const switch_br = w.air.unwrapSwitch(inst);
879885
880 const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness|886 const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness|
...@@ -916,17 +922,17 @@ const Writer = struct {...@@ -916,17 +922,17 @@ const Writer = struct {
916922
917 const deaths = liveness.deaths[case.idx];923 const deaths = liveness.deaths[case.idx];
918 if (deaths.len != 0) {924 if (deaths.len != 0) {
919 try s.writeByteNTimes(' ', w.indent);925 try s.splatByteAll(' ', w.indent);
920 for (deaths, 0..) |operand, i| {926 for (deaths, 0..) |operand, i| {
921 if (i != 0) try s.writeAll(" ");927 if (i != 0) try s.writeAll(" ");
922 try s.print("{}!", .{operand});928 try s.print("{f}!", .{operand});
923 }929 }
924 try s.writeAll("\n");930 try s.writeAll("\n");
925 }931 }
926932
927 try w.writeBody(s, case.body);933 try w.writeBody(s, case.body);
928 w.indent -= 2;934 w.indent -= 2;
929 try s.writeByteNTimes(' ', w.indent);935 try s.splatByteAll(' ', w.indent);
930 try s.writeAll("}");936 try s.writeAll("}");
931 }937 }
932938
...@@ -942,47 +948,47 @@ const Writer = struct {...@@ -942,47 +948,47 @@ const Writer = struct {
942948
943 const deaths = liveness.deaths[liveness.deaths.len - 1];949 const deaths = liveness.deaths[liveness.deaths.len - 1];
944 if (deaths.len != 0) {950 if (deaths.len != 0) {
945 try s.writeByteNTimes(' ', w.indent);951 try s.splatByteAll(' ', w.indent);
946 for (deaths, 0..) |operand, i| {952 for (deaths, 0..) |operand, i| {
947 if (i != 0) try s.writeAll(" ");953 if (i != 0) try s.writeAll(" ");
948 try s.print("{}!", .{operand});954 try s.print("{f}!", .{operand});
949 }955 }
950 try s.writeAll("\n");956 try s.writeAll("\n");
951 }957 }
952958
953 try w.writeBody(s, else_body);959 try w.writeBody(s, else_body);
954 w.indent -= 2;960 w.indent -= 2;
955 try s.writeByteNTimes(' ', w.indent);961 try s.splatByteAll(' ', w.indent);
956 try s.writeAll("}");962 try s.writeAll("}");
957 }963 }
958964
959 try s.writeAll("\n");965 try s.writeAll("\n");
960 try s.writeByteNTimes(' ', old_indent);966 try s.splatByteAll(' ', old_indent);
961 }967 }
962968
963 fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {969 fn writeWasmMemorySize(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
964 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;970 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
965 try s.print("{d}", .{pl_op.payload});971 try s.print("{d}", .{pl_op.payload});
966 }972 }
967973
968 fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {974 fn writeWasmMemoryGrow(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
969 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;975 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
970 try s.print("{d}, ", .{pl_op.payload});976 try s.print("{d}, ", .{pl_op.payload});
971 try w.writeOperand(s, inst, 0, pl_op.operand);977 try w.writeOperand(s, inst, 0, pl_op.operand);
972 }978 }
973979
974 fn writeWorkDimension(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {980 fn writeWorkDimension(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void {
975 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;981 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
976 try s.print("{d}", .{pl_op.payload});982 try s.print("{d}", .{pl_op.payload});
977 }983 }
978984
979 fn writeOperand(985 fn writeOperand(
980 w: *Writer,986 w: *Writer,
981 s: anytype,987 s: *std.io.Writer,
982 inst: Air.Inst.Index,988 inst: Air.Inst.Index,
983 op_index: usize,989 op_index: usize,
984 operand: Air.Inst.Ref,990 operand: Air.Inst.Ref,
985 ) @TypeOf(s).Error!void {991 ) Error!void {
986 const small_tomb_bits = Air.Liveness.bpi - 1;992 const small_tomb_bits = Air.Liveness.bpi - 1;
987 const dies = if (w.liveness) |liveness| blk: {993 const dies = if (w.liveness) |liveness| blk: {
988 if (op_index < small_tomb_bits)994 if (op_index < small_tomb_bits)
...@@ -1004,16 +1010,16 @@ const Writer = struct {...@@ -1004,16 +1010,16 @@ const Writer = struct {
10041010
1005 fn writeInstRef(1011 fn writeInstRef(
1006 w: *Writer,1012 w: *Writer,
1007 s: anytype,1013 s: *std.io.Writer,
1008 operand: Air.Inst.Ref,1014 operand: Air.Inst.Ref,
1009 dies: bool,1015 dies: bool,
1010 ) @TypeOf(s).Error!void {1016 ) Error!void {
1011 if (@intFromEnum(operand) < InternPool.static_len) {1017 if (@intFromEnum(operand) < InternPool.static_len) {
1012 return s.print("@{}", .{operand});1018 return s.print("@{}", .{operand});
1013 } else if (operand.toInterned()) |ip_index| {1019 } else if (operand.toInterned()) |ip_index| {
1014 const pt = w.pt;1020 const pt = w.pt;
1015 const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf());1021 const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf());
1016 try s.print("<{}, {}>", .{1022 try s.print("<{f}, {f}>", .{
1017 ty.fmt(pt),1023 ty.fmt(pt),
1018 Value.fromInterned(ip_index).fmtValue(pt),1024 Value.fromInterned(ip_index).fmtValue(pt),
1019 });1025 });
...@@ -1024,12 +1030,12 @@ const Writer = struct {...@@ -1024,12 +1030,12 @@ const Writer = struct {
10241030
1025 fn writeInstIndex(1031 fn writeInstIndex(
1026 w: *Writer,1032 w: *Writer,
1027 s: anytype,1033 s: *std.io.Writer,
1028 inst: Air.Inst.Index,1034 inst: Air.Inst.Index,
1029 dies: bool,1035 dies: bool,
1030 ) @TypeOf(s).Error!void {1036 ) Error!void {
1031 _ = w;1037 _ = w;
1032 try s.print("{}", .{inst});1038 try s.print("{f}", .{inst});
1033 if (dies) try s.writeByte('!');1039 if (dies) try s.writeByte('!');
1034 }1040 }
10351041
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 = {f},
204 \\ .max = {c},204 \\ .max = {f},
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}' 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+40-45
...@@ -399,9 +399,7 @@ pub const Path = struct {...@@ -399,9 +399,7 @@ pub const Path = struct {
399 const Formatter = struct {399 const Formatter = struct {
400 p: Path,400 p: Path,
401 comp: *Compilation,401 comp: *Compilation,
402 pub fn format(f: Formatter, comptime unused_fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void {402 pub fn format(f: Formatter, w: *std.io.Writer) std.io.Writer.Error!void {
403 comptime assert(unused_fmt.len == 0);
404 _ = options;
405 const root_path: []const u8 = switch (f.p.root) {403 const root_path: []const u8 = switch (f.p.root) {
406 .zig_lib => f.comp.dirs.zig_lib.path orelse ".",404 .zig_lib => f.comp.dirs.zig_lib.path orelse ".",
407 .global_cache => f.comp.dirs.global_cache.path orelse ".",405 .global_cache => f.comp.dirs.global_cache.path orelse ".",
...@@ -730,10 +728,10 @@ pub const Directories = struct {...@@ -730,10 +728,10 @@ pub const Directories = struct {
730 };728 };
731729
732 if (std.mem.eql(u8, zig_lib.path orelse "", global_cache.path orelse "")) {730 if (std.mem.eql(u8, zig_lib.path orelse "", global_cache.path orelse "")) {
733 fatal("zig lib directory '{}' cannot be equal to global cache directory '{}'", .{ zig_lib, global_cache });731 fatal("zig lib directory '{f}' cannot be equal to global cache directory '{f}'", .{ zig_lib, global_cache });
734 }732 }
735 if (std.mem.eql(u8, zig_lib.path orelse "", local_cache.path orelse "")) {733 if (std.mem.eql(u8, zig_lib.path orelse "", local_cache.path orelse "")) {
736 fatal("zig lib directory '{}' cannot be equal to local cache directory '{}'", .{ zig_lib, local_cache });734 fatal("zig lib directory '{f}' cannot be equal to local cache directory '{f}'", .{ zig_lib, local_cache });
737 }735 }
738736
739 return .{737 return .{
...@@ -1001,7 +999,7 @@ pub const CObject = struct {...@@ -1001,7 +999,7 @@ pub const CObject = struct {
1001999
1002 var line = std.ArrayList(u8).init(eb.gpa);1000 var line = std.ArrayList(u8).init(eb.gpa);
1003 defer line.deinit();1001 defer line.deinit();
1004 file.reader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;1002 file.deprecatedReader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;
10051003
1006 break :source_line try eb.addString(line.items);1004 break :source_line try eb.addString(line.items);
1007 };1005 };
...@@ -1069,7 +1067,7 @@ pub const CObject = struct {...@@ -1069,7 +1067,7 @@ pub const CObject = struct {
10691067
1070 const file = try std.fs.cwd().openFile(path, .{});1068 const file = try std.fs.cwd().openFile(path, .{});
1071 defer file.close();1069 defer file.close();
1072 var br = std.io.bufferedReader(file.reader());1070 var br = std.io.bufferedReader(file.deprecatedReader());
1073 const reader = br.reader();1071 const reader = br.reader();
1074 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });1072 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });
1075 defer bc.deinit();1073 defer bc.deinit();
...@@ -1875,7 +1873,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1875,7 +1873,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1875 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {1873 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
1876 std.debug.lockStdErr();1874 std.debug.lockStdErr();
1877 defer std.debug.unlockStdErr();1875 defer std.debug.unlockStdErr();
1878 const stderr = std.io.getStdErr().writer();1876 const stderr = std.fs.File.stderr().deprecatedWriter();
1879 nosuspend {1877 nosuspend {
1880 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;1878 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1881 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;1879 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
...@@ -2689,7 +2687,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2689,7 +2687,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2689 const is_hit = man.hit() catch |err| switch (err) {2687 const is_hit = man.hit() catch |err| switch (err) {
2690 error.CacheCheckFailed => switch (man.diagnostic) {2688 error.CacheCheckFailed => switch (man.diagnostic) {
2691 .none => unreachable,2689 .none => unreachable,
2692 .manifest_create, .manifest_read, .manifest_lock, .manifest_seek => |e| return comp.setMiscFailure(2690 .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure(
2693 .check_whole_cache,2691 .check_whole_cache,
2694 "failed to check cache: {s} {s}",2692 "failed to check cache: {s} {s}",
2695 .{ @tagName(man.diagnostic), @errorName(e) },2693 .{ @tagName(man.diagnostic), @errorName(e) },
...@@ -2699,7 +2697,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2699,7 +2697,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2699 const prefix = man.cache.prefixes()[pp.prefix];2697 const prefix = man.cache.prefixes()[pp.prefix];
2700 return comp.setMiscFailure(2698 return comp.setMiscFailure(
2701 .check_whole_cache,2699 .check_whole_cache,
2702 "failed to check cache: '{}{s}' {s} {s}",2700 "failed to check cache: '{f}{s}' {s} {s}",
2703 .{ prefix, pp.sub_path, @tagName(man.diagnostic), @errorName(op.err) },2701 .{ prefix, pp.sub_path, @tagName(man.diagnostic), @errorName(op.err) },
2704 );2702 );
2705 },2703 },
...@@ -2916,7 +2914,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2916,7 +2914,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2916 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {2914 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
2917 return comp.setMiscFailure(2915 return comp.setMiscFailure(
2918 .rename_results,2916 .rename_results,
2919 "failed to rename compilation results ('{}{s}') into local cache ('{}{s}'): {s}",2917 "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {s}",
2920 .{2918 .{
2921 comp.dirs.local_cache, tmp_dir_sub_path,2919 comp.dirs.local_cache, tmp_dir_sub_path,
2922 comp.dirs.local_cache, o_sub_path,2920 comp.dirs.local_cache, o_sub_path,
...@@ -2983,7 +2981,7 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat...@@ -2983,7 +2981,7 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat
2983 break @intCast(i);2981 break @intCast(i);
2984 }2982 }
2985 } else std.debug.panic(2983 } else std.debug.panic(
2986 "missing prefix directory '{s}' ('{}') for '{s}'",2984 "missing prefix directory '{s}' ('{f}') for '{s}'",
2987 .{ @tagName(path.root), want_prefix_dir, path.sub_path },2985 .{ @tagName(path.root), want_prefix_dir, path.sub_path },
2988 );2986 );
29892987
...@@ -3322,7 +3320,7 @@ fn emitFromCObject(...@@ -3322,7 +3320,7 @@ fn emitFromCObject(
3322 emit_path.root_dir.handle,3320 emit_path.root_dir.handle,
3323 emit_path.sub_path,3321 emit_path.sub_path,
3324 .{},3322 .{},
3325 ) catch |err| log.err("unable to copy '{}' to '{}': {s}", .{3323 ) catch |err| log.err("unable to copy '{f}' to '{f}': {s}", .{
3326 src_path,3324 src_path,
3327 emit_path,3325 emit_path,
3328 @errorName(err),3326 @errorName(err),
...@@ -3670,7 +3668,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3670,7 +3668,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3670 .illegal_zig_import => try bundle.addString("this compiler implementation does not allow importing files from this directory"),3668 .illegal_zig_import => try bundle.addString("this compiler implementation does not allow importing files from this directory"),
3671 },3669 },
3672 .src_loc = try bundle.addSourceLocation(.{3670 .src_loc = try bundle.addSourceLocation(.{
3673 .src_path = try bundle.printString("{}", .{file.path.fmt(comp)}),3671 .src_path = try bundle.printString("{f}", .{file.path.fmt(comp)}),
3674 .span_start = start,3672 .span_start = start,
3675 .span_main = start,3673 .span_main = start,
3676 .span_end = @intCast(end),3674 .span_end = @intCast(end),
...@@ -3717,7 +3715,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3717,7 +3715,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3717 assert(!is_retryable);3715 assert(!is_retryable);
3718 // AstGen/ZoirGen succeeded with errors. Note that this may include AST errors.3716 // AstGen/ZoirGen succeeded with errors. Note that this may include AST errors.
3719 _ = try file.getTree(zcu); // Tree must be loaded.3717 _ = try file.getTree(zcu); // Tree must be loaded.
3720 const path = try std.fmt.allocPrint(gpa, "{}", .{file.path.fmt(comp)});3718 const path = try std.fmt.allocPrint(gpa, "{f}", .{file.path.fmt(comp)});
3721 defer gpa.free(path);3719 defer gpa.free(path);
3722 if (file.zir != null) {3720 if (file.zir != null) {
3723 try bundle.addZirErrorMessages(file.zir.?, file.tree.?, file.source.?, path);3721 try bundle.addZirErrorMessages(file.zir.?, file.tree.?, file.source.?, path);
...@@ -3772,9 +3770,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3772,9 +3770,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3772 if (!refs.contains(anal_unit)) continue;3770 if (!refs.contains(anal_unit)) continue;
3773 }3771 }
37743772
3775 std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{3773 std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{f}'", .{
3776 error_msg.msg,3774 error_msg.msg, zcu.fmtAnalUnit(anal_unit),
3777 zcu.fmtAnalUnit(anal_unit),
3778 });3775 });
37793776
3780 try addModuleErrorMsg(zcu, &bundle, error_msg.*, added_any_analysis_error);3777 try addModuleErrorMsg(zcu, &bundle, error_msg.*, added_any_analysis_error);
...@@ -3932,11 +3929,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3932,11 +3929,11 @@ 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.3929 // 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.3930 // However, we haven't reported any such error.
3934 // This is a compiler bug.3931 // This is a compiler bug.
3935 const stderr = std.io.getStdErr().writer();3932 const stderr = std.fs.File.stderr().deprecatedWriter();
3936 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");3933 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3937 try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});3934 try stderr.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
3938 while (ref) |r| {3935 while (ref) |r| {
3939 try stderr.print("referenced by: {}{s}\n", .{3936 try stderr.print("referenced by: {f}{s}\n", .{
3940 zcu.fmtAnalUnit(r.referencer),3937 zcu.fmtAnalUnit(r.referencer),
3941 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",3938 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
3942 });3939 });
...@@ -4035,7 +4032,7 @@ pub fn addModuleErrorMsg(...@@ -4035,7 +4032,7 @@ pub fn addModuleErrorMsg(
4035 const err_src_loc = module_err_msg.src_loc.upgrade(zcu);4032 const err_src_loc = module_err_msg.src_loc.upgrade(zcu);
4036 const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| {4033 const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| {
4037 try eb.addRootErrorMessage(.{4034 try eb.addRootErrorMessage(.{
4038 .msg = try eb.printString("unable to load '{}': {s}", .{4035 .msg = try eb.printString("unable to load '{f}': {s}", .{
4039 err_src_loc.file_scope.path.fmt(zcu.comp), @errorName(err),4036 err_src_loc.file_scope.path.fmt(zcu.comp), @errorName(err),
4040 }),4037 }),
4041 });4038 });
...@@ -4098,7 +4095,7 @@ pub fn addModuleErrorMsg(...@@ -4098,7 +4095,7 @@ pub fn addModuleErrorMsg(
4098 }4095 }
40994096
4100 const src_loc = try eb.addSourceLocation(.{4097 const src_loc = try eb.addSourceLocation(.{
4101 .src_path = try eb.printString("{}", .{err_src_loc.file_scope.path.fmt(zcu.comp)}),4098 .src_path = try eb.printString("{f}", .{err_src_loc.file_scope.path.fmt(zcu.comp)}),
4102 .span_start = err_span.start,4099 .span_start = err_span.start,
4103 .span_main = err_span.main,4100 .span_main = err_span.main,
4104 .span_end = err_span.end,4101 .span_end = err_span.end,
...@@ -4130,7 +4127,7 @@ pub fn addModuleErrorMsg(...@@ -4130,7 +4127,7 @@ pub fn addModuleErrorMsg(
4130 const gop = try notes.getOrPutContext(gpa, .{4127 const gop = try notes.getOrPutContext(gpa, .{
4131 .msg = try eb.addString(module_note.msg),4128 .msg = try eb.addString(module_note.msg),
4132 .src_loc = try eb.addSourceLocation(.{4129 .src_loc = try eb.addSourceLocation(.{
4133 .src_path = try eb.printString("{}", .{note_src_loc.file_scope.path.fmt(zcu.comp)}),4130 .src_path = try eb.printString("{f}", .{note_src_loc.file_scope.path.fmt(zcu.comp)}),
4134 .span_start = span.start,4131 .span_start = span.start,
4135 .span_main = span.main,4132 .span_main = span.main,
4136 .span_end = span.end,4133 .span_end = span.end,
...@@ -4175,7 +4172,7 @@ fn addReferenceTraceFrame(...@@ -4175,7 +4172,7 @@ fn addReferenceTraceFrame(
4175 try ref_traces.append(gpa, .{4172 try ref_traces.append(gpa, .{
4176 .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),4173 .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),
4177 .src_loc = try eb.addSourceLocation(.{4174 .src_loc = try eb.addSourceLocation(.{
4178 .src_path = try eb.printString("{}", .{src.file_scope.path.fmt(zcu.comp)}),4175 .src_path = try eb.printString("{f}", .{src.file_scope.path.fmt(zcu.comp)}),
4179 .span_start = span.start,4176 .span_start = span.start,
4180 .span_main = span.main,4177 .span_main = span.main,
4181 .span_end = span.end,4178 .span_end = span.end,
...@@ -4836,7 +4833,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4836,7 +4833,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4836 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {4833 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
4837 return comp.lockAndSetMiscFailure(4834 return comp.lockAndSetMiscFailure(
4838 .docs_copy,4835 .docs_copy,
4839 "unable to create output directory '{}': {s}",4836 "unable to create output directory '{f}': {s}",
4840 .{ docs_path, @errorName(err) },4837 .{ docs_path, @errorName(err) },
4841 );4838 );
4842 };4839 };
...@@ -4856,7 +4853,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4856,7 +4853,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4856 var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| {4853 var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| {
4857 return comp.lockAndSetMiscFailure(4854 return comp.lockAndSetMiscFailure(
4858 .docs_copy,4855 .docs_copy,
4859 "unable to create '{}/sources.tar': {s}",4856 "unable to create '{f}/sources.tar': {s}",
4860 .{ docs_path, @errorName(err) },4857 .{ docs_path, @errorName(err) },
4861 );4858 );
4862 };4859 };
...@@ -4885,7 +4882,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4885,7 +4882,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4885 const root_dir, const sub_path = root.openInfo(comp.dirs);4882 const root_dir, const sub_path = root.openInfo(comp.dirs);
4886 break :d root_dir.openDir(sub_path, .{ .iterate = true });4883 break :d root_dir.openDir(sub_path, .{ .iterate = true });
4887 } catch |err| {4884 } catch |err| {
4888 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{}': {s}", .{4885 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{f}': {s}", .{
4889 root.fmt(comp), @errorName(err),4886 root.fmt(comp), @errorName(err),
4890 });4887 });
4891 };4888 };
...@@ -4894,7 +4891,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4894,7 +4891,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4894 var walker = try mod_dir.walk(comp.gpa);4891 var walker = try mod_dir.walk(comp.gpa);
4895 defer walker.deinit();4892 defer walker.deinit();
48964893
4897 var archiver = std.tar.writer(tar_file.writer().any());4894 var archiver = std.tar.writer(tar_file.deprecatedWriter().any());
4898 archiver.prefix = name;4895 archiver.prefix = name;
48994896
4900 while (try walker.next()) |entry| {4897 while (try walker.next()) |entry| {
...@@ -4907,13 +4904,13 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4907,13 +4904,13 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4907 else => continue,4904 else => continue,
4908 }4905 }
4909 var file = mod_dir.openFile(entry.path, .{}) catch |err| {4906 var file = mod_dir.openFile(entry.path, .{}) catch |err| {
4910 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open '{}{s}': {s}", .{4907 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open '{f}{s}': {s}", .{
4911 root.fmt(comp), entry.path, @errorName(err),4908 root.fmt(comp), entry.path, @errorName(err),
4912 });4909 });
4913 };4910 };
4914 defer file.close();4911 defer file.close();
4915 archiver.writeFile(entry.path, file) catch |err| {4912 archiver.writeFile(entry.path, file) catch |err| {
4916 return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive '{}{s}': {s}", .{4913 return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive '{f}{s}': {s}", .{
4917 root.fmt(comp), entry.path, @errorName(err),4914 root.fmt(comp), entry.path, @errorName(err),
4918 });4915 });
4919 };4916 };
...@@ -5043,7 +5040,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -5043,7 +5040,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
5043 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {5040 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
5044 return comp.lockAndSetMiscFailure(5041 return comp.lockAndSetMiscFailure(
5045 .docs_copy,5042 .docs_copy,
5046 "unable to create output directory '{}': {s}",5043 "unable to create output directory '{f}': {s}",
5047 .{ docs_path, @errorName(err) },5044 .{ docs_path, @errorName(err) },
5048 );5045 );
5049 };5046 };
...@@ -5055,10 +5052,8 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -5055,10 +5052,8 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
5055 "main.wasm",5052 "main.wasm",
5056 .{},5053 .{},
5057 ) catch |err| {5054 ) catch |err| {
5058 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}' to '{}': {s}", .{5055 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{f}' to '{f}': {s}", .{
5059 crt_file.full_object_path,5056 crt_file.full_object_path, docs_path, @errorName(err),
5060 docs_path,
5061 @errorName(err),
5062 });5057 });
5063 };5058 };
5064}5059}
...@@ -5131,7 +5126,7 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {...@@ -5131,7 +5126,7 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {
5131 defer comp.mutex.unlock();5126 defer comp.mutex.unlock();
5132 comp.setMiscFailure(5127 comp.setMiscFailure(
5133 .write_builtin_zig,5128 .write_builtin_zig,
5134 "unable to write '{}': {s}",5129 "unable to write '{f}': {s}",
5135 .{ file.path.fmt(comp), @errorName(err) },5130 .{ file.path.fmt(comp), @errorName(err) },
5136 );5131 );
5137 };5132 };
...@@ -5852,7 +5847,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5852,7 +5847,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
58525847
5853 try child.spawn();5848 try child.spawn();
58545849
5855 const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));5850 const stderr = try child.stderr.?.deprecatedReader().readAllAlloc(arena, std.math.maxInt(usize));
58565851
5857 const term = child.wait() catch |err| {5852 const term = child.wait() catch |err| {
5858 return comp.failCObj(c_object, "failed to spawn zig clang {s}: {s}", .{ argv.items[0], @errorName(err) });5853 return comp.failCObj(c_object, "failed to spawn zig clang {s}: {s}", .{ argv.items[0], @errorName(err) });
...@@ -6012,9 +6007,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6012,9 +6007,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
60126007
6013 // In .rc files, a " within a quoted string is escaped as ""6008 // In .rc files, a " within a quoted string is escaped as ""
6014 const fmtRcEscape = struct {6009 const fmtRcEscape = struct {
6015 fn formatRcEscape(bytes: []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {6010 fn formatRcEscape(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
6016 _ = fmt;
6017 _ = options;
6018 for (bytes) |byte| switch (byte) {6011 for (bytes) |byte| switch (byte) {
6019 '"' => try writer.writeAll("\"\""),6012 '"' => try writer.writeAll("\"\""),
6020 '\\' => try writer.writeAll("\\\\"),6013 '\\' => try writer.writeAll("\\\\"),
...@@ -6022,7 +6015,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6022,7 +6015,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6022 };6015 };
6023 }6016 }
60246017
6025 pub fn fmtRcEscape(bytes: []const u8) std.fmt.Formatter(formatRcEscape) {6018 pub fn fmtRcEscape(bytes: []const u8) std.fmt.Formatter([]const u8, formatRcEscape) {
6026 return .{ .data = bytes };6019 return .{ .data = bytes };
6027 }6020 }
6028 }.fmtRcEscape;6021 }.fmtRcEscape;
...@@ -6036,7 +6029,9 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6036,7 +6029,9 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6036 // 24 is RT_MANIFEST6029 // 24 is RT_MANIFEST
6037 const resource_type = 24;6030 const resource_type = 24;
60386031
6039 const input = try std.fmt.allocPrint(arena, "{} {} \"{s}\"", .{ resource_id, resource_type, fmtRcEscape(src_path) });6032 const input = try std.fmt.allocPrint(arena, "{d} {d} \"{f}\"", .{
6033 resource_id, resource_type, fmtRcEscape(src_path),
6034 });
60406035
6041 try o_dir.writeFile(.{ .sub_path = rc_basename, .data = input });6036 try o_dir.writeFile(.{ .sub_path = rc_basename, .data = input });
60426037
...@@ -6251,7 +6246,7 @@ fn spawnZigRc(...@@ -6251,7 +6246,7 @@ fn spawnZigRc(
6251 }6246 }
62526247
6253 // Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace)6248 // Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace)
6254 const stderr_reader = child.stderr.?.reader();6249 const stderr_reader = child.stderr.?.deprecatedReader();
6255 const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);6250 const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);
62566251
6257 const term = child.wait() catch |err| {6252 const term = child.wait() catch |err| {
...@@ -7214,7 +7209,7 @@ pub fn lockAndSetMiscFailure(...@@ -7214,7 +7209,7 @@ pub fn lockAndSetMiscFailure(
7214pub fn dump_argv(argv: []const []const u8) void {7209pub fn dump_argv(argv: []const []const u8) void {
7215 std.debug.lockStdErr();7210 std.debug.lockStdErr();
7216 defer std.debug.unlockStdErr();7211 defer std.debug.unlockStdErr();
7217 const stderr = std.io.getStdErr().writer();7212 const stderr = std.fs.File.stderr().deprecatedWriter();
7218 for (argv[0 .. argv.len - 1]) |arg| {7213 for (argv[0 .. argv.len - 1]) |arg| {
7219 nosuspend stderr.print("{s} ", .{arg}) catch return;7214 nosuspend stderr.print("{s} ", .{arg}) catch return;
7220 }7215 }
src/IncrementalDebugServer.zig+5-5
...@@ -142,8 +142,8 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons...@@ -142,8 +142,8 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons
142 const create_gen = zcu.incremental_debug_state.navs.get(nav_index) orelse return w.writeAll("unknown nav index");142 const create_gen = zcu.incremental_debug_state.navs.get(nav_index) orelse return w.writeAll("unknown nav index");
143 const nav = ip.getNav(nav_index);143 const nav = ip.getNav(nav_index);
144 try w.print(144 try w.print(
145 \\name: '{}'145 \\name: '{f}'
146 \\fqn: '{}'146 \\fqn: '{f}'
147 \\status: {s}147 \\status: {s}
148 \\created on generation: {d}148 \\created on generation: {d}
149 \\149 \\
...@@ -234,7 +234,7 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons...@@ -234,7 +234,7 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons
234 for (unit_info.deps.items, 0..) |dependee, i| {234 for (unit_info.deps.items, 0..) |dependee, i| {
235 try w.print("[{d}] ", .{i});235 try w.print("[{d}] ", .{i});
236 switch (dependee) {236 switch (dependee) {
237 .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{}", .{zcu.fmtDependee(dependee)}),237 .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}),
238 .nav_val, .nav_ty => |nav| try w.print("{s} {d}", .{ @tagName(dependee), @intFromEnum(nav) }),238 .nav_val, .nav_ty => |nav| try w.print("{s} {d}", .{ @tagName(dependee), @intFromEnum(nav) }),
239 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {239 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
240 .struct_type, .union_type, .enum_type => try w.print("type {d}", .{@intFromEnum(ip_index)}),240 .struct_type, .union_type, .enum_type => try w.print("type {d}", .{@intFromEnum(ip_index)}),
...@@ -260,7 +260,7 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons...@@ -260,7 +260,7 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons
260 const ip_index: InternPool.Index = @enumFromInt(parseIndex(arg_str) orelse return w.writeAll("malformed ip index"));260 const ip_index: InternPool.Index = @enumFromInt(parseIndex(arg_str) orelse return w.writeAll("malformed ip index"));
261 const create_gen = zcu.incremental_debug_state.types.get(ip_index) orelse return w.writeAll("unknown type");261 const create_gen = zcu.incremental_debug_state.types.get(ip_index) orelse return w.writeAll("unknown type");
262 try w.print(262 try w.print(
263 \\name: '{}'263 \\name: '{f}'
264 \\created on generation: {d}264 \\created on generation: {d}
265 \\265 \\
266 , .{266 , .{
...@@ -365,7 +365,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void {...@@ -365,7 +365,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void {
365 .union_type,365 .union_type,
366 .enum_type,366 .enum_type,
367 .opaque_type,367 .opaque_type,
368 => try w.print("{}[{d}]", .{ ty.containerTypeName(ip).fmt(ip), @intFromEnum(ty.toIntern()) }),368 => try w.print("{f}[{d}]", .{ ty.containerTypeName(ip).fmt(ip), @intFromEnum(ty.toIntern()) }),
369369
370 else => unreachable,370 else => unreachable,
371 }371 }
src/InternPool.zig+30-31
...@@ -1881,23 +1881,23 @@ pub const NullTerminatedString = enum(u32) {...@@ -1881,23 +1881,23 @@ pub const NullTerminatedString = enum(u32) {
1881 const FormatData = struct {1881 const FormatData = struct {
1882 string: NullTerminatedString,1882 string: NullTerminatedString,
1883 ip: *const InternPool,1883 ip: *const InternPool,
1884 id: bool,
1884 };1885 };
1885 fn format(1886 fn format(data: FormatData, writer: *std.io.Writer) std.io.Writer.Error!void {
1886 data: FormatData,
1887 comptime specifier: []const u8,
1888 _: std.fmt.FormatOptions,
1889 writer: anytype,
1890 ) @TypeOf(writer).Error!void {
1891 const slice = data.string.toSlice(data.ip);1887 const slice = data.string.toSlice(data.ip);
1892 if (comptime std.mem.eql(u8, specifier, "")) {1888 if (!data.id) {
1893 try writer.writeAll(slice);1889 try writer.writeAll(slice);
1894 } else if (comptime std.mem.eql(u8, specifier, "i")) {1890 } else {
1895 try writer.print("{p}", .{std.zig.fmtId(slice)});1891 try writer.print("{f}", .{std.zig.fmtIdP(slice)});
1896 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");1892 }
1893 }
1894
1895 pub fn fmt(string: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(FormatData, format) {
1896 return .{ .data = .{ .string = string, .ip = ip, .id = false } };
1897 }1897 }
18981898
1899 pub fn fmt(string: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(format) {1899 pub fn fmtId(string: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(FormatData, format) {
1900 return .{ .data = .{ .string = string, .ip = ip } };1900 return .{ .data = .{ .string = string, .ip = ip, .id = true } };
1901 }1901 }
19021902
1903 const debug_state = InternPool.debug_state;1903 const debug_state = InternPool.debug_state;
...@@ -9750,7 +9750,7 @@ fn finishFuncInstance(...@@ -9750,7 +9750,7 @@ fn finishFuncInstance(
9750 const fn_namespace = fn_owner_nav.analysis.?.namespace;9750 const fn_namespace = fn_owner_nav.analysis.?.namespace;
97519751
9752 // TODO: improve this name9752 // TODO: improve this name
9753 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{9753 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{f}__anon_{d}", .{
9754 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),9754 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
9755 }, .no_embedded_nulls);9755 }, .no_embedded_nulls);
9756 const nav_index = try ip.createNav(gpa, tid, .{9756 const nav_index = try ip.createNav(gpa, tid, .{
...@@ -11259,8 +11259,9 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -11259,8 +11259,9 @@ 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.io.getStdErr().writer());11262 var buffer: [4096]u8 = undefined;
11263 const w = bw.writer();11263 const stderr_bw = std.debug.lockStderrWriter(&buffer);
11264 defer std.debug.unlockStderrWriter();
11264 for (ip.locals, 0..) |*local, tid| {11265 for (ip.locals, 0..) |*local, tid| {
11265 const items = local.shared.items.view();11266 const items = local.shared.items.view();
11266 for (11267 for (
...@@ -11269,12 +11270,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -11269,12 +11270,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11269 0..,11270 0..,
11270 ) |tag, data, index| {11271 ) |tag, data, index| {
11271 const i = Index.Unwrapped.wrap(.{ .tid = @enumFromInt(tid), .index = @intCast(index) }, ip);11272 const i = Index.Unwrapped.wrap(.{ .tid = @enumFromInt(tid), .index = @intCast(index) }, ip);
11272 try w.print("${d} = {s}(", .{ i, @tagName(tag) });11273 try stderr_bw.print("${d} = {s}(", .{ i, @tagName(tag) });
11273 switch (tag) {11274 switch (tag) {
11274 .removed => {},11275 .removed => {},
1127511276
11276 .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),11277 .simple_type => try stderr_bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}),
11277 .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),11278 .simple_value => try stderr_bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}),
1127811279
11279 .type_int_signed,11280 .type_int_signed,
11280 .type_int_unsigned,11281 .type_int_unsigned,
...@@ -11347,17 +11348,16 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -11347,17 +11348,16 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11347 .func_coerced,11348 .func_coerced,
11348 .union_value,11349 .union_value,
11349 .memoized_call,11350 .memoized_call,
11350 => try w.print("{d}", .{data}),11351 => try stderr_bw.print("{d}", .{data}),
1135111352
11352 .opt_null,11353 .opt_null,
11353 .type_slice,11354 .type_slice,
11354 .only_possible_value,11355 .only_possible_value,
11355 => try w.print("${d}", .{data}),11356 => try stderr_bw.print("${d}", .{data}),
11356 }11357 }
11357 try w.writeAll(")\n");11358 try stderr_bw.writeAll(")\n");
11358 }11359 }
11359 }11360 }
11360 try bw.flush();
11361}11361}
1136211362
11363pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {11363pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {
...@@ -11369,9 +11369,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11369,9 +11369,6 @@ 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.io.getStdErr().writer());
11373 const w = bw.writer();
11374
11375 var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .empty;11372 var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .empty;
11376 for (ip.locals, 0..) |*local, tid| {11373 for (ip.locals, 0..) |*local, tid| {
11377 const items = local.shared.items.view().slice();11374 const items = local.shared.items.view().slice();
...@@ -11394,6 +11391,10 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11394,6 +11391,10 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11394 }11391 }
11395 }11392 }
1139611393
11394 var buffer: [4096]u8 = undefined;
11395 const stderr_bw = std.debug.lockStderrWriter(&buffer);
11396 defer std.debug.unlockStderrWriter();
11397
11397 const SortContext = struct {11398 const SortContext = struct {
11398 values: []std.ArrayListUnmanaged(Index),11399 values: []std.ArrayListUnmanaged(Index),
11399 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {11400 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
...@@ -11405,23 +11406,21 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11405,23 +11406,21 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11405 var it = instances.iterator();11406 var it = instances.iterator();
11406 while (it.next()) |entry| {11407 while (it.next()) |entry| {
11407 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);11408 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);
11408 try w.print("{} ({}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });11409 try stderr_bw.print("{f} ({d}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
11409 for (entry.value_ptr.items) |index| {11410 for (entry.value_ptr.items) |index| {
11410 const unwrapped_index = index.unwrap(ip);11411 const unwrapped_index = index.unwrap(ip);
11411 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));11412 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));
11412 const owner_nav = ip.getNav(func.owner_nav);11413 const owner_nav = ip.getNav(func.owner_nav);
11413 try w.print(" {}: (", .{owner_nav.name.fmt(ip)});11414 try stderr_bw.print(" {f}: (", .{owner_nav.name.fmt(ip)});
11414 for (func.comptime_args.get(ip)) |arg| {11415 for (func.comptime_args.get(ip)) |arg| {
11415 if (arg != .none) {11416 if (arg != .none) {
11416 const key = ip.indexToKey(arg);11417 const key = ip.indexToKey(arg);
11417 try w.print(" {} ", .{key});11418 try stderr_bw.print(" {} ", .{key});
11418 }11419 }
11419 }11420 }
11420 try w.writeAll(")\n");11421 try stderr_bw.writeAll(")\n");
11421 }11422 }
11422 }11423 }
11423
11424 try bw.flush();
11425}11424}
1142611425
11427pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {11426pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
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+64-61
...@@ -27,6 +27,22 @@...@@ -27,6 +27,22 @@
27//! All of this must be done with only referring to the state inside this struct27//! All of this must be done with only referring to the state inside this struct
28//! because this work will be done in a dedicated thread.28//! because this work will be done in a dedicated thread.
2929
30const builtin = @import("builtin");
31const std = @import("std");
32const fs = std.fs;
33const assert = std.debug.assert;
34const ascii = std.ascii;
35const Allocator = std.mem.Allocator;
36const Cache = std.Build.Cache;
37const ThreadPool = std.Thread.Pool;
38const WaitGroup = std.Thread.WaitGroup;
39const Fetch = @This();
40const git = @import("Fetch/git.zig");
41const Package = @import("../Package.zig");
42const Manifest = Package.Manifest;
43const ErrorBundle = std.zig.ErrorBundle;
44const native_os = builtin.os.tag;
45
30arena: std.heap.ArenaAllocator,46arena: std.heap.ArenaAllocator,
31location: Location,47location: Location,
32location_tok: std.zig.Ast.TokenIndex,48location_tok: std.zig.Ast.TokenIndex,
...@@ -185,7 +201,7 @@ pub const JobQueue = struct {...@@ -185,7 +201,7 @@ pub const JobQueue = struct {
185 const hash_slice = hash.toSlice();201 const hash_slice = hash.toSlice();
186202
187 try buf.writer().print(203 try buf.writer().print(
188 \\ pub const {} = struct {{204 \\ pub const {f} = struct {{
189 \\205 \\
190 , .{std.zig.fmtId(hash_slice)});206 , .{std.zig.fmtId(hash_slice)});
191207
...@@ -211,15 +227,15 @@ pub const JobQueue = struct {...@@ -211,15 +227,15 @@ pub const JobQueue = struct {
211 }227 }
212228
213 try buf.writer().print(229 try buf.writer().print(
214 \\ pub const build_root = "{q}";230 \\ pub const build_root = "{f}";
215 \\231 \\
216 , .{fetch.package_root});232 , .{std.fmt.alt(fetch.package_root, .formatEscapeString)});
217233
218 if (fetch.has_build_zig) {234 if (fetch.has_build_zig) {
219 try buf.writer().print(235 try buf.writer().print(
220 \\ pub const build_zig = @import("{}");236 \\ pub const build_zig = @import("{f}");
221 \\237 \\
222 , .{std.zig.fmtEscapes(hash_slice)});238 , .{std.zig.fmtString(hash_slice)});
223 }239 }
224240
225 if (fetch.manifest) |*manifest| {241 if (fetch.manifest) |*manifest| {
...@@ -230,8 +246,8 @@ pub const JobQueue = struct {...@@ -230,8 +246,8 @@ pub const JobQueue = struct {
230 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {246 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {
231 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;
232 try buf.writer().print(248 try buf.writer().print(
233 " .{{ \"{}\", \"{}\" }},\n",249 " .{{ \"{f}\", \"{f}\" }},\n",
234 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },250 .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) },
235 );251 );
236 }252 }
237253
...@@ -262,8 +278,8 @@ pub const JobQueue = struct {...@@ -262,8 +278,8 @@ pub const JobQueue = struct {
262 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {278 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {
263 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;
264 try buf.writer().print(280 try buf.writer().print(
265 " .{{ \"{}\", \"{}\" }},\n",281 " .{{ \"{f}\", \"{f}\" }},\n",
266 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },282 .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) },
267 );283 );
268 }284 }
269 try buf.appendSlice("};\n");285 try buf.appendSlice("};\n");
...@@ -353,7 +369,7 @@ pub fn run(f: *Fetch) RunError!void {...@@ -353,7 +369,7 @@ pub fn run(f: *Fetch) RunError!void {
353 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {369 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {
354 return f.fail(370 return f.fail(
355 f.location_tok,371 f.location_tok,
356 try eb.printString("dependency path outside project: '{}'", .{pkg_root}),372 try eb.printString("dependency path outside project: '{f}'", .{pkg_root}),
357 );373 );
358 }374 }
359 }375 }
...@@ -420,14 +436,14 @@ pub fn run(f: *Fetch) RunError!void {...@@ -420,14 +436,14 @@ pub fn run(f: *Fetch) RunError!void {
420 }436 }
421 if (f.job_queue.read_only) return f.fail(437 if (f.job_queue.read_only) return f.fail(
422 f.name_tok,438 f.name_tok,
423 try eb.printString("package not found at '{}{s}'", .{439 try eb.printString("package not found at '{f}{s}'", .{
424 cache_root, pkg_sub_path,440 cache_root, pkg_sub_path,
425 }),441 }),
426 );442 );
427 },443 },
428 else => |e| {444 else => |e| {
429 try eb.addRootErrorMessage(.{445 try eb.addRootErrorMessage(.{
430 .msg = try eb.printString("unable to open global package cache directory '{}{s}': {s}", .{446 .msg = try eb.printString("unable to open global package cache directory '{f}{s}': {s}", .{
431 cache_root, pkg_sub_path, @errorName(e),447 cache_root, pkg_sub_path, @errorName(e),
432 }),448 }),
433 });449 });
...@@ -604,7 +620,7 @@ pub fn computedPackageHash(f: *const Fetch) Package.Hash {...@@ -604,7 +620,7 @@ pub fn computedPackageHash(f: *const Fetch) Package.Hash {
604 const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32);620 const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32);
605 if (f.manifest) |man| {621 if (f.manifest) |man| {
606 var version_buffer: [32]u8 = undefined;622 var version_buffer: [32]u8 = undefined;
607 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{}", .{man.version}) catch &version_buffer;623 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{f}", .{man.version}) catch &version_buffer;
608 return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size);624 return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size);
609 }625 }
610 // In the future build.zig.zon fields will be added to allow overriding these values626 // In the future build.zig.zon fields will be added to allow overriding these values
...@@ -622,7 +638,7 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void {...@@ -622,7 +638,7 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void {
622 error.FileNotFound => {},638 error.FileNotFound => {},
623 else => |e| {639 else => |e| {
624 try eb.addRootErrorMessage(.{640 try eb.addRootErrorMessage(.{
625 .msg = try eb.printString("unable to access '{}{s}': {s}", .{641 .msg = try eb.printString("unable to access '{f}{s}': {s}", .{
626 f.package_root, Package.build_zig_basename, @errorName(e),642 f.package_root, Package.build_zig_basename, @errorName(e),
627 }),643 }),
628 });644 });
...@@ -647,7 +663,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -647,7 +663,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
647 else => |e| {663 else => |e| {
648 const file_path = try pkg_root.join(arena, Manifest.basename);664 const file_path = try pkg_root.join(arena, Manifest.basename);
649 try eb.addRootErrorMessage(.{665 try eb.addRootErrorMessage(.{
650 .msg = try eb.printString("unable to load package manifest '{}': {s}", .{666 .msg = try eb.printString("unable to load package manifest '{f}': {s}", .{
651 file_path, @errorName(e),667 file_path, @errorName(e),
652 }),668 }),
653 });669 });
...@@ -659,7 +675,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -659,7 +675,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
659 ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon);675 ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon);
660676
661 if (ast.errors.len > 0) {677 if (ast.errors.len > 0) {
662 const file_path = try std.fmt.allocPrint(arena, "{}" ++ fs.path.sep_str ++ Manifest.basename, .{pkg_root});678 const file_path = try std.fmt.allocPrint(arena, "{f}" ++ fs.path.sep_str ++ Manifest.basename, .{pkg_root});
663 try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb);679 try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb);
664 return error.FetchFailed;680 return error.FetchFailed;
665 }681 }
...@@ -672,7 +688,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -672,7 +688,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
672 const manifest = &f.manifest.?;688 const manifest = &f.manifest.?;
673689
674 if (manifest.errors.len > 0) {690 if (manifest.errors.len > 0) {
675 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ "{s}", .{ pkg_root, Manifest.basename });691 const src_path = try eb.printString("{f}" ++ fs.path.sep_str ++ "{s}", .{ pkg_root, Manifest.basename });
676 try manifest.copyErrorsIntoBundle(ast.*, src_path, eb);692 try manifest.copyErrorsIntoBundle(ast.*, src_path, eb);
677 return error.FetchFailed;693 return error.FetchFailed;
678 }694 }
...@@ -827,7 +843,7 @@ fn srcLoc(...@@ -827,7 +843,7 @@ fn srcLoc(
827 const ast = f.parent_manifest_ast orelse return .none;843 const ast = f.parent_manifest_ast orelse return .none;
828 const eb = &f.error_bundle;844 const eb = &f.error_bundle;
829 const start_loc = ast.tokenLocation(0, tok);845 const start_loc = ast.tokenLocation(0, tok);
830 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});846 const src_path = try eb.printString("{f}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});
831 const msg_off = 0;847 const msg_off = 0;
832 return eb.addSourceLocation(.{848 return eb.addSourceLocation(.{
833 .src_path = src_path,849 .src_path = src_path,
...@@ -961,7 +977,7 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re...@@ -961,7 +977,7 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
961 if (ascii.eqlIgnoreCase(uri.scheme, "file")) {977 if (ascii.eqlIgnoreCase(uri.scheme, "file")) {
962 const path = try uri.path.toRawMaybeAlloc(arena);978 const path = try uri.path.toRawMaybeAlloc(arena);
963 return .{ .file = f.parent_package_root.openFile(path, .{}) catch |err| {979 return .{ .file = f.parent_package_root.openFile(path, .{}) catch |err| {
964 return f.fail(f.location_tok, try eb.printString("unable to open '{}{s}': {s}", .{980 return f.fail(f.location_tok, try eb.printString("unable to open '{f}{s}': {s}", .{
965 f.parent_package_root, path, @errorName(err),981 f.parent_package_root, path, @errorName(err),
966 }));982 }));
967 } };983 } };
...@@ -1063,13 +1079,16 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re...@@ -1063,13 +1079,16 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
1063 });1079 });
1064 const notes_start = try eb.reserveNotes(notes_len);1080 const notes_start = try eb.reserveNotes(notes_len);
1065 eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{1081 eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{
1066 .msg = try eb.printString("try .url = \"{;+/}#{}\",", .{ uri, want_oid }),1082 .msg = try eb.printString("try .url = \"{f}#{f}\",", .{
1083 uri.fmt(.{ .scheme = true, .authority = true, .path = true }),
1084 want_oid,
1085 }),
1067 }));1086 }));
1068 return error.FetchFailed;1087 return error.FetchFailed;
1069 }1088 }
10701089
1071 var want_oid_buf: [git.Oid.max_formatted_length]u8 = undefined;1090 var want_oid_buf: [git.Oid.max_formatted_length]u8 = undefined;
1072 _ = std.fmt.bufPrint(&want_oid_buf, "{}", .{want_oid}) catch unreachable;1091 _ = std.fmt.bufPrint(&want_oid_buf, "{f}", .{want_oid}) catch unreachable;
1073 var fetch_stream = session.fetch(&.{&want_oid_buf}, server_header_buffer) catch |err| {1092 var fetch_stream = session.fetch(&.{&want_oid_buf}, server_header_buffer) catch |err| {
1074 return f.fail(f.location_tok, try eb.printString(1093 return f.fail(f.location_tok, try eb.printString(
1075 "unable to create fetch stream: {s}",1094 "unable to create fetch stream: {s}",
...@@ -1305,7 +1324,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {...@@ -1305,7 +1324,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {
1305 .{@errorName(err)},1324 .{@errorName(err)},
1306 ));1325 ));
1307 if (len == 0) break;1326 if (len == 0) break;
1308 zip_file.writer().writeAll(buf[0..len]) catch |err| return f.fail(f.location_tok, try eb.printString(1327 zip_file.deprecatedWriter().writeAll(buf[0..len]) catch |err| return f.fail(f.location_tok, try eb.printString(
1309 "write temporary zip file failed: {s}",1328 "write temporary zip file failed: {s}",
1310 .{@errorName(err)},1329 .{@errorName(err)},
1311 ));1330 ));
...@@ -1358,7 +1377,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U...@@ -1358,7 +1377,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
1358 var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true });1377 var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true });
1359 defer pack_file.close();1378 defer pack_file.close();
1360 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();1379 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
1361 try fifo.pump(resource.fetch_stream.reader(), pack_file.writer());1380 try fifo.pump(resource.fetch_stream.reader(), pack_file.deprecatedWriter());
1362 try pack_file.sync();1381 try pack_file.sync();
13631382
1364 var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true });1383 var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true });
...@@ -1366,7 +1385,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U...@@ -1366,7 +1385,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
1366 {1385 {
1367 const index_prog_node = f.prog_node.start("Index pack", 0);1386 const index_prog_node = f.prog_node.start("Index pack", 0);
1368 defer index_prog_node.end();1387 defer index_prog_node.end();
1369 var index_buffered_writer = std.io.bufferedWriter(index_file.writer());1388 var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter());
1370 try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer());1389 try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer());
1371 try index_buffered_writer.flush();1390 try index_buffered_writer.flush();
1372 try index_file.sync();1391 try index_file.sync();
...@@ -1508,7 +1527,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute...@@ -1508,7 +1527,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
15081527
1509 while (walker.next() catch |err| {1528 while (walker.next() catch |err| {
1510 try eb.addRootErrorMessage(.{ .msg = try eb.printString(1529 try eb.addRootErrorMessage(.{ .msg = try eb.printString(
1511 "unable to walk temporary directory '{}': {s}",1530 "unable to walk temporary directory '{f}': {s}",
1512 .{ pkg_path, @errorName(err) },1531 .{ pkg_path, @errorName(err) },
1513 ) });1532 ) });
1514 return error.FetchFailed;1533 return error.FetchFailed;
...@@ -1638,14 +1657,14 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute...@@ -1638,14 +1657,14 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
1638}1657}
16391658
1640fn dumpHashInfo(all_files: []const *const HashedFile) !void {1659fn dumpHashInfo(all_files: []const *const HashedFile) !void {
1641 const stdout = std.io.getStdOut();1660 const stdout: std.fs.File = .stdout();
1642 var bw = std.io.bufferedWriter(stdout.writer());1661 var bw = std.io.bufferedWriter(stdout.deprecatedWriter());
1643 const w = bw.writer();1662 const w = bw.writer();
16441663
1645 for (all_files) |hashed_file| {1664 for (all_files) |hashed_file| {
1646 try w.print("{s}: {s}: {s}\n", .{1665 try w.print("{s}: {x}: {s}\n", .{
1647 @tagName(hashed_file.kind),1666 @tagName(hashed_file.kind),
1648 std.fmt.fmtSliceHexLower(&hashed_file.hash),1667 &hashed_file.hash,
1649 hashed_file.normalized_path,1668 hashed_file.normalized_path,
1650 });1669 });
1651 }1670 }
...@@ -1817,28 +1836,6 @@ pub fn depDigest(pkg_root: Cache.Path, cache_root: Cache.Directory, dep: Manifes...@@ -1817,28 +1836,6 @@ pub fn depDigest(pkg_root: Cache.Path, cache_root: Cache.Directory, dep: Manifes
1817 }1836 }
1818}1837}
18191838
1820const builtin = @import("builtin");
1821const std = @import("std");
1822const fs = std.fs;
1823const assert = std.debug.assert;
1824const ascii = std.ascii;
1825const Allocator = std.mem.Allocator;
1826const Cache = std.Build.Cache;
1827const ThreadPool = std.Thread.Pool;
1828const WaitGroup = std.Thread.WaitGroup;
1829const Fetch = @This();
1830const git = @import("Fetch/git.zig");
1831const Package = @import("../Package.zig");
1832const Manifest = Package.Manifest;
1833const ErrorBundle = std.zig.ErrorBundle;
1834const native_os = builtin.os.tag;
1835
1836test {
1837 _ = Filter;
1838 _ = FileType;
1839 _ = UnpackResult;
1840}
1841
1842// Detects executable header: ELF or Macho-O magic header or shebang line.1839// Detects executable header: ELF or Macho-O magic header or shebang line.
1843const FileHeader = struct {1840const FileHeader = struct {
1844 header: [4]u8 = undefined,1841 header: [4]u8 = undefined,
...@@ -2056,15 +2053,15 @@ const UnpackResult = struct {...@@ -2056,15 +2053,15 @@ const UnpackResult = struct {
2056 // output errors to string2053 // output errors to string
2057 var errors = try fetch.error_bundle.toOwnedBundle("");2054 var errors = try fetch.error_bundle.toOwnedBundle("");
2058 defer errors.deinit(gpa);2055 defer errors.deinit(gpa);
2059 var out = std.ArrayList(u8).init(gpa);2056 var aw: std.io.Writer.Allocating = .init(gpa);
2060 defer out.deinit();2057 defer aw.deinit();
2061 try errors.renderToWriter(.{ .ttyconf = .no_color }, out.writer());2058 try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer);
2062 try std.testing.expectEqualStrings(2059 try std.testing.expectEqualStrings(
2063 \\error: unable to unpack2060 \\error: unable to unpack
2064 \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError2061 \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError
2065 \\ note: file 'dir2/file4' has unsupported type 'x'2062 \\ note: file 'dir2/file4' has unsupported type 'x'
2066 \\2063 \\
2067 , out.items);2064 , aw.getWritten());
2068 }2065 }
2069};2066};
20702067
...@@ -2080,7 +2077,7 @@ test "zip" {...@@ -2080,7 +2077,7 @@ test "zip" {
2080 {2077 {
2081 var zip_file = try tmp.dir.createFile("test.zip", .{});2078 var zip_file = try tmp.dir.createFile("test.zip", .{});
2082 defer zip_file.close();2079 defer zip_file.close();
2083 var bw = std.io.bufferedWriter(zip_file.writer());2080 var bw = std.io.bufferedWriter(zip_file.deprecatedWriter());
2084 var store: [test_files.len]std.zip.testutil.FileStore = undefined;2081 var store: [test_files.len]std.zip.testutil.FileStore = undefined;
2085 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});2082 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});
2086 try bw.flush();2083 try bw.flush();
...@@ -2113,7 +2110,7 @@ test "zip with one root folder" {...@@ -2113,7 +2110,7 @@ test "zip with one root folder" {
2113 {2110 {
2114 var zip_file = try tmp.dir.createFile("test.zip", .{});2111 var zip_file = try tmp.dir.createFile("test.zip", .{});
2115 defer zip_file.close();2112 defer zip_file.close();
2116 var bw = std.io.bufferedWriter(zip_file.writer());2113 var bw = std.io.bufferedWriter(zip_file.deprecatedWriter());
2117 var store: [test_files.len]std.zip.testutil.FileStore = undefined;2114 var store: [test_files.len]std.zip.testutil.FileStore = undefined;
2118 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});2115 try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{});
2119 try bw.flush();2116 try bw.flush();
...@@ -2431,9 +2428,15 @@ const TestFetchBuilder = struct {...@@ -2431,9 +2428,15 @@ const TestFetchBuilder = struct {
2431 if (notes_len > 0) {2428 if (notes_len > 0) {
2432 try std.testing.expectEqual(notes_len, em.notes_len);2429 try std.testing.expectEqual(notes_len, em.notes_len);
2433 }2430 }
2434 var al = std.ArrayList(u8).init(std.testing.allocator);2431 var aw: std.io.Writer.Allocating = .init(std.testing.allocator);
2435 defer al.deinit();2432 defer aw.deinit();
2436 try errors.renderToWriter(.{ .ttyconf = .no_color }, al.writer());2433 try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer);
2437 try std.testing.expectEqualStrings(msg, al.items);2434 try std.testing.expectEqualStrings(msg, aw.getWritten());
2438 }2435 }
2439};2436};
2437
2438test {
2439 _ = Filter;
2440 _ = FileType;
2441 _ = UnpackResult;
2442}
src/Package/Fetch/git.zig+40-31
...@@ -119,15 +119,8 @@ pub const Oid = union(Format) {...@@ -119,15 +119,8 @@ pub const Oid = union(Format) {
119 } else error.InvalidOid;119 } else error.InvalidOid;
120 }120 }
121121
122 pub fn format(122 pub fn format(oid: Oid, writer: *std.io.Writer) std.io.Writer.Error!void {
123 oid: Oid,123 try writer.print("{x}", .{oid.slice()});
124 comptime fmt: []const u8,
125 options: std.fmt.FormatOptions,
126 writer: anytype,
127 ) @TypeOf(writer).Error!void {
128 _ = fmt;
129 _ = options;
130 try writer.print("{}", .{std.fmt.fmtSliceHexLower(oid.slice())});
131 }124 }
132125
133 pub fn slice(oid: *const Oid) []const u8 {126 pub fn slice(oid: *const Oid) []const u8 {
...@@ -353,7 +346,7 @@ const Odb = struct {...@@ -353,7 +346,7 @@ const Odb = struct {
353 fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb {346 fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb {
354 try pack_file.seekTo(0);347 try pack_file.seekTo(0);
355 try index_file.seekTo(0);348 try index_file.seekTo(0);
356 const index_header = try IndexHeader.read(index_file.reader());349 const index_header = try IndexHeader.read(index_file.deprecatedReader());
357 return .{350 return .{
358 .format = format,351 .format = format,
359 .pack_file = pack_file,352 .pack_file = pack_file,
...@@ -377,7 +370,7 @@ const Odb = struct {...@@ -377,7 +370,7 @@ const Odb = struct {
377 const base_object = while (true) {370 const base_object = while (true) {
378 if (odb.cache.get(base_offset)) |base_object| break base_object;371 if (odb.cache.get(base_offset)) |base_object| break base_object;
379372
380 base_header = try EntryHeader.read(odb.format, odb.pack_file.reader());373 base_header = try EntryHeader.read(odb.format, odb.pack_file.deprecatedReader());
381 switch (base_header) {374 switch (base_header) {
382 .ofs_delta => |ofs_delta| {375 .ofs_delta => |ofs_delta| {
383 try delta_offsets.append(odb.allocator, base_offset);376 try delta_offsets.append(odb.allocator, base_offset);
...@@ -390,7 +383,7 @@ const Odb = struct {...@@ -390,7 +383,7 @@ const Odb = struct {
390 base_offset = try odb.pack_file.getPos();383 base_offset = try odb.pack_file.getPos();
391 },384 },
392 else => {385 else => {
393 const base_data = try readObjectRaw(odb.allocator, odb.pack_file.reader(), base_header.uncompressedLength());386 const base_data = try readObjectRaw(odb.allocator, odb.pack_file.deprecatedReader(), base_header.uncompressedLength());
394 errdefer odb.allocator.free(base_data);387 errdefer odb.allocator.free(base_data);
395 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };388 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };
396 try odb.cache.put(odb.allocator, base_offset, base_object);389 try odb.cache.put(odb.allocator, base_offset, base_object);
...@@ -420,7 +413,7 @@ const Odb = struct {...@@ -420,7 +413,7 @@ const Odb = struct {
420 const found_index = while (start_index < end_index) {413 const found_index = while (start_index < end_index) {
421 const mid_index = start_index + (end_index - start_index) / 2;414 const mid_index = start_index + (end_index - start_index) / 2;
422 try odb.index_file.seekTo(IndexHeader.size + mid_index * oid_length);415 try odb.index_file.seekTo(IndexHeader.size + mid_index * oid_length);
423 const mid_oid = try Oid.readBytes(odb.format, odb.index_file.reader());416 const mid_oid = try Oid.readBytes(odb.format, odb.index_file.deprecatedReader());
424 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {417 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {
425 .lt => start_index = mid_index + 1,418 .lt => start_index = mid_index + 1,
426 .gt => end_index = mid_index,419 .gt => end_index = mid_index,
...@@ -431,12 +424,12 @@ const Odb = struct {...@@ -431,12 +424,12 @@ const Odb = struct {
431 const n_objects = odb.index_header.fan_out_table[255];424 const n_objects = odb.index_header.fan_out_table[255];
432 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);425 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);
433 try odb.index_file.seekTo(offset_values_start + found_index * 4);426 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));427 const l1_offset: packed struct { value: u31, big: bool } = @bitCast(try odb.index_file.deprecatedReader().readInt(u32, .big));
435 const pack_offset = pack_offset: {428 const pack_offset = pack_offset: {
436 if (l1_offset.big) {429 if (l1_offset.big) {
437 const l2_offset_values_start = offset_values_start + n_objects * 4;430 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);431 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);432 break :pack_offset try odb.index_file.deprecatedReader().readInt(u64, .big);
440 } else {433 } else {
441 break :pack_offset l1_offset.value;434 break :pack_offset l1_offset.value;
442 }435 }
...@@ -669,13 +662,21 @@ pub const Session = struct {...@@ -669,13 +662,21 @@ pub const Session = struct {
669 fn init(allocator: Allocator, uri: std.Uri) !Location {662 fn init(allocator: Allocator, uri: std.Uri) !Location {
670 const scheme = try allocator.dupe(u8, uri.scheme);663 const scheme = try allocator.dupe(u8, uri.scheme);
671 errdefer allocator.free(scheme);664 errdefer allocator.free(scheme);
672 const user = if (uri.user) |user| try std.fmt.allocPrint(allocator, "{user}", .{user}) else null;665 const user = if (uri.user) |user| try std.fmt.allocPrint(allocator, "{f}", .{
666 std.fmt.alt(user, .formatUser),
667 }) else null;
673 errdefer if (user) |s| allocator.free(s);668 errdefer if (user) |s| allocator.free(s);
674 const password = if (uri.password) |password| try std.fmt.allocPrint(allocator, "{password}", .{password}) else null;669 const password = if (uri.password) |password| try std.fmt.allocPrint(allocator, "{f}", .{
670 std.fmt.alt(password, .formatPassword),
671 }) else null;
675 errdefer if (password) |s| allocator.free(s);672 errdefer if (password) |s| allocator.free(s);
676 const host = if (uri.host) |host| try std.fmt.allocPrint(allocator, "{host}", .{host}) else null;673 const host = if (uri.host) |host| try std.fmt.allocPrint(allocator, "{f}", .{
674 std.fmt.alt(host, .formatHost),
675 }) else null;
677 errdefer if (host) |s| allocator.free(s);676 errdefer if (host) |s| allocator.free(s);
678 const path = try std.fmt.allocPrint(allocator, "{path}", .{uri.path});677 const path = try std.fmt.allocPrint(allocator, "{f}", .{
678 std.fmt.alt(uri.path, .formatPath),
679 });
679 errdefer allocator.free(path);680 errdefer allocator.free(path);
680 // The query and fragment are not used as part of the base server URI.681 // The query and fragment are not used as part of the base server URI.
681 return .{682 return .{
...@@ -706,7 +707,9 @@ pub const Session = struct {...@@ -706,7 +707,9 @@ pub const Session = struct {
706 fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator {707 fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator {
707 var info_refs_uri = session.location.uri;708 var info_refs_uri = session.location.uri;
708 {709 {
709 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{path}", .{session.location.uri.path});710 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{
711 std.fmt.alt(session.location.uri.path, .formatPath),
712 });
710 defer session.allocator.free(session_uri_path);713 defer session.allocator.free(session_uri_path);
711 info_refs_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "info/refs" }) };714 info_refs_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "info/refs" }) };
712 }715 }
...@@ -730,7 +733,9 @@ pub const Session = struct {...@@ -730,7 +733,9 @@ pub const Session = struct {
730 if (request.response.status != .ok) return error.ProtocolError;733 if (request.response.status != .ok) return error.ProtocolError;
731 const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects;734 const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects;
732 if (any_redirects_occurred) {735 if (any_redirects_occurred) {
733 const request_uri_path = try std.fmt.allocPrint(session.allocator, "{path}", .{request.uri.path});736 const request_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{
737 std.fmt.alt(request.uri.path, .formatPath),
738 });
734 defer session.allocator.free(request_uri_path);739 defer session.allocator.free(request_uri_path);
735 if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect;740 if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect;
736 var new_uri = request.uri;741 var new_uri = request.uri;
...@@ -817,7 +822,9 @@ pub const Session = struct {...@@ -817,7 +822,9 @@ pub const Session = struct {
817 pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator {822 pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator {
818 var upload_pack_uri = session.location.uri;823 var upload_pack_uri = session.location.uri;
819 {824 {
820 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{path}", .{session.location.uri.path});825 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{
826 std.fmt.alt(session.location.uri.path, .formatPath),
827 });
821 defer session.allocator.free(session_uri_path);828 defer session.allocator.free(session_uri_path);
822 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };829 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };
823 }830 }
...@@ -932,7 +939,9 @@ pub const Session = struct {...@@ -932,7 +939,9 @@ pub const Session = struct {
932 ) !FetchStream {939 ) !FetchStream {
933 var upload_pack_uri = session.location.uri;940 var upload_pack_uri = session.location.uri;
934 {941 {
935 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{path}", .{session.location.uri.path});942 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{
943 std.fmt.alt(session.location.uri.path, .formatPath),
944 });
936 defer session.allocator.free(session_uri_path);945 defer session.allocator.free(session_uri_path);
937 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };946 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };
938 }947 }
...@@ -1026,7 +1035,7 @@ pub const Session = struct {...@@ -1026,7 +1035,7 @@ pub const Session = struct {
1026 ProtocolError,1035 ProtocolError,
1027 UnexpectedPacket,1036 UnexpectedPacket,
1028 };1037 };
1029 pub const Reader = std.io.Reader(*FetchStream, ReadError, read);1038 pub const Reader = std.io.GenericReader(*FetchStream, ReadError, read);
10301039
1031 const StreamCode = enum(u8) {1040 const StreamCode = enum(u8) {
1032 pack_data = 1,1041 pack_data = 1,
...@@ -1320,7 +1329,7 @@ fn indexPackFirstPass(...@@ -1320,7 +1329,7 @@ fn indexPackFirstPass(
1320 index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry),1329 index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry),
1321 pending_deltas: *std.ArrayListUnmanaged(IndexEntry),1330 pending_deltas: *std.ArrayListUnmanaged(IndexEntry),
1322) !Oid {1331) !Oid {
1323 var pack_buffered_reader = std.io.bufferedReader(pack.reader());1332 var pack_buffered_reader = std.io.bufferedReader(pack.deprecatedReader());
1324 var pack_counting_reader = std.io.countingReader(pack_buffered_reader.reader());1333 var pack_counting_reader = std.io.countingReader(pack_buffered_reader.reader());
1325 var pack_hashed_reader = std.compress.hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format));1334 var pack_hashed_reader = std.compress.hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format));
1326 const pack_reader = pack_hashed_reader.reader();1335 const pack_reader = pack_hashed_reader.reader();
...@@ -1400,7 +1409,7 @@ fn indexPackHashDelta(...@@ -1400,7 +1409,7 @@ fn indexPackHashDelta(
1400 if (cache.get(base_offset)) |base_object| break base_object;1409 if (cache.get(base_offset)) |base_object| break base_object;
14011410
1402 try pack.seekTo(base_offset);1411 try pack.seekTo(base_offset);
1403 base_header = try EntryHeader.read(format, pack.reader());1412 base_header = try EntryHeader.read(format, pack.deprecatedReader());
1404 switch (base_header) {1413 switch (base_header) {
1405 .ofs_delta => |ofs_delta| {1414 .ofs_delta => |ofs_delta| {
1406 try delta_offsets.append(allocator, base_offset);1415 try delta_offsets.append(allocator, base_offset);
...@@ -1411,7 +1420,7 @@ fn indexPackHashDelta(...@@ -1411,7 +1420,7 @@ fn indexPackHashDelta(
1411 base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset;1420 base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset;
1412 },1421 },
1413 else => {1422 else => {
1414 const base_data = try readObjectRaw(allocator, pack.reader(), base_header.uncompressedLength());1423 const base_data = try readObjectRaw(allocator, pack.deprecatedReader(), base_header.uncompressedLength());
1415 errdefer allocator.free(base_data);1424 errdefer allocator.free(base_data);
1416 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };1425 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };
1417 try cache.put(allocator, base_offset, base_object);1426 try cache.put(allocator, base_offset, base_object);
...@@ -1448,8 +1457,8 @@ fn resolveDeltaChain(...@@ -1448,8 +1457,8 @@ fn resolveDeltaChain(
14481457
1449 const delta_offset = delta_offsets[i];1458 const delta_offset = delta_offsets[i];
1450 try pack.seekTo(delta_offset);1459 try pack.seekTo(delta_offset);
1451 const delta_header = try EntryHeader.read(format, pack.reader());1460 const delta_header = try EntryHeader.read(format, pack.deprecatedReader());
1452 const delta_data = try readObjectRaw(allocator, pack.reader(), delta_header.uncompressedLength());1461 const delta_data = try readObjectRaw(allocator, pack.deprecatedReader(), delta_header.uncompressedLength());
1453 defer allocator.free(delta_data);1462 defer allocator.free(delta_data);
1454 var delta_stream = std.io.fixedBufferStream(delta_data);1463 var delta_stream = std.io.fixedBufferStream(delta_data);
1455 const delta_reader = delta_stream.reader();1464 const delta_reader = delta_stream.reader();
...@@ -1561,7 +1570,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void...@@ -1561,7 +1570,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void
15611570
1562 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });1571 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });
1563 defer index_file.close();1572 defer index_file.close();
1564 try indexPack(testing.allocator, format, pack_file, index_file.writer());1573 try indexPack(testing.allocator, format, pack_file, index_file.deprecatedWriter());
15651574
1566 // Arbitrary size limit on files read while checking the repository contents1575 // 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)1576 // (all files in the test repo are known to be smaller than this)
...@@ -1678,7 +1687,7 @@ pub fn main() !void {...@@ -1678,7 +1687,7 @@ pub fn main() !void {
1678 std.debug.print("Starting index...\n", .{});1687 std.debug.print("Starting index...\n", .{});
1679 var index_file = try git_dir.createFile("idx", .{ .read = true });1688 var index_file = try git_dir.createFile("idx", .{ .read = true });
1680 defer index_file.close();1689 defer index_file.close();
1681 var index_buffered_writer = std.io.bufferedWriter(index_file.writer());1690 var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter());
1682 try indexPack(allocator, format, pack_file, index_buffered_writer.writer());1691 try indexPack(allocator, format, pack_file, index_buffered_writer.writer());
1683 try index_buffered_writer.flush();1692 try index_buffered_writer.flush();
1684 try index_file.sync();1693 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+481-480
...@@ -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 },
...@@ -1144,7 +1144,7 @@ fn analyzeBodyInner(...@@ -1144,7 +1144,7 @@ fn analyzeBodyInner(
11441144
1145 // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away.1145 // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away.
1146 if (build_options.enable_logging) {1146 if (build_options.enable_logging) {
1147 std.log.scoped(.sema_zir).debug("sema ZIR {} %{d}", .{ path: {1147 std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path: {
1148 const file_index = block.src_base_inst.resolveFile(&zcu.intern_pool);1148 const file_index = block.src_base_inst.resolveFile(&zcu.intern_pool);
1149 const file = zcu.fileByIndex(file_index);1149 const file = zcu.fileByIndex(file_index);
1150 break :path file.path.fmt(zcu.comp);1150 break :path file.path.fmt(zcu.comp);
...@@ -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| {
...@@ -2763,7 +2763,7 @@ fn zirTupleDecl(...@@ -2763,7 +2763,7 @@ fn zirTupleDecl(
2763 const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src);2763 const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src);
2764 const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value });2764 const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value });
2765 if (field_init_val.canMutateComptimeVarState(zcu)) {2765 if (field_init_val.canMutateComptimeVarState(zcu)) {
2766 const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, pt.tid, "{}", .{field_index}, .no_embedded_nulls);2766 const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
2767 return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val);2767 return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val);
2768 }2768 }
2769 break :init field_init_val.toIntern();2769 break :init field_init_val.toIntern();
...@@ -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 w = &aw.writer;
3030 const writer = buf.writer(gpa);3030 w.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) w.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 w.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 w.writeByte(')') catch return error.OutOfMemory;
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) {
...@@ -5575,9 +5574,8 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -5575,9 +5574,8 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
55755574
5576 if (operand_ty.arrayLen(zcu) != extra.expect_len) {5575 if (operand_ty.arrayLen(zcu) != extra.expect_len) {
5577 return sema.failWithOwnedErrorMsg(block, msg: {5576 return sema.failWithOwnedErrorMsg(block, msg: {
5578 const msg = try sema.errMsg(src, "expected {} elements for destructure, found {}", .{5577 const msg = try sema.errMsg(src, "expected {d} elements for destructure, found {d}", .{
5579 extra.expect_len,5578 extra.expect_len, operand_ty.arrayLen(zcu),
5580 operand_ty.arrayLen(zcu),
5581 });5579 });
5582 errdefer msg.destroy(sema.gpa);5580 errdefer msg.destroy(sema.gpa);
5583 try sema.errNote(destructure_src, msg, "result destructured here", .{});5581 try sema.errNote(destructure_src, msg, "result destructured here", .{});
...@@ -5604,12 +5602,12 @@ fn failWithBadMemberAccess(...@@ -5604,12 +5602,12 @@ fn failWithBadMemberAccess(
5604 else => unreachable,5602 else => unreachable,
5605 };5603 };
5606 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {5604 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 '{}'", .{5605 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),5606 agg_ty.fmt(pt), field_name.fmt(ip),
5609 });5607 });
5610 };5608 };
56115609
5612 return sema.fail(block, field_src, "{s} '{}' has no member named '{}'", .{5610 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
5613 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),5611 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
5614 });5612 });
5615}5613}
...@@ -5629,7 +5627,7 @@ fn failWithBadStructFieldAccess(...@@ -5629,7 +5627,7 @@ fn failWithBadStructFieldAccess(
5629 const msg = msg: {5627 const msg = msg: {
5630 const msg = try sema.errMsg(5628 const msg = try sema.errMsg(
5631 field_src,5629 field_src,
5632 "no field named '{}' in struct '{}'",5630 "no field named '{f}' in struct '{f}'",
5633 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },5631 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },
5634 );5632 );
5635 errdefer msg.destroy(sema.gpa);5633 errdefer msg.destroy(sema.gpa);
...@@ -5655,7 +5653,7 @@ fn failWithBadUnionFieldAccess(...@@ -5655,7 +5653,7 @@ fn failWithBadUnionFieldAccess(
5655 const msg = msg: {5653 const msg = msg: {
5656 const msg = try sema.errMsg(5654 const msg = try sema.errMsg(
5657 field_src,5655 field_src,
5658 "no field named '{}' in union '{}'",5656 "no field named '{f}' in union '{f}'",
5659 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },5657 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },
5660 );5658 );
5661 errdefer msg.destroy(gpa);5659 errdefer msg.destroy(gpa);
...@@ -5907,30 +5905,29 @@ fn zirCompileLog(...@@ -5907,30 +5905,29 @@ fn zirCompileLog(
5907 const zcu = pt.zcu;5905 const zcu = pt.zcu;
5908 const gpa = zcu.gpa;5906 const gpa = zcu.gpa;
59095907
5910 var buf: std.ArrayListUnmanaged(u8) = .empty;5908 var aw: std.io.Writer.Allocating = .init(gpa);
5911 defer buf.deinit(gpa);5909 defer aw.deinit();
59125910 const writer = &aw.writer;
5913 const writer = buf.writer(gpa);
59145911
5915 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);5912 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
5916 const src_node = extra.data.src_node;5913 const src_node = extra.data.src_node;
5917 const args = sema.code.refSlice(extra.end, extended.small);5914 const args = sema.code.refSlice(extra.end, extended.small);
59185915
5919 for (args, 0..) |arg_ref, i| {5916 for (args, 0..) |arg_ref, i| {
5920 if (i != 0) try writer.print(", ", .{});5917 if (i != 0) writer.writeAll(", ") catch return error.OutOfMemory;
59215918
5922 const arg = try sema.resolveInst(arg_ref);5919 const arg = try sema.resolveInst(arg_ref);
5923 const arg_ty = sema.typeOf(arg);5920 const arg_ty = sema.typeOf(arg);
5924 if (try sema.resolveValueResolveLazy(arg)) |val| {5921 if (try sema.resolveValueResolveLazy(arg)) |val| {
5925 try writer.print("@as({}, {})", .{5922 writer.print("@as({f}, {f})", .{
5926 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),5923 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),
5927 });5924 }) catch return error.OutOfMemory;
5928 } else {5925 } else {
5929 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(pt)});5926 writer.print("@as({f}, [runtime value])", .{arg_ty.fmt(pt)}) catch return error.OutOfMemory;
5930 }5927 }
5931 }5928 }
59325929
5933 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);5930 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, aw.getWritten(), .no_embedded_nulls);
59345931
5935 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {5932 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {
5936 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{5933 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{
...@@ -6472,7 +6469,7 @@ fn resolveAnalyzedBlock(...@@ -6472,7 +6469,7 @@ fn resolveAnalyzedBlock(
6472 const type_src = src; // TODO: better source location6469 const type_src = src; // TODO: better source location
6473 if (try resolved_ty.comptimeOnlySema(pt)) {6470 if (try resolved_ty.comptimeOnlySema(pt)) {
6474 const msg = msg: {6471 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)});6472 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);6473 errdefer msg.destroy(sema.gpa);
64776474
6478 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;6475 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;
...@@ -6588,7 +6585,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -6588,7 +6585,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
65886585
6589 {6586 {
6590 if (ptr_ty.zigTypeTag(zcu) != .pointer) {6587 if (ptr_ty.zigTypeTag(zcu) != .pointer) {
6591 return sema.fail(block, ptr_src, "expected pointer type, found '{}'", .{ptr_ty.fmt(pt)});6588 return sema.fail(block, ptr_src, "expected pointer type, found '{f}'", .{ptr_ty.fmt(pt)});
6592 }6589 }
6593 const ptr_ty_info = ptr_ty.ptrInfo(zcu);6590 const ptr_ty_info = ptr_ty.ptrInfo(zcu);
6594 if (ptr_ty_info.flags.size == .slice) {6591 if (ptr_ty_info.flags.size == .slice) {
...@@ -6611,7 +6608,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -6611,7 +6608,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
6611 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);6608 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);
6612 if (!try sema.validateExternType(export_ty, .other)) {6609 if (!try sema.validateExternType(export_ty, .other)) {
6613 return sema.failWithOwnedErrorMsg(block, msg: {6610 return sema.failWithOwnedErrorMsg(block, msg: {
6614 const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)});6611 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)});
6615 errdefer msg.destroy(sema.gpa);6612 errdefer msg.destroy(sema.gpa);
6616 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);6613 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
6617 try sema.addDeclaredHereNote(msg, export_ty);6614 try sema.addDeclaredHereNote(msg, export_ty);
...@@ -6663,7 +6660,7 @@ pub fn analyzeExport(...@@ -6663,7 +6660,7 @@ pub fn analyzeExport(
66636660
6664 if (!try sema.validateExternType(export_ty, .other)) {6661 if (!try sema.validateExternType(export_ty, .other)) {
6665 return sema.failWithOwnedErrorMsg(block, msg: {6662 return sema.failWithOwnedErrorMsg(block, msg: {
6666 const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)});6663 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)});
6667 errdefer msg.destroy(gpa);6664 errdefer msg.destroy(gpa);
66686665
6669 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);6666 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
...@@ -7287,7 +7284,7 @@ fn checkCallArgumentCount(...@@ -7287,7 +7284,7 @@ fn checkCallArgumentCount(
7287 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))7284 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))
7288 {7285 {
7289 const msg = msg: {7286 const msg = msg: {
7290 const msg = try sema.errMsg(func_src, "cannot call optional type '{}'", .{7287 const msg = try sema.errMsg(func_src, "cannot call optional type '{f}'", .{
7291 callee_ty.fmt(pt),7288 callee_ty.fmt(pt),
7292 });7289 });
7293 errdefer msg.destroy(sema.gpa);7290 errdefer msg.destroy(sema.gpa);
...@@ -7299,7 +7296,7 @@ fn checkCallArgumentCount(...@@ -7299,7 +7296,7 @@ fn checkCallArgumentCount(
7299 },7296 },
7300 else => {},7297 else => {},
7301 }7298 }
7302 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(pt)});7299 return sema.fail(block, func_src, "type '{f}' not a function", .{callee_ty.fmt(pt)});
7303 };7300 };
73047301
7305 const func_ty_info = zcu.typeToFunc(func_ty).?;7302 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7362,7 +7359,7 @@ fn callBuiltin(...@@ -7362,7 +7359,7 @@ fn callBuiltin(
7362 },7359 },
7363 else => {},7360 else => {},
7364 }7361 }
7365 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(pt)});7362 std.debug.panic("type '{f}' is not a function calling builtin fn", .{callee_ty.fmt(pt)});
7366 };7363 };
73677364
7368 const func_ty_info = zcu.typeToFunc(func_ty).?;7365 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7746,7 +7743,7 @@ fn analyzeCall(...@@ -7746,7 +7743,7 @@ fn analyzeCall(
77467743
7747 if (!param_ty.isValidParamType(zcu)) {7744 if (!param_ty.isValidParamType(zcu)) {
7748 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";7745 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
7749 return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{7746 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
7750 opaque_str, param_ty.fmt(pt),7747 opaque_str, param_ty.fmt(pt),
7751 });7748 });
7752 }7749 }
...@@ -7843,7 +7840,7 @@ fn analyzeCall(...@@ -7843,7 +7840,7 @@ fn analyzeCall(
78437840
7844 if (!full_ty.isValidReturnType(zcu)) {7841 if (!full_ty.isValidReturnType(zcu)) {
7845 const opaque_str = if (full_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";7842 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", .{7843 return sema.fail(block, func_ret_ty_src, "{s}return type '{f}' not allowed", .{
7847 opaque_str, full_ty.fmt(pt),7844 opaque_str, full_ty.fmt(pt),
7848 });7845 });
7849 }7846 }
...@@ -8301,7 +8298,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -8301,7 +8298,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
8301 }8298 }
8302 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);8299 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);
8303 if (owner_func_ty.toIntern() != func_ty.toIntern()) {8300 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 '{}'", .{8301 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),8302 func_ty.fmt(pt), owner_func_ty.fmt(pt),
8306 });8303 });
8307 }8304 }
...@@ -8325,9 +8322,9 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -8325,9 +8322,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 });8322 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);8323 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);
8327 if (child_type.zigTypeTag(zcu) == .@"opaque") {8324 if (child_type.zigTypeTag(zcu) == .@"opaque") {
8328 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(pt)});8325 return sema.fail(block, operand_src, "opaque type '{f}' cannot be optional", .{child_type.fmt(pt)});
8329 } else if (child_type.zigTypeTag(zcu) == .null) {8326 } else if (child_type.zigTypeTag(zcu) == .null) {
8330 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(pt)});8327 return sema.fail(block, operand_src, "type '{f}' cannot be optional", .{child_type.fmt(pt)});
8331 }8328 }
8332 const opt_type = try pt.optionalType(child_type.toIntern());8329 const opt_type = try pt.optionalType(child_type.toIntern());
83338330
...@@ -8388,7 +8385,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8388,7 +8385,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;8385 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
8389 switch (vec_ty.zigTypeTag(zcu)) {8386 switch (vec_ty.zigTypeTag(zcu)) {
8390 .array, .vector => {},8387 .array, .vector => {},
8391 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{}'", .{vec_ty.fmt(pt)}),8388 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}),
8392 }8389 }
8393 return Air.internedToRef(vec_ty.childType(zcu).toIntern());8390 return Air.internedToRef(vec_ty.childType(zcu).toIntern());
8394}8391}
...@@ -8456,7 +8453,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:...@@ -8456,7 +8453,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:
8456 const pt = sema.pt;8453 const pt = sema.pt;
8457 const zcu = pt.zcu;8454 const zcu = pt.zcu;
8458 if (elem_type.zigTypeTag(zcu) == .@"opaque") {8455 if (elem_type.zigTypeTag(zcu) == .@"opaque") {
8459 return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(pt)});8456 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) {8457 } else if (elem_type.zigTypeTag(zcu) == .noreturn) {
8461 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});8458 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});
8462 }8459 }
...@@ -8492,7 +8489,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8492,7 +8489,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8492 const payload = try sema.resolveType(block, rhs_src, extra.rhs);8489 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
84938490
8494 if (error_set.zigTypeTag(zcu) != .error_set) {8491 if (error_set.zigTypeTag(zcu) != .error_set) {
8495 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{8492 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{
8496 error_set.fmt(pt),8493 error_set.fmt(pt),
8497 });8494 });
8498 }8495 }
...@@ -8505,11 +8502,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p...@@ -8505,11 +8502,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p
8505 const pt = sema.pt;8502 const pt = sema.pt;
8506 const zcu = pt.zcu;8503 const zcu = pt.zcu;
8507 if (payload_ty.zigTypeTag(zcu) == .@"opaque") {8504 if (payload_ty.zigTypeTag(zcu) == .@"opaque") {
8508 return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{8505 return sema.fail(block, payload_src, "error union with payload of opaque type '{f}' not allowed", .{
8509 payload_ty.fmt(pt),8506 payload_ty.fmt(pt),
8510 });8507 });
8511 } else if (payload_ty.zigTypeTag(zcu) == .error_set) {8508 } 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", .{8509 return sema.fail(block, payload_src, "error union with payload of error set type '{f}' not allowed", .{
8513 payload_ty.fmt(pt),8510 payload_ty.fmt(pt),
8514 });8511 });
8515 }8512 }
...@@ -8647,9 +8644,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8647,9 +8644,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8647 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);8644 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);
8648 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);8645 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);
8649 if (lhs_ty.zigTypeTag(zcu) != .error_set)8646 if (lhs_ty.zigTypeTag(zcu) != .error_set)
8650 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(pt)});8647 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{lhs_ty.fmt(pt)});
8651 if (rhs_ty.zigTypeTag(zcu) != .error_set)8648 if (rhs_ty.zigTypeTag(zcu) != .error_set)
8652 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(pt)});8649 return sema.fail(block, rhs_src, "expected error set type, found '{f}'", .{rhs_ty.fmt(pt)});
86538650
8654 // Anything merged with anyerror is anyerror.8651 // Anything merged with anyerror is anyerror.
8655 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {8652 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {
...@@ -8759,7 +8756,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8759,7 +8756,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8759 return sema.fail(8756 return sema.fail(
8760 block,8757 block,
8761 operand_src,8758 operand_src,
8762 "untagged union '{}' cannot be converted to integer",8759 "untagged union '{f}' cannot be converted to integer",
8763 .{operand_ty.fmt(pt)},8760 .{operand_ty.fmt(pt)},
8764 );8761 );
8765 };8762 };
...@@ -8767,7 +8764,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8767,7 +8764,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8767 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);8764 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);
8768 },8765 },
8769 else => {8766 else => {
8770 return sema.fail(block, operand_src, "expected enum or tagged union, found '{}'", .{8767 return sema.fail(block, operand_src, "expected enum or tagged union, found '{f}'", .{
8771 operand_ty.fmt(pt),8768 operand_ty.fmt(pt),
8772 });8769 });
8773 },8770 },
...@@ -8778,7 +8775,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8778,7 +8775,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8778 // TODO: use correct solution8775 // TODO: use correct solution
8779 // https://github.com/ziglang/zig/issues/159098776 // https://github.com/ziglang/zig/issues/15909
8780 if (enum_tag_ty.enumFieldCount(zcu) == 0 and !enum_tag_ty.isNonexhaustiveEnum(zcu)) {8777 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 '{}'", .{8778 return sema.fail(block, operand_src, "cannot use @intFromEnum on empty enum '{f}'", .{
8782 enum_tag_ty.fmt(pt),8779 enum_tag_ty.fmt(pt),
8783 });8780 });
8784 }8781 }
...@@ -8812,7 +8809,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8812,7 +8809,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8812 const operand_ty = sema.typeOf(operand);8809 const operand_ty = sema.typeOf(operand);
88138810
8814 if (dest_ty.zigTypeTag(zcu) != .@"enum") {8811 if (dest_ty.zigTypeTag(zcu) != .@"enum") {
8815 return sema.fail(block, src, "expected enum, found '{}'", .{dest_ty.fmt(pt)});8812 return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)});
8816 }8813 }
8817 _ = try sema.checkIntType(block, operand_src, operand_ty);8814 _ = try sema.checkIntType(block, operand_src, operand_ty);
88188815
...@@ -8822,7 +8819,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8822,7 +8819,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8822 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {8819 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
8823 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());8820 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());
8824 }8821 }
8825 return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{8822 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),8823 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt),
8827 });8824 });
8828 }8825 }
...@@ -8830,7 +8827,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8830,7 +8827,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8830 return sema.failWithUseOfUndef(block, operand_src);8827 return sema.failWithUseOfUndef(block, operand_src);
8831 }8828 }
8832 if (!(try sema.enumHasInt(dest_ty, int_val))) {8829 if (!(try sema.enumHasInt(dest_ty, int_val))) {
8833 return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{8830 return sema.fail(block, src, "enum '{f}' has no tag with value '{f}'", .{
8834 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),8831 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),
8835 });8832 });
8836 }8833 }
...@@ -9024,7 +9021,7 @@ fn zirErrUnionPayload(...@@ -9024,7 +9021,7 @@ fn zirErrUnionPayload(
9024 const operand_src = src;9021 const operand_src = src;
9025 const err_union_ty = sema.typeOf(operand);9022 const err_union_ty = sema.typeOf(operand);
9026 if (err_union_ty.zigTypeTag(zcu) != .error_union) {9023 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
9027 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{9024 return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{
9028 err_union_ty.fmt(pt),9025 err_union_ty.fmt(pt),
9029 });9026 });
9030 }9027 }
...@@ -9092,7 +9089,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -9092,7 +9089,7 @@ fn analyzeErrUnionPayloadPtr(
9092 assert(operand_ty.zigTypeTag(zcu) == .pointer);9089 assert(operand_ty.zigTypeTag(zcu) == .pointer);
90939090
9094 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {9091 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {
9095 return sema.fail(block, src, "expected error union type, found '{}'", .{9092 return sema.fail(block, src, "expected error union type, found '{f}'", .{
9096 operand_ty.childType(zcu).fmt(pt),9093 operand_ty.childType(zcu).fmt(pt),
9097 });9094 });
9098 }9095 }
...@@ -9169,7 +9166,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air...@@ -9169,7 +9166,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
9169 const zcu = pt.zcu;9166 const zcu = pt.zcu;
9170 const operand_ty = sema.typeOf(operand);9167 const operand_ty = sema.typeOf(operand);
9171 if (operand_ty.zigTypeTag(zcu) != .error_union) {9168 if (operand_ty.zigTypeTag(zcu) != .error_union) {
9172 return sema.fail(block, src, "expected error union type, found '{}'", .{9169 return sema.fail(block, src, "expected error union type, found '{f}'", .{
9173 operand_ty.fmt(pt),9170 operand_ty.fmt(pt),
9174 });9171 });
9175 }9172 }
...@@ -9205,7 +9202,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:...@@ -9205,7 +9202,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:
9205 assert(operand_ty.zigTypeTag(zcu) == .pointer);9202 assert(operand_ty.zigTypeTag(zcu) == .pointer);
92069203
9207 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {9204 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {
9208 return sema.fail(block, src, "expected error union type, found '{}'", .{9205 return sema.fail(block, src, "expected error union type, found '{f}'", .{
9209 operand_ty.childType(zcu).fmt(pt),9206 operand_ty.childType(zcu).fmt(pt),
9210 });9207 });
9211 }9208 }
...@@ -9450,19 +9447,17 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {...@@ -9450,19 +9447,17 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
9450fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {9447fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {
9451 const CallingConventionsSupportingVarArgsList = struct {9448 const CallingConventionsSupportingVarArgsList = struct {
9452 arch: std.Target.Cpu.Arch,9449 arch: std.Target.Cpu.Arch,
9453 pub fn format(ctx: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {9450 pub fn format(ctx: @This(), w: *std.io.Writer) std.io.Writer.Error!void {
9454 _ = fmt;
9455 _ = options;
9456 var first = true;9451 var first = true;
9457 for (calling_conventions_supporting_var_args) |cc_inner| {9452 for (calling_conventions_supporting_var_args) |cc_inner| {
9458 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {9453 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {
9459 if (supported_arch == ctx.arch) break;9454 if (supported_arch == ctx.arch) break;
9460 } else continue; // callconv not supported by this arch9455 } else continue; // callconv not supported by this arch
9461 if (!first) {9456 if (!first) {
9462 try writer.writeAll(", ");9457 try w.writeAll(", ");
9463 }9458 }
9464 first = false;9459 first = false;
9465 try writer.print("'{s}'", .{@tagName(cc_inner)});9460 try w.print("'{s}'", .{@tagName(cc_inner)});
9466 }9461 }
9467 }9462 }
9468 };9463 };
...@@ -9472,7 +9467,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:...@@ -9472,7 +9467,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)});9467 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});
9473 errdefer msg.destroy(sema.gpa);9468 errdefer msg.destroy(sema.gpa);
9474 const target = sema.pt.zcu.getTarget();9469 const target = sema.pt.zcu.getTarget();
9475 try sema.errNote(src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});9470 try sema.errNote(src, msg, "supported calling conventions: {f}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});
9476 break :msg msg;9471 break :msg msg;
9477 });9472 });
9478 }9473 }
...@@ -9520,7 +9515,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)...@@ -9520,7 +9515,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)
9520 }9515 }
95219516
9522 return sema.failWithOwnedErrorMsg(block, msg: {9517 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)});9518 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);9519 errdefer msg.destroy(sema.gpa);
95259520
9526 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;9521 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;
...@@ -9598,13 +9593,13 @@ fn funcCommon(...@@ -9598,13 +9593,13 @@ fn funcCommon(
9598 }9593 }
9599 if (!param_ty.isValidParamType(zcu)) {9594 if (!param_ty.isValidParamType(zcu)) {
9600 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9595 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9601 return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{9596 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
9602 opaque_str, param_ty.fmt(pt),9597 opaque_str, param_ty.fmt(pt),
9603 });9598 });
9604 }9599 }
9605 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {9600 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {
9606 const msg = msg: {9601 const msg = msg: {
9607 const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{9602 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),9603 param_ty.fmt(pt), @tagName(cc),
9609 });9604 });
9610 errdefer msg.destroy(sema.gpa);9605 errdefer msg.destroy(sema.gpa);
...@@ -9618,7 +9613,7 @@ fn funcCommon(...@@ -9618,7 +9613,7 @@ fn funcCommon(
9618 }9613 }
9619 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {9614 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
9620 const msg = msg: {9615 const msg = msg: {
9621 const msg = try sema.errMsg(param_src, "parameter of type '{}' must be declared comptime", .{9616 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
9622 param_ty.fmt(pt),9617 param_ty.fmt(pt),
9623 });9618 });
9624 errdefer msg.destroy(sema.gpa);9619 errdefer msg.destroy(sema.gpa);
...@@ -9798,7 +9793,7 @@ fn finishFunc(...@@ -9798,7 +9793,7 @@ fn finishFunc(
97989793
9799 if (!return_type.isValidReturnType(zcu)) {9794 if (!return_type.isValidReturnType(zcu)) {
9800 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9795 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9801 return sema.fail(block, ret_ty_src, "{s}return type '{}' not allowed", .{9796 return sema.fail(block, ret_ty_src, "{s}return type '{f}' not allowed", .{
9802 opaque_str, return_type.fmt(pt),9797 opaque_str, return_type.fmt(pt),
9803 });9798 });
9804 }9799 }
...@@ -9806,7 +9801,7 @@ fn finishFunc(...@@ -9806,7 +9801,7 @@ fn finishFunc(
9806 !try sema.validateExternType(return_type, .ret_ty))9801 !try sema.validateExternType(return_type, .ret_ty))
9807 {9802 {
9808 const msg = msg: {9803 const msg = msg: {
9809 const msg = try sema.errMsg(ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{9804 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),9805 return_type.fmt(pt), @tagName(cc_resolved),
9811 });9806 });
9812 errdefer msg.destroy(gpa);9807 errdefer msg.destroy(gpa);
...@@ -9828,7 +9823,7 @@ fn finishFunc(...@@ -9828,7 +9823,7 @@ fn finishFunc(
98289823
9829 const msg = try sema.errMsg(9824 const msg = try sema.errMsg(
9830 ret_ty_src,9825 ret_ty_src,
9831 "function with comptime-only return type '{}' requires all parameters to be comptime",9826 "function with comptime-only return type '{f}' requires all parameters to be comptime",
9832 .{return_type.fmt(pt)},9827 .{return_type.fmt(pt)},
9833 );9828 );
9834 errdefer msg.destroy(sema.gpa);9829 errdefer msg.destroy(sema.gpa);
...@@ -9897,17 +9892,15 @@ fn finishFunc(...@@ -9897,17 +9892,15 @@ fn finishFunc(
9897 .bad_arch => |allowed_archs| {9892 .bad_arch => |allowed_archs| {
9898 const ArchListFormatter = struct {9893 const ArchListFormatter = struct {
9899 archs: []const std.Target.Cpu.Arch,9894 archs: []const std.Target.Cpu.Arch,
9900 pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {9895 pub fn format(formatter: @This(), w: *std.io.Writer) std.io.Writer.Error!void {
9901 _ = fmt;
9902 _ = options;
9903 for (formatter.archs, 0..) |arch, i| {9896 for (formatter.archs, 0..) |arch, i| {
9904 if (i != 0)9897 if (i != 0)
9905 try writer.writeAll(", ");9898 try w.writeAll(", ");
9906 try writer.print("'{s}'", .{@tagName(arch)});9899 try w.print("'{s}'", .{@tagName(arch)});
9907 }9900 }
9908 }9901 }
9909 };9902 };
9910 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {}", .{9903 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {f}", .{
9911 @tagName(cc_resolved),9904 @tagName(cc_resolved),
9912 ArchListFormatter{ .archs = allowed_archs },9905 ArchListFormatter{ .archs = allowed_archs },
9913 });9906 });
...@@ -10008,7 +10001,7 @@ fn analyzeAs(...@@ -10008,7 +10001,7 @@ fn analyzeAs(
10008 const operand = try sema.resolveInst(zir_operand);10001 const operand = try sema.resolveInst(zir_operand);
10009 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;10002 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
10010 switch (dest_ty.zigTypeTag(zcu)) {10003 switch (dest_ty.zigTypeTag(zcu)) {
10011 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{}'", .{dest_ty.fmt(pt)}),10004 .@"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", .{}),10005 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
10013 else => {},10006 else => {},
10014 }10007 }
...@@ -10036,12 +10029,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10036,12 +10029,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10036 const ptr_ty = operand_ty.scalarType(zcu);10029 const ptr_ty = operand_ty.scalarType(zcu);
10037 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;10030 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
10038 if (!ptr_ty.isPtrAtRuntime(zcu)) {10031 if (!ptr_ty.isPtrAtRuntime(zcu)) {
10039 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(pt)});10032 return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)});
10040 }10033 }
10041 const pointee_ty = ptr_ty.childType(zcu);10034 const pointee_ty = ptr_ty.childType(zcu);
10042 if (try ptr_ty.comptimeOnlySema(pt)) {10035 if (try ptr_ty.comptimeOnlySema(pt)) {
10043 const msg = msg: {10036 const msg = msg: {
10044 const msg = try sema.errMsg(ptr_src, "comptime-only type '{}' has no pointer address", .{pointee_ty.fmt(pt)});10037 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);10038 errdefer msg.destroy(sema.gpa);
10046 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);10039 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);
10047 break :msg msg;10040 break :msg msg;
...@@ -10289,14 +10282,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10289,14 +10282,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10289 .type,10282 .type,
10290 .undefined,10283 .undefined,
10291 .void,10284 .void,
10292 => return sema.fail(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)}),10285 => return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}),
1029310286
10294 .@"enum" => {10287 .@"enum" => {
10295 const msg = msg: {10288 const msg = msg: {
10296 const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)});10289 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
10297 errdefer msg.destroy(sema.gpa);10290 errdefer msg.destroy(sema.gpa);
10298 switch (operand_ty.zigTypeTag(zcu)) {10291 switch (operand_ty.zigTypeTag(zcu)) {
10299 .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(pt)}),10292 .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
10300 else => {},10293 else => {},
10301 }10294 }
1030210295
...@@ -10307,11 +10300,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10307,11 +10300,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1030710300
10308 .pointer => {10301 .pointer => {
10309 const msg = msg: {10302 const msg = msg: {
10310 const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)});10303 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
10311 errdefer msg.destroy(sema.gpa);10304 errdefer msg.destroy(sema.gpa);
10312 switch (operand_ty.zigTypeTag(zcu)) {10305 switch (operand_ty.zigTypeTag(zcu)) {
10313 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(pt)}),10306 .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)}),10307 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}),
10315 else => {},10308 else => {},
10316 }10309 }
1031710310
...@@ -10325,7 +10318,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10325,7 +10318,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10325 .@"union" => "union",10318 .@"union" => "union",
10326 else => unreachable,10319 else => unreachable,
10327 };10320 };
10328 return sema.fail(block, src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{10321 return sema.fail(block, src, "cannot @bitCast to '{f}'; {s} does not have a guaranteed in-memory layout", .{
10329 dest_ty.fmt(pt), container,10322 dest_ty.fmt(pt), container,
10330 });10323 });
10331 },10324 },
...@@ -10353,14 +10346,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10353,14 +10346,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10353 .type,10346 .type,
10354 .undefined,10347 .undefined,
10355 .void,10348 .void,
10356 => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)}),10349 => return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)}),
1035710350
10358 .@"enum" => {10351 .@"enum" => {
10359 const msg = msg: {10352 const msg = msg: {
10360 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)});10353 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
10361 errdefer msg.destroy(sema.gpa);10354 errdefer msg.destroy(sema.gpa);
10362 switch (dest_ty.zigTypeTag(zcu)) {10355 switch (dest_ty.zigTypeTag(zcu)) {
10363 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{}'", .{dest_ty.fmt(pt)}),10356 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{f}'", .{dest_ty.fmt(pt)}),
10364 else => {},10357 else => {},
10365 }10358 }
1036610359
...@@ -10370,11 +10363,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10370,11 +10363,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10370 },10363 },
10371 .pointer => {10364 .pointer => {
10372 const msg = msg: {10365 const msg = msg: {
10373 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)});10366 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
10374 errdefer msg.destroy(sema.gpa);10367 errdefer msg.destroy(sema.gpa);
10375 switch (dest_ty.zigTypeTag(zcu)) {10368 switch (dest_ty.zigTypeTag(zcu)) {
10376 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{}'", .{dest_ty.fmt(pt)}),10369 .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)}),10370 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}),
10378 else => {},10371 else => {},
10379 }10372 }
1038010373
...@@ -10388,7 +10381,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10388,7 +10381,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10388 .@"union" => "union",10381 .@"union" => "union",
10389 else => unreachable,10382 else => unreachable,
10390 };10383 };
10391 return sema.fail(block, operand_src, "cannot @bitCast from '{}'; {s} does not have a guaranteed in-memory layout", .{10384 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,10385 operand_ty.fmt(pt), container,
10393 });10386 });
10394 },10387 },
...@@ -10431,7 +10424,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10431,7 +10424,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10431 else => return sema.fail(10424 else => return sema.fail(
10432 block,10425 block,
10433 src,10426 src,
10434 "expected float or vector type, found '{}'",10427 "expected float or vector type, found '{f}'",
10435 .{dest_ty.fmt(pt)},10428 .{dest_ty.fmt(pt)},
10436 ),10429 ),
10437 };10430 };
...@@ -10441,7 +10434,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10441,7 +10434,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10441 else => return sema.fail(10434 else => return sema.fail(
10442 block,10435 block,
10443 operand_src,10436 operand_src,
10444 "expected float or vector type, found '{}'",10437 "expected float or vector type, found '{f}'",
10445 .{operand_ty.fmt(pt)},10438 .{operand_ty.fmt(pt)},
10446 ),10439 ),
10447 }10440 }
...@@ -10525,7 +10518,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10525,7 +10518,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10525 if (indexable_ty.zigTypeTag(zcu) != .pointer) {10518 if (indexable_ty.zigTypeTag(zcu) != .pointer) {
10526 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });10519 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });
10527 const msg = msg: {10520 const msg = msg: {
10528 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{}'", .{10521 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{f}'", .{
10529 indexable_ty.fmt(pt),10522 indexable_ty.fmt(pt),
10530 });10523 });
10531 errdefer msg.destroy(sema.gpa);10524 errdefer msg.destroy(sema.gpa);
...@@ -10667,7 +10660,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -10667,7 +10660,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));10660 const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand));
10668 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {10661 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {
10669 .pointer => lhs_ptr_ty.childType(zcu),10662 .pointer => lhs_ptr_ty.childType(zcu),
10670 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{lhs_ptr_ty.fmt(pt)}),10663 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{lhs_ptr_ty.fmt(pt)}),
10671 };10664 };
1067210665
10673 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {10666 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {
...@@ -10682,7 +10675,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -10682,7 +10675,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
10682 };10675 };
10683 },10676 },
10684 },10677 },
10685 else => return sema.fail(block, src, "slice of non-array type '{}'", .{lhs_ty.fmt(pt)}),10678 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{lhs_ty.fmt(pt)}),
10686 };10679 };
1068710680
10688 return Air.internedToRef(sentinel_ty.toIntern());10681 return Air.internedToRef(sentinel_ty.toIntern());
...@@ -10877,7 +10870,7 @@ const SwitchProngAnalysis = struct {...@@ -10877,7 +10870,7 @@ const SwitchProngAnalysis = struct {
10877 .base_node_inst = capture_src.base_node_inst,10870 .base_node_inst = capture_src.base_node_inst,
10878 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },10871 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },
10879 };10872 };
10880 return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{}'", .{10873 return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{f}'", .{
10881 operand_ty.fmt(pt),10874 operand_ty.fmt(pt),
10882 });10875 });
10883 }10876 }
...@@ -11309,7 +11302,7 @@ fn switchCond(...@@ -11309,7 +11302,7 @@ fn switchCond(
11309 .@"enum",11302 .@"enum",
11310 => {11303 => {
11311 if (operand_ty.isSlice(zcu)) {11304 if (operand_ty.isSlice(zcu)) {
11312 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(pt)});11305 return sema.fail(block, src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
11313 }11306 }
11314 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {11307 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
11315 return Air.internedToRef(opv.toIntern());11308 return Air.internedToRef(opv.toIntern());
...@@ -11344,7 +11337,7 @@ fn switchCond(...@@ -11344,7 +11337,7 @@ fn switchCond(
11344 .vector,11337 .vector,
11345 .frame,11338 .frame,
11346 .@"anyframe",11339 .@"anyframe",
11347 => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(pt)}),11340 => return sema.fail(block, src, "switch on type '{f}'", .{operand_ty.fmt(pt)}),
11348 }11341 }
11349}11342}
1135011343
...@@ -11445,7 +11438,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11445,7 +11438,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11445 operand_ty;11438 operand_ty;
1144611439
11447 if (operand_err_set.zigTypeTag(zcu) != .error_union) {11440 if (operand_err_set.zigTypeTag(zcu) != .error_union) {
11448 return sema.fail(block, switch_src, "expected error union type, found '{}'", .{11441 return sema.fail(block, switch_src, "expected error union type, found '{f}'", .{
11449 operand_ty.fmt(pt),11442 operand_ty.fmt(pt),
11450 });11443 });
11451 }11444 }
...@@ -11699,7 +11692,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11699,7 +11692,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.11692 // Even if the operand is comptime-known, this `switch` is runtime.
11700 if (try operand_ty.comptimeOnlySema(pt)) {11693 if (try operand_ty.comptimeOnlySema(pt)) {
11701 return sema.failWithOwnedErrorMsg(block, msg: {11694 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)});11695 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);11696 errdefer msg.destroy(gpa);
11704 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});11697 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});
11705 break :msg msg;11698 break :msg msg;
...@@ -11923,14 +11916,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11923,14 +11916,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11923 cond_ty,11916 cond_ty,
11924 i,11917 i,
11925 msg,11918 msg,
11926 "unhandled enumeration value: '{}'",11919 "unhandled enumeration value: '{f}'",
11927 .{field_name.fmt(&zcu.intern_pool)},11920 .{field_name.fmt(&zcu.intern_pool)},
11928 );11921 );
11929 }11922 }
11930 try sema.errNote(11923 try sema.errNote(
11931 cond_ty.srcLoc(zcu),11924 cond_ty.srcLoc(zcu),
11932 msg,11925 msg,
11933 "enum '{}' declared here",11926 "enum '{f}' declared here",
11934 .{cond_ty.fmt(pt)},11927 .{cond_ty.fmt(pt)},
11935 );11928 );
11936 break :msg msg;11929 break :msg msg;
...@@ -12142,7 +12135,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12142,7 +12135,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12142 return sema.fail(12135 return sema.fail(
12143 block,12136 block,
12144 src,12137 src,
12145 "else prong required when switching on type '{}'",12138 "else prong required when switching on type '{f}'",
12146 .{cond_ty.fmt(pt)},12139 .{cond_ty.fmt(pt)},
12147 );12140 );
12148 }12141 }
...@@ -12218,7 +12211,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12218,7 +12211,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12218 .@"anyframe",12211 .@"anyframe",
12219 .comptime_float,12212 .comptime_float,
12220 .float,12213 .float,
12221 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{12214 => return sema.fail(block, operand_src, "invalid switch operand type '{f}'", .{
12222 raw_operand_ty.fmt(pt),12215 raw_operand_ty.fmt(pt),
12223 }),12216 }),
12224 }12217 }
...@@ -12747,7 +12740,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12747,7 +12740,7 @@ fn analyzeSwitchRuntimeBlock(
12747 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {12740 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {
12748 .@"enum" => {12741 .@"enum" => {
12749 if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) {12742 if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) {
12750 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{12743 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
12751 operand_ty.fmt(pt),12744 operand_ty.fmt(pt),
12752 });12745 });
12753 }12746 }
...@@ -12803,7 +12796,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12803,7 +12796,7 @@ fn analyzeSwitchRuntimeBlock(
12803 },12796 },
12804 .error_set => {12797 .error_set => {
12805 if (operand_ty.isAnyError(zcu)) {12798 if (operand_ty.isAnyError(zcu)) {
12806 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{12799 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
12807 operand_ty.fmt(pt),12800 operand_ty.fmt(pt),
12808 });12801 });
12809 }12802 }
...@@ -12964,7 +12957,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12964,7 +12957,7 @@ fn analyzeSwitchRuntimeBlock(
12964 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));12957 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));
12965 }12958 }
12966 },12959 },
12967 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{12960 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
12968 operand_ty.fmt(pt),12961 operand_ty.fmt(pt),
12969 }),12962 }),
12970 };12963 };
...@@ -13478,7 +13471,7 @@ fn validateErrSetSwitch(...@@ -13478,7 +13471,7 @@ fn validateErrSetSwitch(
13478 try sema.errNote(13471 try sema.errNote(
13479 src,13472 src,
13480 msg,13473 msg,
13481 "unhandled error value: 'error.{}'",13474 "unhandled error value: 'error.{f}'",
13482 .{error_name.fmt(ip)},13475 .{error_name.fmt(ip)},
13483 );13476 );
13484 }13477 }
...@@ -13704,7 +13697,7 @@ fn validateSwitchNoRange(...@@ -13704,7 +13697,7 @@ fn validateSwitchNoRange(
13704 const msg = msg: {13697 const msg = msg: {
13705 const msg = try sema.errMsg(13698 const msg = try sema.errMsg(
13706 operand_src,13699 operand_src,
13707 "ranges not allowed when switching on type '{}'",13700 "ranges not allowed when switching on type '{f}'",
13708 .{operand_ty.fmt(sema.pt)},13701 .{operand_ty.fmt(sema.pt)},
13709 );13702 );
13710 errdefer msg.destroy(sema.gpa);13703 errdefer msg.destroy(sema.gpa);
...@@ -13862,7 +13855,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13862,7 +13855,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13862 .array_type => break :hf field_name.eqlSlice("len", ip),13855 .array_type => break :hf field_name.eqlSlice("len", ip),
13863 else => {},13856 else => {},
13864 }13857 }
13865 return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{13858 return sema.fail(block, ty_src, "type '{f}' does not support '@hasField'", .{
13866 ty.fmt(pt),13859 ty.fmt(pt),
13867 });13860 });
13868 };13861 };
...@@ -14050,7 +14043,7 @@ fn zirShl(...@@ -14050,7 +14043,7 @@ fn zirShl(
14050 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14043 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14051 const rhs_elem = try rhs_val.elemValue(pt, i);14044 const rhs_elem = try rhs_val.elemValue(pt, i);
14052 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {14045 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 '{}'", .{14046 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),14047 rhs_elem.fmtValueSema(pt, sema),
14055 i,14048 i,
14056 scalar_ty.fmt(pt),14049 scalar_ty.fmt(pt),
...@@ -14058,7 +14051,7 @@ fn zirShl(...@@ -14058,7 +14051,7 @@ fn zirShl(
14058 }14051 }
14059 }14052 }
14060 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {14053 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {
14061 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{14054 return sema.fail(block, rhs_src, "shift amount '{f}' is too large for operand type '{f}'", .{
14062 rhs_val.fmtValueSema(pt, sema),14055 rhs_val.fmtValueSema(pt, sema),
14063 scalar_ty.fmt(pt),14056 scalar_ty.fmt(pt),
14064 });14057 });
...@@ -14069,19 +14062,19 @@ fn zirShl(...@@ -14069,19 +14062,19 @@ fn zirShl(
14069 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14062 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14070 const rhs_elem = try rhs_val.elemValue(pt, i);14063 const rhs_elem = try rhs_val.elemValue(pt, i);
14071 if (rhs_elem.compareHetero(.lt, try pt.intValue(scalar_rhs_ty, 0), zcu)) {14064 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}'", .{14065 return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
14073 rhs_elem.fmtValueSema(pt, sema),14066 rhs_elem.fmtValueSema(pt, sema),
14074 i,14067 i,
14075 });14068 });
14076 }14069 }
14077 }14070 }
14078 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {14071 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
14079 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{14072 return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
14080 rhs_val.fmtValueSema(pt, sema),14073 rhs_val.fmtValueSema(pt, sema),
14081 });14074 });
14082 }14075 }
14083 } else if (scalar_rhs_ty.isSignedInt(zcu)) {14076 } else if (scalar_rhs_ty.isSignedInt(zcu)) {
14084 return sema.fail(block, rhs_src, "shift by signed type '{}'", .{rhs_ty.fmt(pt)});14077 return sema.fail(block, rhs_src, "shift by signed type '{f}'", .{rhs_ty.fmt(pt)});
14085 }14078 }
1408614079
14087 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {14080 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {
...@@ -14231,7 +14224,7 @@ fn zirShr(...@@ -14231,7 +14224,7 @@ fn zirShr(
14231 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14224 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14232 const rhs_elem = try rhs_val.elemValue(pt, i);14225 const rhs_elem = try rhs_val.elemValue(pt, i);
14233 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {14226 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 '{}'", .{14227 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),14228 rhs_elem.fmtValueSema(pt, sema),
14236 i,14229 i,
14237 scalar_ty.fmt(pt),14230 scalar_ty.fmt(pt),
...@@ -14239,7 +14232,7 @@ fn zirShr(...@@ -14239,7 +14232,7 @@ fn zirShr(
14239 }14232 }
14240 }14233 }
14241 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {14234 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {
14242 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{14235 return sema.fail(block, rhs_src, "shift amount '{f}' is too large for operand type '{f}'", .{
14243 rhs_val.fmtValueSema(pt, sema),14236 rhs_val.fmtValueSema(pt, sema),
14244 scalar_ty.fmt(pt),14237 scalar_ty.fmt(pt),
14245 });14238 });
...@@ -14250,14 +14243,14 @@ fn zirShr(...@@ -14250,14 +14243,14 @@ fn zirShr(
14250 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14243 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14251 const rhs_elem = try rhs_val.elemValue(pt, i);14244 const rhs_elem = try rhs_val.elemValue(pt, i);
14252 if (rhs_elem.compareHetero(.lt, try pt.intValue(rhs_ty.childType(zcu), 0), zcu)) {14245 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}'", .{14246 return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
14254 rhs_elem.fmtValueSema(pt, sema),14247 rhs_elem.fmtValueSema(pt, sema),
14255 i,14248 i,
14256 });14249 });
14257 }14250 }
14258 }14251 }
14259 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {14252 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
14260 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{14253 return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
14261 rhs_val.fmtValueSema(pt, sema),14254 rhs_val.fmtValueSema(pt, sema),
14262 });14255 });
14263 }14256 }
...@@ -14386,7 +14379,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14386,7 +14379,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14386 const scalar_tag = scalar_ty.zigTypeTag(zcu);14379 const scalar_tag = scalar_ty.zigTypeTag(zcu);
1438714380
14388 if (scalar_tag != .int and scalar_tag != .bool)14381 if (scalar_tag != .int and scalar_tag != .bool)
14389 return sema.fail(block, operand_src, "bitwise not operation on type '{}'", .{operand_ty.fmt(pt)});14382 return sema.fail(block, operand_src, "bitwise not operation on type '{f}'", .{operand_ty.fmt(pt)});
1439014383
14391 return analyzeBitNot(sema, block, operand, src);14384 return analyzeBitNot(sema, block, operand, src);
14392}14385}
...@@ -14543,11 +14536,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14543,11 +14536,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1454314536
14544 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {14537 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {
14545 if (lhs_is_tuple) break :lhs_info undefined;14538 if (lhs_is_tuple) break :lhs_info undefined;
14546 return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)});14539 return sema.fail(block, lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
14547 };14540 };
14548 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {14541 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {
14549 assert(!rhs_is_tuple);14542 assert(!rhs_is_tuple);
14550 return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(pt)});14543 return sema.fail(block, rhs_src, "expected indexable; found '{f}'", .{rhs_ty.fmt(pt)});
14551 };14544 };
1455214545
14553 const resolved_elem_ty = t: {14546 const resolved_elem_ty = t: {
...@@ -15000,7 +14993,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15000,7 +14993,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 exponentiation14993 // 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 {14994 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
15002 const msg = msg: {14995 const msg = msg: {
15003 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)});14996 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
15004 errdefer msg.destroy(sema.gpa);14997 errdefer msg.destroy(sema.gpa);
15005 switch (lhs_ty.zigTypeTag(zcu)) {14998 switch (lhs_ty.zigTypeTag(zcu)) {
15006 .int, .float, .comptime_float, .comptime_int, .vector => {14999 .int, .float, .comptime_float, .comptime_int, .vector => {
...@@ -15132,7 +15125,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15132,7 +15125,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15132 .int, .comptime_int, .float, .comptime_float => false,15125 .int, .comptime_int, .float, .comptime_float => false,
15133 else => true,15126 else => true,
15134 }) {15127 }) {
15135 return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(pt)});15128 return sema.fail(block, src, "negation of type '{f}'", .{rhs_ty.fmt(pt)});
15136 }15129 }
1513715130
15138 if (rhs_scalar_ty.isAnyFloat()) {15131 if (rhs_scalar_ty.isAnyFloat()) {
...@@ -15163,7 +15156,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -15163,7 +15156,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1516315156
15164 switch (rhs_scalar_ty.zigTypeTag(zcu)) {15157 switch (rhs_scalar_ty.zigTypeTag(zcu)) {
15165 .int, .comptime_int, .float, .comptime_float => {},15158 .int, .comptime_int, .float, .comptime_float => {},
15166 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(pt)}),15159 else => return sema.fail(block, src, "negation of type '{f}'", .{rhs_ty.fmt(pt)}),
15167 }15160 }
1516815161
15169 const lhs = Air.internedToRef((try sema.splat(rhs_ty, try pt.intValue(rhs_scalar_ty, 0))).toIntern());15162 const lhs = Air.internedToRef((try sema.splat(rhs_ty, try pt.intValue(rhs_scalar_ty, 0))).toIntern());
...@@ -15237,7 +15230,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15237,7 +15230,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15237 return sema.fail(15230 return sema.fail(
15238 block,15231 block,
15239 src,15232 src,
15240 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",15233 "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) },15234 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), rem.fmtValueSema(pt, sema) },
15242 );15235 );
15243 }15236 }
...@@ -15289,7 +15282,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15289,7 +15282,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15289 return sema.fail(15282 return sema.fail(
15290 block,15283 block,
15291 src,15284 src,
15292 "division with '{}' and '{}': signed integers must use @divTrunc, @divFloor, or @divExact",15285 "division with '{f}' and '{f}': signed integers must use @divTrunc, @divFloor, or @divExact",
15293 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },15286 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },
15294 );15287 );
15295 }15288 }
...@@ -15951,7 +15944,7 @@ fn zirOverflowArithmetic(...@@ -15951,7 +15944,7 @@ fn zirOverflowArithmetic(
15951 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);15944 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);
1595215945
15953 if (dest_ty.scalarType(zcu).zigTypeTag(zcu) != .int) {15946 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)});15947 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{f}'", .{dest_ty.fmt(pt)});
15955 }15948 }
1595615949
15957 const maybe_lhs_val = try sema.resolveValue(lhs);15950 const maybe_lhs_val = try sema.resolveValue(lhs);
...@@ -16157,14 +16150,14 @@ fn analyzeArithmetic(...@@ -16157,14 +16150,14 @@ fn analyzeArithmetic(
16157 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");16150 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");
16158 }16151 }
16159 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {16152 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {
16160 return sema.fail(block, src, "incompatible pointer arithmetic operands '{}' and '{}'", .{16153 return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{
16161 lhs_ty.fmt(pt), rhs_ty.fmt(pt),16154 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
16162 });16155 });
16163 }16156 }
1616416157
16165 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);16158 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
16166 if (elem_size == 0) {16159 if (elem_size == 0) {
16167 return sema.fail(block, src, "pointer arithmetic requires element type '{}' to have runtime bits", .{16160 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
16168 lhs_ty.elemType2(zcu).fmt(pt),16161 lhs_ty.elemType2(zcu).fmt(pt),
16169 });16162 });
16170 }16163 }
...@@ -16215,7 +16208,7 @@ fn analyzeArithmetic(...@@ -16215,7 +16208,7 @@ fn analyzeArithmetic(
16215 };16208 };
1621616209
16217 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {16210 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {
16218 return sema.fail(block, src, "pointer arithmetic requires element type '{}' to have runtime bits", .{16211 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
16219 lhs_ty.elemType2(zcu).fmt(pt),16212 lhs_ty.elemType2(zcu).fmt(pt),
16220 });16213 });
16221 }16214 }
...@@ -16619,7 +16612,7 @@ fn zirCmpEq(...@@ -16619,7 +16612,7 @@ fn zirCmpEq(
1661916612
16620 if (lhs_ty_tag == .null or rhs_ty_tag == .null) {16613 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;16614 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)});16615 return sema.fail(block, src, "comparison of '{f}' with null", .{non_null_type.fmt(pt)});
16623 }16616 }
1662416617
16625 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {16618 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {
...@@ -16676,7 +16669,7 @@ fn analyzeCmpUnionTag(...@@ -16676,7 +16669,7 @@ fn analyzeCmpUnionTag(
16676 const msg = msg: {16669 const msg = msg: {
16677 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});16670 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);16671 errdefer msg.destroy(sema.gpa);
16679 try sema.errNote(union_ty.srcLoc(zcu), msg, "union '{}' is not a tagged union", .{union_ty.fmt(pt)});16672 try sema.errNote(union_ty.srcLoc(zcu), msg, "union '{f}' is not a tagged union", .{union_ty.fmt(pt)});
16680 break :msg msg;16673 break :msg msg;
16681 };16674 };
16682 return sema.failWithOwnedErrorMsg(block, msg);16675 return sema.failWithOwnedErrorMsg(block, msg);
...@@ -16762,7 +16755,7 @@ fn analyzeCmp(...@@ -16762,7 +16755,7 @@ fn analyzeCmp(
16762 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };16755 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
16763 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });16756 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
16764 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {16757 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {
16765 return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{16758 return sema.fail(block, src, "operator {s} not allowed for type '{f}'", .{
16766 compareOperatorName(op), resolved_type.fmt(pt),16759 compareOperatorName(op), resolved_type.fmt(pt),
16767 });16760 });
16768 }16761 }
...@@ -16871,7 +16864,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -16871,7 +16864,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
16871 .undefined,16864 .undefined,
16872 .null,16865 .null,
16873 .@"opaque",16866 .@"opaque",
16874 => return sema.fail(block, operand_src, "no size available for type '{}'", .{ty.fmt(pt)}),16867 => return sema.fail(block, operand_src, "no size available for type '{f}'", .{ty.fmt(pt)}),
1687516868
16876 .type,16869 .type,
16877 .enum_literal,16870 .enum_literal,
...@@ -16912,7 +16905,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -16912,7 +16905,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16912 .undefined,16905 .undefined,
16913 .null,16906 .null,
16914 .@"opaque",16907 .@"opaque",
16915 => return sema.fail(block, operand_src, "no size available for type '{}'", .{operand_ty.fmt(pt)}),16908 => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}),
1691616909
16917 .type,16910 .type,
16918 .enum_literal,16911 .enum_literal,
...@@ -17002,7 +16995,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17002,7 +16995,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17002 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;16995 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;
17003 const tree = file.getTree(zcu) catch |err| {16996 const tree = file.getTree(zcu) catch |err| {
17004 // In this case we emit a warning + a less precise source location.16997 // In this case we emit a warning + a less precise source location.
17005 log.warn("unable to load {}: {s}", .{16998 log.warn("unable to load {f}: {s}", .{
17006 file.path.fmt(zcu.comp), @errorName(err),16999 file.path.fmt(zcu.comp), @errorName(err),
17007 });17000 });
17008 break :name null;17001 break :name null;
...@@ -17030,7 +17023,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17030,7 +17023,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17030 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;17023 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;
17031 const tree = file.getTree(zcu) catch |err| {17024 const tree = file.getTree(zcu) catch |err| {
17032 // In this case we emit a warning + a less precise source location.17025 // In this case we emit a warning + a less precise source location.
17033 log.warn("unable to load {}: {s}", .{17026 log.warn("unable to load {f}: {s}", .{
17034 file.path.fmt(zcu.comp), @errorName(err),17027 file.path.fmt(zcu.comp), @errorName(err),
17035 });17028 });
17036 break :name null;17029 break :name null;
...@@ -18212,7 +18205,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi...@@ -18212,7 +18205,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
18212 return sema.fail(18205 return sema.fail(
18213 block,18206 block,
18214 src,18207 src,
18215 "bit shifting operation expected integer type, found '{}'",18208 "bit shifting operation expected integer type, found '{f}'",
18216 .{operand.fmt(pt)},18209 .{operand.fmt(pt)},
18217 );18210 );
18218}18211}
...@@ -18271,7 +18264,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18271,7 +18264,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18271 const uncasted_ty = sema.typeOf(uncasted_operand);18264 const uncasted_ty = sema.typeOf(uncasted_operand);
18272 if (uncasted_ty.isVector(zcu)) {18265 if (uncasted_ty.isVector(zcu)) {
18273 if (uncasted_ty.scalarType(zcu).zigTypeTag(zcu) != .bool) {18266 if (uncasted_ty.scalarType(zcu).zigTypeTag(zcu) != .bool) {
18274 return sema.fail(block, operand_src, "boolean not operation on type '{}'", .{18267 return sema.fail(block, operand_src, "boolean not operation on type '{f}'", .{
18275 uncasted_ty.fmt(pt),18268 uncasted_ty.fmt(pt),
18276 });18269 });
18277 }18270 }
...@@ -18451,7 +18444,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi...@@ -18451,7 +18444,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi
18451 const pt = sema.pt;18444 const pt = sema.pt;
18452 const zcu = pt.zcu;18445 const zcu = pt.zcu;
18453 if (!ty.isSelfComparable(zcu, true)) {18446 if (!ty.isSelfComparable(zcu, true)) {
18454 return sema.fail(block, src, "non-scalar sentinel type '{}'", .{ty.fmt(pt)});18447 return sema.fail(block, src, "non-scalar sentinel type '{f}'", .{ty.fmt(pt)});
18455 }18448 }
18456}18449}
1845718450
...@@ -18501,7 +18494,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -18501,7 +18494,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
18501 const zcu = pt.zcu;18494 const zcu = pt.zcu;
18502 switch (ty.zigTypeTag(zcu)) {18495 switch (ty.zigTypeTag(zcu)) {
18503 .error_set, .error_union, .undefined => return,18496 .error_set, .error_union, .undefined => return,
18504 else => return sema.fail(block, src, "expected error union type, found '{}'", .{18497 else => return sema.fail(block, src, "expected error union type, found '{f}'", .{
18505 ty.fmt(pt),18498 ty.fmt(pt),
18506 }),18499 }),
18507 }18500 }
...@@ -18645,7 +18638,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -18645,7 +18638,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
18645 const pt = sema.pt;18638 const pt = sema.pt;
18646 const zcu = pt.zcu;18639 const zcu = pt.zcu;
18647 if (err_union_ty.zigTypeTag(zcu) != .error_union) {18640 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
18648 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{18641 return sema.fail(parent_block, operand_src, "expected error union type, found '{f}'", .{
18649 err_union_ty.fmt(pt),18642 err_union_ty.fmt(pt),
18650 });18643 });
18651 }18644 }
...@@ -18705,7 +18698,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -18705,7 +18698,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
18705 const pt = sema.pt;18698 const pt = sema.pt;
18706 const zcu = pt.zcu;18699 const zcu = pt.zcu;
18707 if (err_union_ty.zigTypeTag(zcu) != .error_union) {18700 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
18708 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{18701 return sema.fail(parent_block, operand_src, "expected error union type, found '{f}'", .{
18709 err_union_ty.fmt(pt),18702 err_union_ty.fmt(pt),
18710 });18703 });
18711 }18704 }
...@@ -18903,7 +18896,7 @@ fn zirRetImplicit(...@@ -18903,7 +18896,7 @@ fn zirRetImplicit(
18903 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);18896 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
18904 if (base_tag == .noreturn) {18897 if (base_tag == .noreturn) {
18905 const msg = msg: {18898 const msg = msg: {
18906 const msg = try sema.errMsg(ret_ty_src, "function declared '{}' implicitly returns", .{18899 const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{
18907 sema.fn_ret_ty.fmt(pt),18900 sema.fn_ret_ty.fmt(pt),
18908 });18901 });
18909 errdefer msg.destroy(sema.gpa);18902 errdefer msg.destroy(sema.gpa);
...@@ -18913,7 +18906,7 @@ fn zirRetImplicit(...@@ -18913,7 +18906,7 @@ fn zirRetImplicit(
18913 return sema.failWithOwnedErrorMsg(block, msg);18906 return sema.failWithOwnedErrorMsg(block, msg);
18914 } else if (base_tag != .void) {18907 } else if (base_tag != .void) {
18915 const msg = msg: {18908 const msg = msg: {
18916 const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{}' implicitly returns", .{18909 const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{f}' implicitly returns", .{
18917 sema.fn_ret_ty.fmt(pt),18910 sema.fn_ret_ty.fmt(pt),
18918 });18911 });
18919 errdefer msg.destroy(sema.gpa);18912 errdefer msg.destroy(sema.gpa);
...@@ -19302,13 +19295,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19302,13 +19295,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1930219295
19303 if (host_size != 0) {19296 if (host_size != 0) {
19304 if (bit_offset >= host_size * 8) {19297 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", .{19298 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} starts {d} bits after the end of a {d} byte host integer", .{
19306 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,19299 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,
19307 });19300 });
19308 }19301 }
19309 const elem_bit_size = try elem_ty.bitSizeSema(pt);19302 const elem_bit_size = try elem_ty.bitSizeSema(pt);
19310 if (elem_bit_size > host_size * 8 - bit_offset) {19303 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", .{19304 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{
19312 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,19305 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
19313 });19306 });
19314 }19307 }
...@@ -19323,7 +19316,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19323,7 +19316,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19323 } else if (inst_data.size == .c) {19316 } else if (inst_data.size == .c) {
19324 if (!try sema.validateExternType(elem_ty, .other)) {19317 if (!try sema.validateExternType(elem_ty, .other)) {
19325 const msg = msg: {19318 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)});19319 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);19320 errdefer msg.destroy(sema.gpa);
1932819321
19329 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);19322 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);
...@@ -19340,7 +19333,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19340,7 +19333,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1934019333
19341 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {19334 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {
19342 return sema.failWithOwnedErrorMsg(block, msg: {19335 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)});19336 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);19337 errdefer msg.destroy(sema.gpa);
19345 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);19338 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);
19346 break :msg msg;19339 break :msg msg;
...@@ -19509,7 +19502,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19509,7 +19502,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;19502 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);19503 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);
19511 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {19504 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {
19512 return sema.fail(block, ty_src, "expected union type, found '{}'", .{union_ty.fmt(pt)});19505 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});
19513 }19506 }
19514 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });19507 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });
19515 const init = try sema.resolveInst(extra.init);19508 const init = try sema.resolveInst(extra.init);
...@@ -19672,7 +19665,7 @@ fn zirStructInit(...@@ -19672,7 +19665,7 @@ fn zirStructInit(
19672 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});19665 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
19673 errdefer msg.destroy(sema.gpa);19666 errdefer msg.destroy(sema.gpa);
1967419667
19675 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{}' declared here", .{19668 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{f}' declared here", .{
19676 field_name.fmt(ip),19669 field_name.fmt(ip),
19677 });19670 });
19678 try sema.addDeclaredHereNote(msg, resolved_ty);19671 try sema.addDeclaredHereNote(msg, resolved_ty);
...@@ -19791,7 +19784,7 @@ fn finishStructInit(...@@ -19791,7 +19784,7 @@ fn finishStructInit(
19791 const field_init = struct_type.fieldInit(ip, i);19784 const field_init = struct_type.fieldInit(ip, i);
19792 if (field_init == .none) {19785 if (field_init == .none) {
19793 const field_name = struct_type.field_names.get(ip)[i];19786 const field_name = struct_type.field_names.get(ip)[i];
19794 const template = "missing struct field: {}";19787 const template = "missing struct field: {f}";
19795 const args = .{field_name.fmt(ip)};19788 const args = .{field_name.fmt(ip)};
19796 if (root_msg) |msg| {19789 if (root_msg) |msg| {
19797 try sema.errNote(init_src, msg, template, args);19790 try sema.errNote(init_src, msg, template, args);
...@@ -20406,7 +20399,7 @@ fn fieldType(...@@ -20406,7 +20399,7 @@ fn fieldType(
20406 },20399 },
20407 else => {},20400 else => {},
20408 }20401 }
20409 return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{20402 return sema.fail(block, ty_src, "expected struct or union; found '{f}'", .{
20410 cur_ty.fmt(pt),20403 cur_ty.fmt(pt),
20411 });20404 });
20412 }20405 }
...@@ -20453,7 +20446,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20453,7 +20446,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20453 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);20446 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
20454 const ty = try sema.resolveType(block, operand_src, inst_data.operand);20447 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
20455 if (ty.isNoReturn(zcu)) {20448 if (ty.isNoReturn(zcu)) {
20456 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.pt)});20449 return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)});
20457 }20450 }
20458 const val = try ty.lazyAbiAlignment(sema.pt);20451 const val = try ty.lazyAbiAlignment(sema.pt);
20459 return Air.internedToRef(val.toIntern());20452 return Air.internedToRef(val.toIntern());
...@@ -20469,7 +20462,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -20469,7 +20462,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
20469 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;20462 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
20470 const operand_scalar_ty = operand_ty.scalarType(zcu);20463 const operand_scalar_ty = operand_ty.scalarType(zcu);
20471 if (operand_scalar_ty.toIntern() != .bool_type) {20464 if (operand_scalar_ty.toIntern() != .bool_type) {
20472 return sema.fail(block, src, "expected 'bool', found '{}'", .{operand_scalar_ty.zigTypeTag(zcu)});20465 return sema.fail(block, src, "expected 'bool', found '{t}'", .{operand_scalar_ty.zigTypeTag(zcu)});
20473 }20466 }
20474 const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined;20467 const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined;
20475 const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1;20468 const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1;
...@@ -20531,7 +20524,7 @@ fn zirAbs(...@@ -20531,7 +20524,7 @@ fn zirAbs(
20531 else => return sema.fail(20524 else => return sema.fail(
20532 block,20525 block,
20533 operand_src,20526 operand_src,
20534 "expected integer, float, or vector of either integers or floats, found '{}'",20527 "expected integer, float, or vector of either integers or floats, found '{f}'",
20535 .{operand_ty.fmt(pt)},20528 .{operand_ty.fmt(pt)},
20536 ),20529 ),
20537 };20530 };
...@@ -20600,7 +20593,7 @@ fn zirUnaryMath(...@@ -20600,7 +20593,7 @@ fn zirUnaryMath(
20600 else => return sema.fail(20593 else => return sema.fail(
20601 block,20594 block,
20602 operand_src,20595 operand_src,
20603 "expected vector of floats or float type, found '{}'",20596 "expected vector of floats or float type, found '{f}'",
20604 .{operand_ty.fmt(pt)},20597 .{operand_ty.fmt(pt)},
20605 ),20598 ),
20606 }20599 }
...@@ -20629,8 +20622,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20629,8 +20622,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20629 },20622 },
20630 .@"enum" => operand_ty,20623 .@"enum" => operand_ty,
20631 .@"union" => operand_ty.unionTagType(zcu) orelse20624 .@"union" => operand_ty.unionTagType(zcu) orelse
20632 return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(pt)}),20625 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 '{}'", .{20626 else => return sema.fail(block, operand_src, "expected enum or union; found '{f}'", .{
20634 operand_ty.fmt(pt),20627 operand_ty.fmt(pt),
20635 }),20628 }),
20636 };20629 };
...@@ -20638,7 +20631,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20638,7 +20631,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 but20631 // TODO I don't think this is the correct way to handle this but
20639 // it prevents a crash.20632 // it prevents a crash.
20640 // https://github.com/ziglang/zig/issues/1590920633 // https://github.com/ziglang/zig/issues/15909
20641 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{20634 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{f}'", .{
20642 enum_ty.fmt(pt),20635 enum_ty.fmt(pt),
20643 });20636 });
20644 }20637 }
...@@ -20646,7 +20639,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20646,7 +20639,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20646 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {20639 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
20647 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {20640 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {
20648 const msg = msg: {20641 const msg = msg: {
20649 const msg = try sema.errMsg(src, "no field with value '{}' in enum '{}'", .{20642 const msg = try sema.errMsg(src, "no field with value '{f}' in enum '{f}'", .{
20650 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),20643 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),
20651 });20644 });
20652 errdefer msg.destroy(sema.gpa);20645 errdefer msg.destroy(sema.gpa);
...@@ -20752,7 +20745,7 @@ fn zirReify(...@@ -20752,7 +20745,7 @@ fn zirReify(
20752 64 => .f64,20745 64 => .f64,
20753 80 => .f80,20746 80 => .f80,
20754 128 => .f128,20747 128 => .f128,
20755 else => return sema.fail(block, src, "{}-bit float unsupported", .{float.bits}),20748 else => return sema.fail(block, src, "{d}-bit float unsupported", .{float.bits}),
20756 };20749 };
20757 return Air.internedToRef(ty.toIntern());20750 return Air.internedToRef(ty.toIntern());
20758 },20751 },
...@@ -20833,7 +20826,7 @@ fn zirReify(...@@ -20833,7 +20826,7 @@ fn zirReify(
20833 } else if (ptr_size == .c) {20826 } else if (ptr_size == .c) {
20834 if (!try sema.validateExternType(elem_ty, .other)) {20827 if (!try sema.validateExternType(elem_ty, .other)) {
20835 const msg = msg: {20828 const msg = msg: {
20836 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(pt)});20829 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);20830 errdefer msg.destroy(gpa);
2083820831
20839 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);20832 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);
...@@ -20946,7 +20939,7 @@ fn zirReify(...@@ -20946,7 +20939,7 @@ fn zirReify(
20946 _ = try pt.getErrorValue(name);20939 _ = try pt.getErrorValue(name);
20947 const gop = names.getOrPutAssumeCapacity(name);20940 const gop = names.getOrPutAssumeCapacity(name);
20948 if (gop.found_existing) {20941 if (gop.found_existing) {
20949 return sema.fail(block, src, "duplicate error '{}'", .{20942 return sema.fail(block, src, "duplicate error '{f}'", .{
20950 name.fmt(ip),20943 name.fmt(ip),
20951 });20944 });
20952 }20945 }
...@@ -21294,7 +21287,7 @@ fn reifyEnum(...@@ -21294,7 +21287,7 @@ fn reifyEnum(
2129421287
21295 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {21288 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {
21296 // TODO: better source location21289 // TODO: better source location
21297 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{21290 return sema.fail(block, src, "field '{f}' with enumeration value '{f}' is too large for backing int type '{f}'", .{
21298 field_name.fmt(ip),21291 field_name.fmt(ip),
21299 field_value_val.fmtValueSema(pt, sema),21292 field_value_val.fmtValueSema(pt, sema),
21300 tag_ty.fmt(pt),21293 tag_ty.fmt(pt),
...@@ -21305,14 +21298,14 @@ fn reifyEnum(...@@ -21305,14 +21298,14 @@ fn reifyEnum(
21305 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {21298 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {
21306 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {21299 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21307 .name => msg: {21300 .name => msg: {
21308 const msg = try sema.errMsg(src, "duplicate enum field '{}'", .{field_name.fmt(ip)});21301 const msg = try sema.errMsg(src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
21309 errdefer msg.destroy(gpa);21302 errdefer msg.destroy(gpa);
21310 _ = conflict.prev_field_idx; // TODO: this note is incorrect21303 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21311 try sema.errNote(src, msg, "other field here", .{});21304 try sema.errNote(src, msg, "other field here", .{});
21312 break :msg msg;21305 break :msg msg;
21313 },21306 },
21314 .value => msg: {21307 .value => msg: {
21315 const msg = try sema.errMsg(src, "enum tag value {} already taken", .{field_value_val.fmtValueSema(pt, sema)});21308 const msg = try sema.errMsg(src, "enum tag value {f} already taken", .{field_value_val.fmtValueSema(pt, sema)});
21316 errdefer msg.destroy(gpa);21309 errdefer msg.destroy(gpa);
21317 _ = conflict.prev_field_idx; // TODO: this note is incorrect21310 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21318 try sema.errNote(src, msg, "other enum tag value here", .{});21311 try sema.errNote(src, msg, "other enum tag value here", .{});
...@@ -21460,13 +21453,13 @@ fn reifyUnion(...@@ -21460,13 +21453,13 @@ fn reifyUnion(
2146021453
21461 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {21454 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {
21462 // TODO: better source location21455 // TODO: better source location
21463 return sema.fail(block, src, "no field named '{}' in enum '{}'", .{21456 return sema.fail(block, src, "no field named '{f}' in enum '{f}'", .{
21464 field_name.fmt(ip), enum_tag_ty.fmt(pt),21457 field_name.fmt(ip), enum_tag_ty.fmt(pt),
21465 });21458 });
21466 };21459 };
21467 if (seen_tags.isSet(enum_index)) {21460 if (seen_tags.isSet(enum_index)) {
21468 // TODO: better source location21461 // TODO: better source location
21469 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});21462 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
21470 }21463 }
21471 seen_tags.set(enum_index);21464 seen_tags.set(enum_index);
2147221465
...@@ -21487,7 +21480,7 @@ fn reifyUnion(...@@ -21487,7 +21480,7 @@ fn reifyUnion(
21487 var it = seen_tags.iterator(.{ .kind = .unset });21480 var it = seen_tags.iterator(.{ .kind = .unset });
21488 while (it.next()) |enum_index| {21481 while (it.next()) |enum_index| {
21489 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);21482 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);
21490 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{}' missing, declared here", .{21483 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{f}' missing, declared here", .{
21491 field_name.fmt(ip),21484 field_name.fmt(ip),
21492 });21485 });
21493 }21486 }
...@@ -21512,7 +21505,7 @@ fn reifyUnion(...@@ -21512,7 +21505,7 @@ fn reifyUnion(
21512 const gop = field_names.getOrPutAssumeCapacity(field_name);21505 const gop = field_names.getOrPutAssumeCapacity(field_name);
21513 if (gop.found_existing) {21506 if (gop.found_existing) {
21514 // TODO: better source location21507 // TODO: better source location
21515 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});21508 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
21516 }21509 }
2151721510
21518 field_ty.* = field_type_val.toIntern();21511 field_ty.* = field_type_val.toIntern();
...@@ -21544,7 +21537,7 @@ fn reifyUnion(...@@ -21544,7 +21537,7 @@ fn reifyUnion(
21544 }21537 }
21545 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {21538 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
21546 return sema.failWithOwnedErrorMsg(block, msg: {21539 return sema.failWithOwnedErrorMsg(block, msg: {
21547 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21540 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21548 errdefer msg.destroy(gpa);21541 errdefer msg.destroy(gpa);
2154921542
21550 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);21543 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);
...@@ -21554,7 +21547,7 @@ fn reifyUnion(...@@ -21554,7 +21547,7 @@ fn reifyUnion(
21554 });21547 });
21555 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21548 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21556 return sema.failWithOwnedErrorMsg(block, msg: {21549 return sema.failWithOwnedErrorMsg(block, msg: {
21557 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21550 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21558 errdefer msg.destroy(gpa);21551 errdefer msg.destroy(gpa);
2155921552
21560 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21553 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
...@@ -21636,14 +21629,14 @@ fn reifyTuple(...@@ -21636,14 +21629,14 @@ fn reifyTuple(
21636 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(21629 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
21637 block,21630 block,
21638 src,21631 src,
21639 "tuple cannot have non-numeric field '{}'",21632 "tuple cannot have non-numeric field '{f}'",
21640 .{field_name.fmt(ip)},21633 .{field_name.fmt(ip)},
21641 );21634 );
21642 if (field_name_index != field_idx) {21635 if (field_name_index != field_idx) {
21643 return sema.fail(21636 return sema.fail(
21644 block,21637 block,
21645 src,21638 src,
21646 "tuple field name '{}' does not match field index {}",21639 "tuple field name '{d}' does not match field index {d}",
21647 .{ field_name_index, field_idx },21640 .{ field_name_index, field_idx },
21648 );21641 );
21649 }21642 }
...@@ -21814,7 +21807,7 @@ fn reifyStruct(...@@ -21814,7 +21807,7 @@ fn reifyStruct(
21814 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);21807 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21815 if (struct_type.addFieldName(ip, field_name)) |prev_index| {21808 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
21816 _ = prev_index; // TODO: better source location21809 _ = prev_index; // TODO: better source location
21817 return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)});21810 return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
21818 }21811 }
2181921812
21820 if (any_aligned_fields) {21813 if (any_aligned_fields) {
...@@ -21883,7 +21876,7 @@ fn reifyStruct(...@@ -21883,7 +21876,7 @@ fn reifyStruct(
21883 }21876 }
21884 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {21877 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
21885 return sema.failWithOwnedErrorMsg(block, msg: {21878 return sema.failWithOwnedErrorMsg(block, msg: {
21886 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21879 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21887 errdefer msg.destroy(gpa);21880 errdefer msg.destroy(gpa);
2188821881
21889 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);21882 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);
...@@ -21893,7 +21886,7 @@ fn reifyStruct(...@@ -21893,7 +21886,7 @@ fn reifyStruct(
21893 });21886 });
21894 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21887 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21895 return sema.failWithOwnedErrorMsg(block, msg: {21888 return sema.failWithOwnedErrorMsg(block, msg: {
21896 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21889 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21897 errdefer msg.destroy(gpa);21890 errdefer msg.destroy(gpa);
2189821891
21899 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21892 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
...@@ -21970,7 +21963,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -21970,7 +21963,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2197021963
21971 if (!try sema.validateExternType(arg_ty, .param_ty)) {21964 if (!try sema.validateExternType(arg_ty, .param_ty)) {
21972 const msg = msg: {21965 const msg = msg: {
21973 const msg = try sema.errMsg(ty_src, "cannot get '{}' from variadic argument", .{arg_ty.fmt(sema.pt)});21966 const msg = try sema.errMsg(ty_src, "cannot get '{f}' from variadic argument", .{arg_ty.fmt(sema.pt)});
21974 errdefer msg.destroy(sema.gpa);21967 errdefer msg.destroy(sema.gpa);
2197521968
21976 try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty);21969 try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty);
...@@ -22029,7 +22022,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -22029,7 +22022,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
22029 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);22022 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
22030 const ty = try sema.resolveType(block, ty_src, inst_data.operand);22023 const ty = try sema.resolveType(block, ty_src, inst_data.operand);
2203122024
22032 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{}", .{ty.fmt(pt)}, .no_embedded_nulls);22025 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls);
22033 return sema.addNullTerminatedStrLit(type_name);22026 return sema.addNullTerminatedStrLit(type_name);
22034}22027}
2203522028
...@@ -22157,7 +22150,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22157,7 +22150,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2215722150
22158 if (ptr_ty.isSlice(zcu)) {22151 if (ptr_ty.isSlice(zcu)) {
22159 const msg = msg: {22152 const msg = msg: {
22160 const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(pt)});22153 const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{f}'", .{ptr_ty.fmt(pt)});
22161 errdefer msg.destroy(sema.gpa);22154 errdefer msg.destroy(sema.gpa);
22162 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});22155 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});
22163 break :msg msg;22156 break :msg msg;
...@@ -22184,7 +22177,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22184,7 +22177,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22184 }22177 }
22185 if (try ptr_ty.comptimeOnlySema(pt)) {22178 if (try ptr_ty.comptimeOnlySema(pt)) {
22186 return sema.failWithOwnedErrorMsg(block, msg: {22179 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)});22180 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);22181 errdefer msg.destroy(sema.gpa);
2218922182
22190 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);22183 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);
...@@ -22241,7 +22234,7 @@ fn ptrFromIntVal(...@@ -22241,7 +22234,7 @@ fn ptrFromIntVal(
22241 }22234 }
22242 const addr = try operand_val.toUnsignedIntSema(pt);22235 const addr = try operand_val.toUnsignedIntSema(pt);
22243 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)22236 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)});22237 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) {22238 if (addr != 0 and ptr_align != .none) {
22246 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|22239 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|
22247 addr & mask22240 addr & mask
...@@ -22249,7 +22242,7 @@ fn ptrFromIntVal(...@@ -22249,7 +22242,7 @@ fn ptrFromIntVal(
22249 addr;22242 addr;
2225022243
22251 if (!ptr_align.check(masked_addr)) {22244 if (!ptr_align.check(masked_addr)) {
22252 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(pt)});22245 return sema.fail(block, operand_src, "pointer type '{f}' requires aligned address", .{ptr_ty.fmt(pt)});
22253 }22246 }
22254 }22247 }
2225522248
...@@ -22294,8 +22287,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22294,8 +22287,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22294 errdefer msg.destroy(sema.gpa);22287 errdefer msg.destroy(sema.gpa);
22295 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);22288 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);
22296 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);22289 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);
22297 try sema.errNote(src, msg, "destination payload is '{}'", .{dest_payload_ty.fmt(pt)});22290 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)});22291 try sema.errNote(src, msg, "operand payload is '{f}'", .{operand_payload_ty.fmt(pt)});
22299 try addDeclaredHereNote(sema, msg, dest_ty);22292 try addDeclaredHereNote(sema, msg, dest_ty);
22300 try addDeclaredHereNote(sema, msg, operand_ty);22293 try addDeclaredHereNote(sema, msg, operand_ty);
22301 break :msg msg;22294 break :msg msg;
...@@ -22340,7 +22333,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22340,7 +22333,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22340 break :disjoint true;22333 break :disjoint true;
22341 };22334 };
22342 if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) {22335 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", .{22336 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),22337 operand_err_ty.fmt(pt), dest_err_ty.fmt(pt),
22345 });22338 });
22346 }22339 }
...@@ -22360,7 +22353,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22360,7 +22353,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22360 };22353 };
2236122354
22362 if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) {22355 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 '{}'", .{22356 return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{
22364 err_name.fmt(ip), dest_err_ty.fmt(pt),22357 err_name.fmt(ip), dest_err_ty.fmt(pt),
22365 });22358 });
22366 }22359 }
...@@ -22520,13 +22513,15 @@ fn ptrCastFull(...@@ -22520,13 +22513,15 @@ fn ptrCastFull(
22520 const src_elem_size = src_elem_ty.abiSize(zcu);22513 const src_elem_size = src_elem_ty.abiSize(zcu);
22521 const dest_elem_size = dest_elem_ty.abiSize(zcu);22514 const dest_elem_size = dest_elem_ty.abiSize(zcu);
22522 if (dest_elem_size == 0) {22515 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) });22516 return sema.fail(block, src, "cannot infer length of slice of zero-bit '{f}' from '{f}'", .{
22517 dest_elem_ty.fmt(pt), operand_ty.fmt(pt),
22518 });
22524 }22519 }
22525 if (opt_src_len) |src_len| {22520 if (opt_src_len) |src_len| {
22526 const bytes = src_len * src_elem_size;22521 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) {22522 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}),22523 .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)}),22524 .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
22530 else => unreachable,22525 else => unreachable,
22531 };22526 };
22532 break :len .{ .constant = dest_len };22527 break :len .{ .constant = dest_len };
...@@ -22544,7 +22539,9 @@ fn ptrCastFull(...@@ -22544,7 +22539,9 @@ fn ptrCastFull(
22544 // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`.22539 // 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`.22540 // 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()) {22541 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) });22542 return sema.fail(block, src, "cannot infer length of comptime-only '{f}' from incompatible '{f}'", .{
22543 dest_ty.fmt(pt), operand_ty.fmt(pt),
22544 });
22548 }22545 }
22549 // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is22546 // `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`.22547 // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`.
...@@ -22552,7 +22549,7 @@ fn ptrCastFull(...@@ -22552,7 +22549,7 @@ fn ptrCastFull(
22552 const base_len = src_len * src_base_per_elem;22549 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) {22550 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}),22551 .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)}),22552 .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
22556 else => unreachable,22553 else => unreachable,
22557 };22554 };
22558 break :len .{ .constant = dest_len };22555 break :len .{ .constant = dest_len };
...@@ -22613,7 +22610,7 @@ fn ptrCastFull(...@@ -22613,7 +22610,7 @@ fn ptrCastFull(
22613 );22610 );
22614 if (imc_res == .ok) break :check_child;22611 if (imc_res == .ok) break :check_child;
22615 return sema.failWithOwnedErrorMsg(block, msg: {22612 return sema.failWithOwnedErrorMsg(block, msg: {
22616 const msg = try sema.errMsg(src, "pointer element type '{}' cannot coerce into element type '{}'", .{22613 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),22614 src_child.fmt(pt), dest_child.fmt(pt),
22618 });22615 });
22619 errdefer msg.destroy(sema.gpa);22616 errdefer msg.destroy(sema.gpa);
...@@ -22640,11 +22637,11 @@ fn ptrCastFull(...@@ -22640,11 +22637,11 @@ fn ptrCastFull(
22640 }22637 }
22641 return sema.failWithOwnedErrorMsg(block, msg: {22638 return sema.failWithOwnedErrorMsg(block, msg: {
22642 const msg = if (src_info.sentinel == .none) blk: {22639 const msg = if (src_info.sentinel == .none) blk: {
22643 break :blk try sema.errMsg(src, "destination pointer requires '{}' sentinel", .{22640 break :blk try sema.errMsg(src, "destination pointer requires '{f}' sentinel", .{
22644 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),22641 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
22645 });22642 });
22646 } else blk: {22643 } else blk: {
22647 break :blk try sema.errMsg(src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{22644 break :blk try sema.errMsg(src, "pointer sentinel '{f}' cannot coerce into pointer sentinel '{f}'", .{
22648 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),22645 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),
22649 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),22646 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
22650 });22647 });
...@@ -22657,7 +22654,7 @@ fn ptrCastFull(...@@ -22657,7 +22654,7 @@ fn ptrCastFull(
2265722654
22658 if (src_info.packed_offset.host_size != dest_info.packed_offset.host_size) {22655 if (src_info.packed_offset.host_size != dest_info.packed_offset.host_size) {
22659 return sema.failWithOwnedErrorMsg(block, msg: {22656 return sema.failWithOwnedErrorMsg(block, msg: {
22660 const msg = try sema.errMsg(src, "pointer host size '{}' cannot coerce into pointer host size '{}'", .{22657 const msg = try sema.errMsg(src, "pointer host size '{d}' cannot coerce into pointer host size '{d}'", .{
22661 src_info.packed_offset.host_size,22658 src_info.packed_offset.host_size,
22662 dest_info.packed_offset.host_size,22659 dest_info.packed_offset.host_size,
22663 });22660 });
...@@ -22669,7 +22666,7 @@ fn ptrCastFull(...@@ -22669,7 +22666,7 @@ fn ptrCastFull(
2266922666
22670 if (src_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset) {22667 if (src_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset) {
22671 return sema.failWithOwnedErrorMsg(block, msg: {22668 return sema.failWithOwnedErrorMsg(block, msg: {
22672 const msg = try sema.errMsg(src, "pointer bit offset '{}' cannot coerce into pointer bit offset '{}'", .{22669 const msg = try sema.errMsg(src, "pointer bit offset '{d}' cannot coerce into pointer bit offset '{d}'", .{
22673 src_info.packed_offset.bit_offset,22670 src_info.packed_offset.bit_offset,
22674 dest_info.packed_offset.bit_offset,22671 dest_info.packed_offset.bit_offset,
22675 });22672 });
...@@ -22686,7 +22683,7 @@ fn ptrCastFull(...@@ -22686,7 +22683,7 @@ fn ptrCastFull(
22686 if (dest_allows_zero) break :check_allowzero;22683 if (dest_allows_zero) break :check_allowzero;
2268722684
22688 return sema.failWithOwnedErrorMsg(block, msg: {22685 return sema.failWithOwnedErrorMsg(block, msg: {
22689 const msg = try sema.errMsg(src, "'{}' could have null values which are illegal in type '{}'", .{22686 const msg = try sema.errMsg(src, "'{f}' could have null values which are illegal in type '{f}'", .{
22690 operand_ty.fmt(pt),22687 operand_ty.fmt(pt),
22691 dest_ty.fmt(pt),22688 dest_ty.fmt(pt),
22692 });22689 });
...@@ -22714,10 +22711,10 @@ fn ptrCastFull(...@@ -22714,10 +22711,10 @@ fn ptrCastFull(
22714 return sema.failWithOwnedErrorMsg(block, msg: {22711 return sema.failWithOwnedErrorMsg(block, msg: {
22715 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});22712 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});
22716 errdefer msg.destroy(sema.gpa);22713 errdefer msg.destroy(sema.gpa);
22717 try sema.errNote(operand_src, msg, "'{}' has alignment '{d}'", .{22714 try sema.errNote(operand_src, msg, "'{f}' has alignment '{d}'", .{
22718 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,22715 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,
22719 });22716 });
22720 try sema.errNote(src, msg, "'{}' has alignment '{d}'", .{22717 try sema.errNote(src, msg, "'{f}' has alignment '{d}'", .{
22721 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,22718 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,
22722 });22719 });
22723 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});22720 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});
...@@ -22731,10 +22728,10 @@ fn ptrCastFull(...@@ -22731,10 +22728,10 @@ fn ptrCastFull(
22731 return sema.failWithOwnedErrorMsg(block, msg: {22728 return sema.failWithOwnedErrorMsg(block, msg: {
22732 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});22729 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});
22733 errdefer msg.destroy(sema.gpa);22730 errdefer msg.destroy(sema.gpa);
22734 try sema.errNote(operand_src, msg, "'{}' has address space '{s}'", .{22731 try sema.errNote(operand_src, msg, "'{f}' has address space '{s}'", .{
22735 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),22732 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),
22736 });22733 });
22737 try sema.errNote(src, msg, "'{}' has address space '{s}'", .{22734 try sema.errNote(src, msg, "'{f}' has address space '{s}'", .{
22738 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),22735 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),
22739 });22736 });
22740 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});22737 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});
...@@ -22801,7 +22798,7 @@ fn ptrCastFull(...@@ -22801,7 +22798,7 @@ fn ptrCastFull(
2280122798
22802 if (operand_val.isNull(zcu)) {22799 if (operand_val.isNull(zcu)) {
22803 if (!dest_ty.ptrAllowsZero(zcu)) {22800 if (!dest_ty.ptrAllowsZero(zcu)) {
22804 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(pt)});22801 return sema.fail(block, operand_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)});
22805 }22802 }
22806 if (dest_ty.zigTypeTag(zcu) == .optional) {22803 if (dest_ty.zigTypeTag(zcu) == .optional) {
22807 return Air.internedToRef((try pt.nullValue(dest_ty)).toIntern());22804 return Air.internedToRef((try pt.nullValue(dest_ty)).toIntern());
...@@ -23092,7 +23089,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23092,7 +23089,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23092 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;23089 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;
23093 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;23090 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;
23094 if (operand_is_vector != dest_is_vector) {23091 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) });23092 return sema.fail(block, operand_src, "expected type '{f}', found '{f}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });
23096 }23093 }
2309723094
23098 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {23095 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {
...@@ -23112,7 +23109,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23112,7 +23109,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23112 }23109 }
2311323110
23114 if (operand_info.signedness != dest_info.signedness) {23111 if (operand_info.signedness != dest_info.signedness) {
23115 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{23112 return sema.fail(block, operand_src, "expected {s} integer type, found '{f}'", .{
23116 @tagName(dest_info.signedness), operand_ty.fmt(pt),23113 @tagName(dest_info.signedness), operand_ty.fmt(pt),
23117 });23114 });
23118 }23115 }
...@@ -23121,7 +23118,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23121,7 +23118,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23121 const msg = msg: {23118 const msg = msg: {
23122 const msg = try sema.errMsg(23119 const msg = try sema.errMsg(
23123 src,23120 src,
23124 "destination type '{}' has more bits than source type '{}'",23121 "destination type '{f}' has more bits than source type '{f}'",
23125 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },23122 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },
23126 );23123 );
23127 errdefer msg.destroy(sema.gpa);23124 errdefer msg.destroy(sema.gpa);
...@@ -23239,7 +23236,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23239,7 +23236,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23239 return sema.fail(23236 return sema.fail(
23240 block,23237 block,
23241 operand_src,23238 operand_src,
23242 "@byteSwap requires the number of bits to be evenly divisible by 8, but {} has {} bits",23239 "@byteSwap requires the number of bits to be evenly divisible by 8, but {f} has {d} bits",
23243 .{ scalar_ty.fmt(pt), bits },23240 .{ scalar_ty.fmt(pt), bits },
23244 );23241 );
23245 }23242 }
...@@ -23359,7 +23356,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -23359,7 +23356,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
23359 try ty.resolveLayout(pt);23356 try ty.resolveLayout(pt);
23360 switch (ty.zigTypeTag(zcu)) {23357 switch (ty.zigTypeTag(zcu)) {
23361 .@"struct" => {},23358 .@"struct" => {},
23362 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),23359 else => return sema.fail(block, ty_src, "expected struct type, found '{f}'", .{ty.fmt(pt)}),
23363 }23360 }
2336423361
23365 const field_index = if (ty.isTuple(zcu)) blk: {23362 const field_index = if (ty.isTuple(zcu)) blk: {
...@@ -23394,7 +23391,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com...@@ -23394,7 +23391,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com
23394 const zcu = pt.zcu;23391 const zcu = pt.zcu;
23395 switch (ty.zigTypeTag(zcu)) {23392 switch (ty.zigTypeTag(zcu)) {
23396 .@"struct", .@"enum", .@"union", .@"opaque" => return,23393 .@"struct", .@"enum", .@"union", .@"opaque" => return,
23397 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(pt)}),23394 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{f}'", .{ty.fmt(pt)}),
23398 }23395 }
23399}23396}
2340023397
...@@ -23405,7 +23402,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr...@@ -23405,7 +23402,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr
23405 switch (ty.zigTypeTag(zcu)) {23402 switch (ty.zigTypeTag(zcu)) {
23406 .comptime_int => return true,23403 .comptime_int => return true,
23407 .int => return false,23404 .int => return false,
23408 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(pt)}),23405 else => return sema.fail(block, src, "expected integer type, found '{f}'", .{ty.fmt(pt)}),
23409 }23406 }
23410}23407}
2341123408
...@@ -23459,7 +23456,7 @@ fn checkPtrOperand(...@@ -23459,7 +23456,7 @@ fn checkPtrOperand(
23459 const msg = msg: {23456 const msg = msg: {
23460 const msg = try sema.errMsg(23457 const msg = try sema.errMsg(
23461 ty_src,23458 ty_src,
23462 "expected pointer, found '{}'",23459 "expected pointer, found '{f}'",
23463 .{ty.fmt(pt)},23460 .{ty.fmt(pt)},
23464 );23461 );
23465 errdefer msg.destroy(sema.gpa);23462 errdefer msg.destroy(sema.gpa);
...@@ -23473,7 +23470,7 @@ fn checkPtrOperand(...@@ -23473,7 +23470,7 @@ fn checkPtrOperand(
23473 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,23470 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
23474 else => {},23471 else => {},
23475 }23472 }
23476 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});23473 return sema.fail(block, ty_src, "expected pointer type, found '{f}'", .{ty.fmt(pt)});
23477}23474}
2347823475
23479fn checkPtrType(23476fn checkPtrType(
...@@ -23491,7 +23488,7 @@ fn checkPtrType(...@@ -23491,7 +23488,7 @@ fn checkPtrType(
23491 const msg = msg: {23488 const msg = msg: {
23492 const msg = try sema.errMsg(23489 const msg = try sema.errMsg(
23493 ty_src,23490 ty_src,
23494 "expected pointer type, found '{}'",23491 "expected pointer type, found '{f}'",
23495 .{ty.fmt(pt)},23492 .{ty.fmt(pt)},
23496 );23493 );
23497 errdefer msg.destroy(sema.gpa);23494 errdefer msg.destroy(sema.gpa);
...@@ -23505,7 +23502,7 @@ fn checkPtrType(...@@ -23505,7 +23502,7 @@ fn checkPtrType(
23505 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,23502 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
23506 else => {},23503 else => {},
23507 }23504 }
23508 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});23505 return sema.fail(block, ty_src, "expected pointer type, found '{f}'", .{ty.fmt(pt)});
23509}23506}
2351023507
23511fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {23508fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
...@@ -23516,7 +23513,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -23516,7 +23513,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
23516 const as = ty.ptrAddressSpace(zcu);23513 const as = ty.ptrAddressSpace(zcu);
23517 if (target_util.arePointersLogical(target, as)) {23514 if (target_util.arePointersLogical(target, as)) {
23518 return sema.failWithOwnedErrorMsg(block, msg: {23515 return sema.failWithOwnedErrorMsg(block, msg: {
23519 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{}'", .{ty.fmt(pt)});23516 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{f}'", .{ty.fmt(pt)});
23520 errdefer msg.destroy(sema.gpa);23517 errdefer msg.destroy(sema.gpa);
23521 try sema.errNote(23518 try sema.errNote(
23522 src,23519 src,
...@@ -23547,7 +23544,7 @@ fn checkVectorElemType(...@@ -23547,7 +23544,7 @@ fn checkVectorElemType(
23547 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,23544 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,
23548 else => {},23545 else => {},
23549 }23546 }
23550 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(pt)});23547 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{f}'", .{ty.fmt(pt)});
23551}23548}
2355223549
23553fn checkFloatType(23550fn checkFloatType(
...@@ -23560,7 +23557,7 @@ fn checkFloatType(...@@ -23560,7 +23557,7 @@ fn checkFloatType(
23560 const zcu = pt.zcu;23557 const zcu = pt.zcu;
23561 switch (ty.zigTypeTag(zcu)) {23558 switch (ty.zigTypeTag(zcu)) {
23562 .comptime_int, .comptime_float, .float => {},23559 .comptime_int, .comptime_float, .float => {},
23563 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(pt)}),23560 else => return sema.fail(block, ty_src, "expected float type, found '{f}'", .{ty.fmt(pt)}),
23564 }23561 }
23565}23562}
2356623563
...@@ -23576,9 +23573,9 @@ fn checkNumericType(...@@ -23576,9 +23573,9 @@ fn checkNumericType(
23576 .comptime_float, .float, .comptime_int, .int => {},23573 .comptime_float, .float, .comptime_int, .int => {},
23577 .vector => switch (ty.childType(zcu).zigTypeTag(zcu)) {23574 .vector => switch (ty.childType(zcu).zigTypeTag(zcu)) {
23578 .comptime_float, .float, .comptime_int, .int => {},23575 .comptime_float, .float, .comptime_int, .int => {},
23579 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),23576 else => |t| return sema.fail(block, ty_src, "expected number, found '{t}'", .{t}),
23580 },23577 },
23581 else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(pt)}),23578 else => return sema.fail(block, ty_src, "expected number, found '{f}'", .{ty.fmt(pt)}),
23582 }23579 }
23583}23580}
2358423581
...@@ -23612,7 +23609,7 @@ fn checkAtomicPtrOperand(...@@ -23612,7 +23609,7 @@ fn checkAtomicPtrOperand(
23612 error.BadType => return sema.fail(23609 error.BadType => return sema.fail(
23613 block,23610 block,
23614 elem_ty_src,23611 elem_ty_src,
23615 "expected bool, integer, float, enum, packed struct, or pointer type; found '{}'",23612 "expected bool, integer, float, enum, packed struct, or pointer type; found '{f}'",
23616 .{elem_ty.fmt(pt)},23613 .{elem_ty.fmt(pt)},
23617 ),23614 ),
23618 };23615 };
...@@ -23673,12 +23670,12 @@ fn checkIntOrVector(...@@ -23673,12 +23670,12 @@ fn checkIntOrVector(
23673 const elem_ty = operand_ty.childType(zcu);23670 const elem_ty = operand_ty.childType(zcu);
23674 switch (elem_ty.zigTypeTag(zcu)) {23671 switch (elem_ty.zigTypeTag(zcu)) {
23675 .int => return elem_ty,23672 .int => return elem_ty,
23676 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{23673 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{f}'", .{
23677 elem_ty.fmt(pt),23674 elem_ty.fmt(pt),
23678 }),23675 }),
23679 }23676 }
23680 },23677 },
23681 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{23678 else => return sema.fail(block, operand_src, "expected integer or vector, found '{f}'", .{
23682 operand_ty.fmt(pt),23679 operand_ty.fmt(pt),
23683 }),23680 }),
23684 }23681 }
...@@ -23698,12 +23695,12 @@ fn checkIntOrVectorAllowComptime(...@@ -23698,12 +23695,12 @@ fn checkIntOrVectorAllowComptime(
23698 const elem_ty = operand_ty.childType(zcu);23695 const elem_ty = operand_ty.childType(zcu);
23699 switch (elem_ty.zigTypeTag(zcu)) {23696 switch (elem_ty.zigTypeTag(zcu)) {
23700 .int, .comptime_int => return elem_ty,23697 .int, .comptime_int => return elem_ty,
23701 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{23698 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{f}'", .{
23702 elem_ty.fmt(pt),23699 elem_ty.fmt(pt),
23703 }),23700 }),
23704 }23701 }
23705 },23702 },
23706 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{23703 else => return sema.fail(block, operand_src, "expected integer or vector, found '{f}'", .{
23707 operand_ty.fmt(pt),23704 operand_ty.fmt(pt),
23708 }),23705 }),
23709 }23706 }
...@@ -23794,7 +23791,7 @@ fn checkVectorizableBinaryOperands(...@@ -23794,7 +23791,7 @@ fn checkVectorizableBinaryOperands(
23794 }23791 }
23795 } else {23792 } else {
23796 const msg = msg: {23793 const msg = msg: {
23797 const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{}' and '{}'", .{23794 const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{f}' and '{f}'", .{
23798 lhs_ty.fmt(pt), rhs_ty.fmt(pt),23795 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
23799 });23796 });
23800 errdefer msg.destroy(sema.gpa);23797 errdefer msg.destroy(sema.gpa);
...@@ -23928,7 +23925,7 @@ fn zirCmpxchg(...@@ -23928,7 +23925,7 @@ fn zirCmpxchg(
23928 return sema.fail(23925 return sema.fail(
23929 block,23926 block,
23930 elem_ty_src,23927 elem_ty_src,
23931 "expected bool, integer, enum, packed struct, or pointer type; found '{}'",23928 "expected bool, integer, enum, packed struct, or pointer type; found '{f}'",
23932 .{elem_ty.fmt(pt)},23929 .{elem_ty.fmt(pt)},
23933 );23930 );
23934 }23931 }
...@@ -24012,7 +24009,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -24012,7 +24009,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2401224009
24013 switch (dest_ty.zigTypeTag(zcu)) {24010 switch (dest_ty.zigTypeTag(zcu)) {
24014 .array, .vector => {},24011 .array, .vector => {},
24015 else => return sema.fail(block, src, "expected array or vector type, found '{}'", .{dest_ty.fmt(pt)}),24012 else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(pt)}),
24016 }24013 }
2401724014
24018 const operand = try sema.resolveInst(extra.rhs);24015 const operand = try sema.resolveInst(extra.rhs);
...@@ -24088,7 +24085,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24088,7 +24085,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24088 const zcu = pt.zcu;24085 const zcu = pt.zcu;
2408924086
24090 if (operand_ty.zigTypeTag(zcu) != .vector) {24087 if (operand_ty.zigTypeTag(zcu) != .vector) {
24091 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(pt)});24088 return sema.fail(block, operand_src, "expected vector, found '{f}'", .{operand_ty.fmt(pt)});
24092 }24089 }
2409324090
24094 const scalar_ty = operand_ty.childType(zcu);24091 const scalar_ty = operand_ty.childType(zcu);
...@@ -24097,13 +24094,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24097,13 +24094,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24097 switch (operation) {24094 switch (operation) {
24098 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {24095 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
24099 .int, .bool => {},24096 .int, .bool => {},
24100 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{24097 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{f}'", .{
24101 @tagName(operation), operand_ty.fmt(pt),24098 @tagName(operation), operand_ty.fmt(pt),
24102 }),24099 }),
24103 },24100 },
24104 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {24101 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
24105 .int, .float => {},24102 .int, .float => {},
24106 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{24103 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{f}'", .{
24107 @tagName(operation), operand_ty.fmt(pt),24104 @tagName(operation), operand_ty.fmt(pt),
24108 }),24105 }),
24109 },24106 },
...@@ -24157,7 +24154,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -24157,7 +24154,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2415724154
24158 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {24155 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {
24159 .array, .vector => sema.typeOf(mask).arrayLen(zcu),24156 .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)}),24157 else => return sema.fail(block, mask_src, "expected vector or array, found '{f}'", .{sema.typeOf(mask).fmt(pt)}),
24161 };24158 };
24162 mask_ty = try pt.vectorType(.{24159 mask_ty = try pt.vectorType(.{
24163 .len = @intCast(mask_len),24160 .len = @intCast(mask_len),
...@@ -24184,11 +24181,14 @@ fn analyzeShuffle(...@@ -24184,11 +24181,14 @@ fn analyzeShuffle(
24184 const b_src = block.builtinCallArgSrc(src_node, 2);24181 const b_src = block.builtinCallArgSrc(src_node, 2);
24185 const mask_src = block.builtinCallArgSrc(src_node, 3);24182 const mask_src = block.builtinCallArgSrc(src_node, 3);
2418624183
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.24184 // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped,
24185 // 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)) {24186 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {
24189 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),24187 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),
24190 .undefined => 0,24188 .undefined => 0,
24191 else => return sema.fail(block, a_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt) }),24189 else => return sema.fail(block, a_src, "expected vector of '{f}', found '{f}'", .{
24190 elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt),
24191 }),
24192 };24192 };
24193 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });24193 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);24194 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);
...@@ -24197,7 +24197,9 @@ fn analyzeShuffle(...@@ -24197,7 +24197,9 @@ fn analyzeShuffle(
24197 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {24197 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {
24198 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),24198 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),
24199 .undefined => 0,24199 .undefined => 0,
24200 else => return sema.fail(block, b_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt) }),24200 else => return sema.fail(block, b_src, "expected vector of '{f}', found '{f}'", .{
24201 elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt),
24202 }),
24201 };24203 };
24202 const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() });24204 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);24205 const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src);
...@@ -24235,7 +24237,7 @@ fn analyzeShuffle(...@@ -24235,7 +24237,7 @@ fn analyzeShuffle(
24235 if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: {24237 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});24238 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);24239 errdefer msg.destroy(sema.gpa);
24238 try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{}' given here", .{ idx, a_ty.fmt(pt) });24240 try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{f}' given here", .{ idx, a_ty.fmt(pt) });
24239 if (idx < b_len) {24241 if (idx < b_len) {
24240 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});24242 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});
24241 }24243 }
...@@ -24248,7 +24250,7 @@ fn analyzeShuffle(...@@ -24248,7 +24250,7 @@ fn analyzeShuffle(
24248 if (idx >= b_len) return sema.failWithOwnedErrorMsg(block, msg: {24250 if (idx >= b_len) return sema.failWithOwnedErrorMsg(block, msg: {
24249 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});24251 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});
24250 errdefer msg.destroy(sema.gpa);24252 errdefer msg.destroy(sema.gpa);
24251 try sema.errNote(b_src, msg, "index '{d}' exceeds bounds of '{}' given here", .{ idx, b_ty.fmt(pt) });24253 try sema.errNote(b_src, msg, "index '{d}' exceeds bounds of '{f}' given here", .{ idx, b_ty.fmt(pt) });
24252 break :msg msg;24254 break :msg msg;
24253 });24255 });
24254 }24256 }
...@@ -24351,7 +24353,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -24351,7 +24353,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2435124353
24352 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {24354 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {
24353 .vector, .array => pred_ty.arrayLen(zcu),24355 .vector, .array => pred_ty.arrayLen(zcu),
24354 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(pt)}),24356 else => return sema.fail(block, pred_src, "expected vector or array, found '{f}'", .{pred_ty.fmt(pt)}),
24355 };24357 };
24356 const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64));24358 const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64));
2435724359
...@@ -24611,7 +24613,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24611,7 +24613,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2461124613
24612 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {24614 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
24613 .comptime_float, .float => {},24615 .comptime_float, .float => {},
24614 else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(pt)}),24616 else => return sema.fail(block, src, "expected vector of floats or float type, found '{f}'", .{ty.fmt(pt)}),
24615 }24617 }
2461624618
24617 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {24619 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
...@@ -24712,7 +24714,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -24712,7 +24714,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2471224714
24713 const args_ty = sema.typeOf(args);24715 const args_ty = sema.typeOf(args);
24714 if (!args_ty.isTuple(zcu)) {24716 if (!args_ty.isTuple(zcu)) {
24715 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(pt)});24717 return sema.fail(block, args_src, "expected a tuple, found '{f}'", .{args_ty.fmt(pt)});
24716 }24718 }
2471724719
24718 const resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(zcu));24720 const resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(zcu));
...@@ -24757,12 +24759,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24757,12 +24759,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24757 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);24759 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);
24758 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);24760 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
24759 if (parent_ptr_info.flags.size != .one) {24761 if (parent_ptr_info.flags.size != .one) {
24760 return sema.fail(block, inst_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(pt)});24762 return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)});
24761 }24763 }
24762 const parent_ty: Type = .fromInterned(parent_ptr_info.child);24764 const parent_ty: Type = .fromInterned(parent_ptr_info.child);
24763 switch (parent_ty.zigTypeTag(zcu)) {24765 switch (parent_ty.zigTypeTag(zcu)) {
24764 .@"struct", .@"union" => {},24766 .@"struct", .@"union" => {},
24765 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(pt)}),24767 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}),
24766 }24768 }
24767 try parent_ty.resolveLayout(pt);24769 try parent_ty.resolveLayout(pt);
2476824770
...@@ -24912,7 +24914,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24912,7 +24914,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24912 }24914 }
2491324915
24914 if (field.index != field_index) {24916 if (field.index != field_index) {
24915 return sema.fail(block, inst_src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{24917 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),24918 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt),
24917 });24919 });
24918 }24920 }
...@@ -25033,7 +25035,7 @@ fn analyzeMinMax(...@@ -25033,7 +25035,7 @@ fn analyzeMinMax(
25033 try sema.checkNumericType(block, operand_src, operand_ty);25035 try sema.checkNumericType(block, operand_src, operand_ty);
25034 if (operand_ty.zigTypeTag(zcu) != .vector) {25036 if (operand_ty.zigTypeTag(zcu) != .vector) {
25035 return sema.failWithOwnedErrorMsg(block, msg: {25037 return sema.failWithOwnedErrorMsg(block, msg: {
25036 const msg = try sema.errMsg(operand_src, "expected vector, found '{}'", .{operand_ty.fmt(pt)});25038 const msg = try sema.errMsg(operand_src, "expected vector, found '{f}'", .{operand_ty.fmt(pt)});
25037 errdefer msg.destroy(zcu.gpa);25039 errdefer msg.destroy(zcu.gpa);
25038 try sema.errNote(operand_srcs[0], msg, "vector operand here", .{});25040 try sema.errNote(operand_srcs[0], msg, "vector operand here", .{});
25039 break :msg msg;25041 break :msg msg;
...@@ -25041,7 +25043,7 @@ fn analyzeMinMax(...@@ -25041,7 +25043,7 @@ fn analyzeMinMax(
25041 }25043 }
25042 if (operand_ty.vectorLen(zcu) != vec_len) {25044 if (operand_ty.vectorLen(zcu) != vec_len) {
25043 return sema.failWithOwnedErrorMsg(block, msg: {25045 return sema.failWithOwnedErrorMsg(block, msg: {
25044 const msg = try sema.errMsg(operand_src, "expected vector of length '{d}', found '{}'", .{ vec_len, operand_ty.fmt(pt) });25046 const msg = try sema.errMsg(operand_src, "expected vector of length '{d}', found '{f}'", .{ vec_len, operand_ty.fmt(pt) });
25045 errdefer msg.destroy(zcu.gpa);25047 errdefer msg.destroy(zcu.gpa);
25046 try sema.errNote(operand_srcs[0], msg, "vector of length '{d}' here", .{vec_len});25048 try sema.errNote(operand_srcs[0], msg, "vector of length '{d}' here", .{vec_len});
25047 break :msg msg;25049 break :msg msg;
...@@ -25054,7 +25056,7 @@ fn analyzeMinMax(...@@ -25054,7 +25056,7 @@ fn analyzeMinMax(
25054 const operand_ty = sema.typeOf(operand);25056 const operand_ty = sema.typeOf(operand);
25055 if (operand_ty.zigTypeTag(zcu) == .vector) {25057 if (operand_ty.zigTypeTag(zcu) == .vector) {
25056 return sema.failWithOwnedErrorMsg(block, msg: {25058 return sema.failWithOwnedErrorMsg(block, msg: {
25057 const msg = try sema.errMsg(operand_srcs[0], "expected vector, found '{}'", .{first_operand_ty.fmt(pt)});25059 const msg = try sema.errMsg(operand_srcs[0], "expected vector, found '{f}'", .{first_operand_ty.fmt(pt)});
25058 errdefer msg.destroy(zcu.gpa);25060 errdefer msg.destroy(zcu.gpa);
25059 try sema.errNote(operand_src, msg, "vector operand here", .{});25061 try sema.errNote(operand_src, msg, "vector operand here", .{});
25060 break :msg msg;25062 break :msg msg;
...@@ -25371,10 +25373,10 @@ fn zirMemcpy(...@@ -25371,10 +25373,10 @@ fn zirMemcpy(
25371 const msg = msg: {25373 const msg = msg: {
25372 const msg = try sema.errMsg(src, "unknown copy length", .{});25374 const msg = try sema.errMsg(src, "unknown copy length", .{});
25373 errdefer msg.destroy(sema.gpa);25375 errdefer msg.destroy(sema.gpa);
25374 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{25376 try sema.errNote(dest_src, msg, "destination type '{f}' provides no length", .{
25375 dest_ty.fmt(pt),25377 dest_ty.fmt(pt),
25376 });25378 });
25377 try sema.errNote(src_src, msg, "source type '{}' provides no length", .{25379 try sema.errNote(src_src, msg, "source type '{f}' provides no length", .{
25378 src_ty.fmt(pt),25380 src_ty.fmt(pt),
25379 });25381 });
25380 break :msg msg;25382 break :msg msg;
...@@ -25398,7 +25400,7 @@ fn zirMemcpy(...@@ -25398,7 +25400,7 @@ fn zirMemcpy(
25398 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {25400 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {
25399 const msg = try sema.errMsg(25401 const msg = try sema.errMsg(
25400 src,25402 src,
25401 "pointer element type '{}' cannot coerce into element type '{}'",25403 "pointer element type '{f}' cannot coerce into element type '{f}'",
25402 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },25404 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },
25403 );25405 );
25404 errdefer msg.destroy(sema.gpa);25406 errdefer msg.destroy(sema.gpa);
...@@ -25417,10 +25419,10 @@ fn zirMemcpy(...@@ -25417,10 +25419,10 @@ fn zirMemcpy(
25417 const msg = msg: {25419 const msg = msg: {
25418 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});25420 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});
25419 errdefer msg.destroy(sema.gpa);25421 errdefer msg.destroy(sema.gpa);
25420 try sema.errNote(dest_src, msg, "length {} here", .{25422 try sema.errNote(dest_src, msg, "length {f} here", .{
25421 dest_len_val.fmtValueSema(pt, sema),25423 dest_len_val.fmtValueSema(pt, sema),
25422 });25424 });
25423 try sema.errNote(src_src, msg, "length {} here", .{25425 try sema.errNote(src_src, msg, "length {f} here", .{
25424 src_len_val.fmtValueSema(pt, sema),25426 src_len_val.fmtValueSema(pt, sema),
25425 });25427 });
25426 break :msg msg;25428 break :msg msg;
...@@ -25635,7 +25637,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25635,7 +25637,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25635 return sema.failWithOwnedErrorMsg(block, msg: {25637 return sema.failWithOwnedErrorMsg(block, msg: {
25636 const msg = try sema.errMsg(src, "unknown @memset length", .{});25638 const msg = try sema.errMsg(src, "unknown @memset length", .{});
25637 errdefer msg.destroy(sema.gpa);25639 errdefer msg.destroy(sema.gpa);
25638 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{25640 try sema.errNote(dest_src, msg, "destination type '{f}' provides no length", .{
25639 dest_ptr_ty.fmt(pt),25641 dest_ptr_ty.fmt(pt),
25640 });25642 });
25641 break :msg msg;25643 break :msg msg;
...@@ -25815,7 +25817,7 @@ fn zirCUndef(...@@ -25815,7 +25817,7 @@ fn zirCUndef(
25815 const src = block.builtinCallArgSrc(extra.node, 0);25817 const src = block.builtinCallArgSrc(extra.node, 0);
2581625818
25817 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cUndef_macro_name });25819 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});25820 try block.c_import_buf.?.print("#undef {s}\n", .{name});
25819 return .void_value;25821 return .void_value;
25820}25822}
2582125823
...@@ -25828,7 +25830,7 @@ fn zirCInclude(...@@ -25828,7 +25830,7 @@ fn zirCInclude(
25828 const src = block.builtinCallArgSrc(extra.node, 0);25830 const src = block.builtinCallArgSrc(extra.node, 0);
2582925831
25830 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cInclude_file_name });25832 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});25833 try block.c_import_buf.?.print("#include <{s}>\n", .{name});
25832 return .void_value;25834 return .void_value;
25833}25835}
2583425836
...@@ -25847,9 +25849,9 @@ fn zirCDefine(...@@ -25847,9 +25849,9 @@ fn zirCDefine(
25847 const rhs = try sema.resolveInst(extra.rhs);25849 const rhs = try sema.resolveInst(extra.rhs);
25848 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {25850 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {
25849 const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value });25851 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 });25852 try block.c_import_buf.?.print("#define {s} {s}\n", .{ name, value });
25851 } else {25853 } else {
25852 try block.c_import_buf.?.writer().print("#define {s}\n", .{name});25854 try block.c_import_buf.?.print("#define {s}\n", .{name});
25853 }25855 }
25854 return .void_value;25856 return .void_value;
25855}25857}
...@@ -26067,7 +26069,7 @@ fn zirBuiltinExtern(...@@ -26067,7 +26069,7 @@ fn zirBuiltinExtern(
26067 }26069 }
26068 if (!try sema.validateExternType(ty, .other)) {26070 if (!try sema.validateExternType(ty, .other)) {
26069 const msg = msg: {26071 const msg = msg: {
26070 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(pt)});26072 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)});
26071 errdefer msg.destroy(sema.gpa);26073 errdefer msg.destroy(sema.gpa);
26072 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);26074 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);
26073 break :msg msg;26075 break :msg msg;
...@@ -26307,7 +26309,7 @@ pub fn validateVarType(...@@ -26307,7 +26309,7 @@ pub fn validateVarType(
26307 if (is_extern) {26309 if (is_extern) {
26308 if (!try sema.validateExternType(var_ty, .other)) {26310 if (!try sema.validateExternType(var_ty, .other)) {
26309 const msg = msg: {26311 const msg = msg: {
26310 const msg = try sema.errMsg(src, "extern variable cannot have type '{}'", .{var_ty.fmt(pt)});26312 const msg = try sema.errMsg(src, "extern variable cannot have type '{f}'", .{var_ty.fmt(pt)});
26311 errdefer msg.destroy(sema.gpa);26313 errdefer msg.destroy(sema.gpa);
26312 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);26314 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);
26313 break :msg msg;26315 break :msg msg;
...@@ -26319,7 +26321,7 @@ pub fn validateVarType(...@@ -26319,7 +26321,7 @@ pub fn validateVarType(
26319 return sema.fail(26321 return sema.fail(
26320 block,26322 block,
26321 src,26323 src,
26322 "non-extern variable with opaque type '{}'",26324 "non-extern variable with opaque type '{f}'",
26323 .{var_ty.fmt(pt)},26325 .{var_ty.fmt(pt)},
26324 );26326 );
26325 }26327 }
...@@ -26328,7 +26330,7 @@ pub fn validateVarType(...@@ -26328,7 +26330,7 @@ pub fn validateVarType(
26328 if (!try var_ty.comptimeOnlySema(pt)) return;26330 if (!try var_ty.comptimeOnlySema(pt)) return;
2632926331
26330 const msg = msg: {26332 const msg = msg: {
26331 const msg = try sema.errMsg(src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(pt)});26333 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);26334 errdefer msg.destroy(sema.gpa);
2633326335
26334 try sema.explainWhyTypeIsComptime(msg, src, var_ty);26336 try sema.explainWhyTypeIsComptime(msg, src, var_ty);
...@@ -26378,7 +26380,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -26378,7 +26380,7 @@ fn explainWhyTypeIsComptimeInner(
26378 => return,26380 => return,
2637926381
26380 .@"fn" => {26382 .@"fn" => {
26381 try sema.errNote(src_loc, msg, "use '*const {}' for a function pointer type", .{ty.fmt(pt)});26383 try sema.errNote(src_loc, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)});
26382 },26384 },
2638326385
26384 .type => {26386 .type => {
...@@ -26394,7 +26396,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -26394,7 +26396,7 @@ fn explainWhyTypeIsComptimeInner(
26394 => return,26396 => return,
2639526397
26396 .@"opaque" => {26398 .@"opaque" => {
26397 try sema.errNote(src_loc, msg, "opaque type '{}' has undefined size", .{ty.fmt(pt)});26399 try sema.errNote(src_loc, msg, "opaque type '{f}' has undefined size", .{ty.fmt(pt)});
26398 },26400 },
2639926401
26400 .array, .vector => {26402 .array, .vector => {
...@@ -26581,7 +26583,7 @@ fn explainWhyTypeIsNotExtern(...@@ -26581,7 +26583,7 @@ fn explainWhyTypeIsNotExtern(
26581 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {26583 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {
26582 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});26584 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});
26583 } else if (try ty.comptimeOnlySema(pt)) {26585 } else if (try ty.comptimeOnlySema(pt)) {
26584 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(pt)});26586 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{f}'", .{pointee_ty.fmt(pt)});
26585 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);26587 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);
26586 }26588 }
26587 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);26589 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);
...@@ -26609,7 +26611,7 @@ fn explainWhyTypeIsNotExtern(...@@ -26609,7 +26611,7 @@ fn explainWhyTypeIsNotExtern(
26609 },26611 },
26610 .@"enum" => {26612 .@"enum" => {
26611 const tag_ty = ty.intTagType(zcu);26613 const tag_ty = ty.intTagType(zcu);
26612 try sema.errNote(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(pt)});26614 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);26615 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
26614 },26616 },
26615 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),26617 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
...@@ -27045,7 +27047,7 @@ fn fieldVal(...@@ -27045,7 +27047,7 @@ fn fieldVal(
27045 return sema.fail(27047 return sema.fail(
27046 block,27048 block,
27047 field_name_src,27049 field_name_src,
27048 "no member named '{}' in '{}'",27050 "no member named '{f}' in '{f}'",
27049 .{ field_name.fmt(ip), object_ty.fmt(pt) },27051 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27050 );27052 );
27051 }27053 }
...@@ -27069,7 +27071,7 @@ fn fieldVal(...@@ -27069,7 +27071,7 @@ fn fieldVal(
27069 return sema.fail(27071 return sema.fail(
27070 block,27072 block,
27071 field_name_src,27073 field_name_src,
27072 "no member named '{}' in '{}'",27074 "no member named '{f}' in '{f}'",
27073 .{ field_name.fmt(ip), object_ty.fmt(pt) },27075 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27074 );27076 );
27075 }27077 }
...@@ -27089,7 +27091,7 @@ fn fieldVal(...@@ -27089,7 +27091,7 @@ fn fieldVal(
27089 switch (ip.indexToKey(child_type.toIntern())) {27091 switch (ip.indexToKey(child_type.toIntern())) {
27090 .error_set_type => |error_set_type| blk: {27092 .error_set_type => |error_set_type| blk: {
27091 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;27093 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;
27092 return sema.fail(block, src, "no error named '{}' in '{}'", .{27094 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
27093 field_name.fmt(ip), child_type.fmt(pt),27095 field_name.fmt(ip), child_type.fmt(pt),
27094 });27096 });
27095 },27097 },
...@@ -27144,7 +27146,7 @@ fn fieldVal(...@@ -27144,7 +27146,7 @@ fn fieldVal(
27144 return sema.failWithBadMemberAccess(block, child_type, src, field_name);27146 return sema.failWithBadMemberAccess(block, child_type, src, field_name);
27145 },27147 },
27146 else => return sema.failWithOwnedErrorMsg(block, msg: {27148 else => return sema.failWithOwnedErrorMsg(block, msg: {
27147 const msg = try sema.errMsg(src, "type '{}' has no members", .{child_type.fmt(pt)});27149 const msg = try sema.errMsg(src, "type '{f}' has no members", .{child_type.fmt(pt)});
27148 errdefer msg.destroy(sema.gpa);27150 errdefer msg.destroy(sema.gpa);
27149 if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{});27151 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", .{});27152 if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{});
...@@ -27190,7 +27192,7 @@ fn fieldPtr(...@@ -27190,7 +27192,7 @@ fn fieldPtr(
27190 const object_ptr_ty = sema.typeOf(object_ptr);27192 const object_ptr_ty = sema.typeOf(object_ptr);
27191 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {27193 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {
27192 .pointer => object_ptr_ty.childType(zcu),27194 .pointer => object_ptr_ty.childType(zcu),
27193 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(pt)}),27195 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{f}'", .{object_ptr_ty.fmt(pt)}),
27194 };27196 };
2719527197
27196 // Zig allows dereferencing a single pointer during field lookup. Note that27198 // Zig allows dereferencing a single pointer during field lookup. Note that
...@@ -27243,7 +27245,7 @@ fn fieldPtr(...@@ -27243,7 +27245,7 @@ fn fieldPtr(
27243 return sema.fail(27245 return sema.fail(
27244 block,27246 block,
27245 field_name_src,27247 field_name_src,
27246 "no member named '{}' in '{}'",27248 "no member named '{f}' in '{f}'",
27247 .{ field_name.fmt(ip), object_ty.fmt(pt) },27249 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27248 );27250 );
27249 }27251 }
...@@ -27298,7 +27300,7 @@ fn fieldPtr(...@@ -27298,7 +27300,7 @@ fn fieldPtr(
27298 return sema.fail(27300 return sema.fail(
27299 block,27301 block,
27300 field_name_src,27302 field_name_src,
27301 "no member named '{}' in '{}'",27303 "no member named '{f}' in '{f}'",
27302 .{ field_name.fmt(ip), object_ty.fmt(pt) },27304 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27303 );27305 );
27304 }27306 }
...@@ -27321,7 +27323,7 @@ fn fieldPtr(...@@ -27321,7 +27323,7 @@ fn fieldPtr(
27321 if (error_set_type.nameIndex(ip, field_name) != null) {27323 if (error_set_type.nameIndex(ip, field_name) != null) {
27322 break :blk;27324 break :blk;
27323 }27325 }
27324 return sema.fail(block, src, "no error named '{}' in '{}'", .{27326 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
27325 field_name.fmt(ip), child_type.fmt(pt),27327 field_name.fmt(ip), child_type.fmt(pt),
27326 });27328 });
27327 },27329 },
...@@ -27375,7 +27377,7 @@ fn fieldPtr(...@@ -27375,7 +27377,7 @@ fn fieldPtr(
27375 }27377 }
27376 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);27378 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
27377 },27379 },
27378 else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(pt)}),27380 else => return sema.fail(block, src, "type '{f}' has no members", .{child_type.fmt(pt)}),
27379 }27381 }
27380 },27382 },
27381 .@"struct" => {27383 .@"struct" => {
...@@ -27430,7 +27432,7 @@ fn fieldCallBind(...@@ -27430,7 +27432,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))27432 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)27433 raw_ptr_ty.childType(zcu)
27432 else27434 else
27433 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(pt)});27435 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{f}'", .{raw_ptr_ty.fmt(pt)});
2743427436
27435 // Optionally dereference a second pointer to get the concrete type.27437 // 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;27438 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;
...@@ -27549,7 +27551,7 @@ fn fieldCallBind(...@@ -27549,7 +27551,7 @@ fn fieldCallBind(
27549 };27551 };
2755027552
27551 const msg = msg: {27553 const msg = msg: {
27552 const msg = try sema.errMsg(src, "no field or member function named '{}' in '{}'", .{27554 const msg = try sema.errMsg(src, "no field or member function named '{f}' in '{f}'", .{
27553 field_name.fmt(ip),27555 field_name.fmt(ip),
27554 concrete_ty.fmt(pt),27556 concrete_ty.fmt(pt),
27555 });27557 });
...@@ -27559,7 +27561,7 @@ fn fieldCallBind(...@@ -27559,7 +27561,7 @@ fn fieldCallBind(
27559 try sema.errNote(27561 try sema.errNote(
27560 zcu.navSrcLoc(nav_index),27562 zcu.navSrcLoc(nav_index),
27561 msg,27563 msg,
27562 "'{}' is not a member function",27564 "'{f}' is not a member function",
27563 .{field_name.fmt(ip)},27565 .{field_name.fmt(ip)},
27564 );27566 );
27565 }27567 }
...@@ -27627,7 +27629,7 @@ fn namespaceLookup(...@@ -27627,7 +27629,7 @@ fn namespaceLookup(
27627 if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {27629 if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {
27628 if (!lookup.accessible) {27630 if (!lookup.accessible) {
27629 return sema.failWithOwnedErrorMsg(block, msg: {27631 return sema.failWithOwnedErrorMsg(block, msg: {
27630 const msg = try sema.errMsg(src, "'{}' is not marked 'pub'", .{27632 const msg = try sema.errMsg(src, "'{f}' is not marked 'pub'", .{
27631 decl_name.fmt(&zcu.intern_pool),27633 decl_name.fmt(&zcu.intern_pool),
27632 });27634 });
27633 errdefer msg.destroy(gpa);27635 errdefer msg.destroy(gpa);
...@@ -27865,12 +27867,12 @@ fn tupleFieldIndex(...@@ -27865,12 +27867,12 @@ fn tupleFieldIndex(
27865 assert(!field_name.eqlSlice("len", ip));27867 assert(!field_name.eqlSlice("len", ip));
27866 if (field_name.toUnsigned(ip)) |field_index| {27868 if (field_name.toUnsigned(ip)) |field_index| {
27867 if (field_index < tuple_ty.structFieldCount(pt.zcu)) return field_index;27869 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 '{}'", .{27870 return sema.fail(block, field_name_src, "index '{f}' out of bounds of tuple '{f}'", .{
27869 field_name.fmt(ip), tuple_ty.fmt(pt),27871 field_name.fmt(ip), tuple_ty.fmt(pt),
27870 });27872 });
27871 }27873 }
2787227874
27873 return sema.fail(block, field_name_src, "no field named '{}' in tuple '{}'", .{27875 return sema.fail(block, field_name_src, "no field named '{f}' in tuple '{f}'", .{
27874 field_name.fmt(ip), tuple_ty.fmt(pt),27876 field_name.fmt(ip), tuple_ty.fmt(pt),
27875 });27877 });
27876}27878}
...@@ -27957,7 +27959,7 @@ fn unionFieldPtr(...@@ -27957,7 +27959,7 @@ fn unionFieldPtr(
27957 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});27959 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
27958 errdefer msg.destroy(sema.gpa);27960 errdefer msg.destroy(sema.gpa);
2795927961
27960 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{27962 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
27961 field_name.fmt(ip),27963 field_name.fmt(ip),
27962 });27964 });
27963 try sema.addDeclaredHereNote(msg, union_ty);27965 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -27991,7 +27993,7 @@ fn unionFieldPtr(...@@ -27991,7 +27993,7 @@ fn unionFieldPtr(
27991 const msg = msg: {27993 const msg = msg: {
27992 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;27994 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);27995 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", .{27996 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
27995 field_name.fmt(ip),27997 field_name.fmt(ip),
27996 active_field_name.fmt(ip),27998 active_field_name.fmt(ip),
27997 });27999 });
...@@ -28059,7 +28061,7 @@ fn unionFieldVal(...@@ -28059,7 +28061,7 @@ fn unionFieldVal(
28059 const msg = msg: {28061 const msg = msg: {
28060 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;28062 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);28063 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", .{28064 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),28065 field_name.fmt(ip), active_field_name.fmt(ip),
28064 });28066 });
28065 errdefer msg.destroy(sema.gpa);28067 errdefer msg.destroy(sema.gpa);
...@@ -28117,7 +28119,7 @@ fn elemPtr(...@@ -28117,7 +28119,7 @@ fn elemPtr(
2811728119
28118 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {28120 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {
28119 .pointer => indexable_ptr_ty.childType(zcu),28121 .pointer => indexable_ptr_ty.childType(zcu),
28120 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(pt)}),28122 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}),
28121 };28123 };
28122 try sema.checkIndexable(block, src, indexable_ty);28124 try sema.checkIndexable(block, src, indexable_ty);
2812328125
...@@ -28288,7 +28290,7 @@ fn validateRuntimeElemAccess(...@@ -28288,7 +28290,7 @@ fn validateRuntimeElemAccess(
28288 const msg = msg: {28290 const msg = msg: {
28289 const msg = try sema.errMsg(28291 const msg = try sema.errMsg(
28290 elem_index_src,28292 elem_index_src,
28291 "values of type '{}' must be comptime-known, but index value is runtime-known",28293 "values of type '{f}' must be comptime-known, but index value is runtime-known",
28292 .{parent_ty.fmt(sema.pt)},28294 .{parent_ty.fmt(sema.pt)},
28293 );28295 );
28294 errdefer msg.destroy(sema.gpa);28296 errdefer msg.destroy(sema.gpa);
...@@ -28304,7 +28306,7 @@ fn validateRuntimeElemAccess(...@@ -28304,7 +28306,7 @@ fn validateRuntimeElemAccess(
28304 const target = zcu.getTarget();28306 const target = zcu.getTarget();
28305 const as = parent_ty.ptrAddressSpace(zcu);28307 const as = parent_ty.ptrAddressSpace(zcu);
28306 if (target_util.arePointersLogical(target, as)) {28308 if (target_util.arePointersLogical(target, as)) {
28307 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{}'", .{parent_ty.fmt(pt)});28309 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{f}'", .{parent_ty.fmt(pt)});
28308 }28310 }
28309 }28311 }
28310}28312}
...@@ -29000,7 +29002,7 @@ fn coerceExtra(...@@ -29000,7 +29002,7 @@ fn coerceExtra(
29000 return sema.fail(29002 return sema.fail(
29001 block,29003 block,
29002 inst_src,29004 inst_src,
29003 "array literal requires address-of operator (&) to coerce to slice type '{}'",29005 "array literal requires address-of operator (&) to coerce to slice type '{f}'",
29004 .{dest_ty.fmt(pt)},29006 .{dest_ty.fmt(pt)},
29005 );29007 );
29006 }29008 }
...@@ -29027,7 +29029,7 @@ fn coerceExtra(...@@ -29027,7 +29029,7 @@ fn coerceExtra(
29027 // pointer to tuple to slice29029 // pointer to tuple to slice
29028 if (!dest_info.flags.is_const) {29030 if (!dest_info.flags.is_const) {
29029 const err_msg = err_msg: {29031 const err_msg = err_msg: {
29030 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(pt)});29032 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);29033 errdefer err_msg.destroy(sema.gpa);
29032 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});29034 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
29033 break :err_msg err_msg;29035 break :err_msg err_msg;
...@@ -29082,7 +29084,7 @@ fn coerceExtra(...@@ -29082,7 +29084,7 @@ fn coerceExtra(
29082 // comptime-known integer to other number29084 // comptime-known integer to other number
29083 if (!(try sema.intFitsInType(val, dest_ty, null))) {29085 if (!(try sema.intFitsInType(val, dest_ty, null))) {
29084 if (!opts.report_err) return error.NotCoercible;29086 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) });29087 return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) });
29086 }29088 }
29087 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {29089 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
29088 .undef => try pt.undefRef(dest_ty),29090 .undef => try pt.undefRef(dest_ty),
...@@ -29124,7 +29126,7 @@ fn coerceExtra(...@@ -29124,7 +29126,7 @@ fn coerceExtra(
29124 return sema.fail(29126 return sema.fail(
29125 block,29127 block,
29126 inst_src,29128 inst_src,
29127 "type '{}' cannot represent float value '{}'",29129 "type '{f}' cannot represent float value '{f}'",
29128 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },29130 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },
29129 );29131 );
29130 }29132 }
...@@ -29157,7 +29159,7 @@ fn coerceExtra(...@@ -29157,7 +29159,7 @@ fn coerceExtra(
29157 // return sema.fail(29159 // return sema.fail(
29158 // block,29160 // block,
29159 // inst_src,29161 // inst_src,
29160 // "type '{}' cannot represent integer value '{}'",29162 // "type '{f}' cannot represent integer value '{f}'",
29161 // .{ dest_ty.fmt(pt), val },29163 // .{ dest_ty.fmt(pt), val },
29162 // );29164 // );
29163 //}29165 //}
...@@ -29171,7 +29173,7 @@ fn coerceExtra(...@@ -29171,7 +29173,7 @@ fn coerceExtra(
29171 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);29173 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
29172 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;29174 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
29173 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {29175 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {
29174 return sema.fail(block, inst_src, "no field named '{}' in enum '{}'", .{29176 return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{
29175 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),29177 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
29176 });29178 });
29177 };29179 };
...@@ -29320,11 +29322,11 @@ fn coerceExtra(...@@ -29320,11 +29322,11 @@ fn coerceExtra(
29320 }29322 }
2932129323
29322 const msg = msg: {29324 const msg = msg: {
29323 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(pt), inst_ty.fmt(pt) });29325 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);29326 errdefer msg.destroy(sema.gpa);
2932529327
29326 if (!can_coerce_to) {29328 if (!can_coerce_to) {
29327 try sema.errNote(inst_src, msg, "cannot coerce to '{}'", .{dest_ty.fmt(pt)});29329 try sema.errNote(inst_src, msg, "cannot coerce to '{f}'", .{dest_ty.fmt(pt)});
29328 }29330 }
2932929331
29330 // E!T to T29332 // E!T to T
...@@ -29364,7 +29366,7 @@ fn coerceExtra(...@@ -29364,7 +29366,7 @@ fn coerceExtra(
29364 try sema.errNote(param_src, msg, "parameter type declared here", .{});29366 try sema.errNote(param_src, msg, "parameter type declared here", .{});
29365 }29367 }
2936629368
29367 // TODO maybe add "cannot store an error in type '{}'" note29369 // TODO maybe add "cannot store an error in type '{f}'" note
2936829370
29369 break :msg msg;29371 break :msg msg;
29370 };29372 };
...@@ -29513,13 +29515,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29513,13 +29515,13 @@ const InMemoryCoercionResult = union(enum) {
29513 break;29515 break;
29514 },29516 },
29515 .comptime_int_not_coercible => |int| {29517 .comptime_int_not_coercible => |int| {
29516 try sema.errNote(src, msg, "type '{}' cannot represent value '{}'", .{29518 try sema.errNote(src, msg, "type '{f}' cannot represent value '{f}'", .{
29517 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),29519 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),
29518 });29520 });
29519 break;29521 break;
29520 },29522 },
29521 .error_union_payload => |pair| {29523 .error_union_payload => |pair| {
29522 try sema.errNote(src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{29524 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),29525 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29524 });29526 });
29525 cur = pair.child;29527 cur = pair.child;
...@@ -29532,18 +29534,18 @@ const InMemoryCoercionResult = union(enum) {...@@ -29532,18 +29534,18 @@ const InMemoryCoercionResult = union(enum) {
29532 },29534 },
29533 .array_sentinel => |sentinel| {29535 .array_sentinel => |sentinel| {
29534 if (sentinel.actual.toIntern() != .unreachable_value) {29536 if (sentinel.actual.toIntern() != .unreachable_value) {
29535 try sema.errNote(src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{29537 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),29538 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29537 });29539 });
29538 } else {29540 } else {
29539 try sema.errNote(src, msg, "destination array requires '{}' sentinel", .{29541 try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
29540 sentinel.wanted.fmtValueSema(pt, sema),29542 sentinel.wanted.fmtValueSema(pt, sema),
29541 });29543 });
29542 }29544 }
29543 break;29545 break;
29544 },29546 },
29545 .array_elem => |pair| {29547 .array_elem => |pair| {
29546 try sema.errNote(src, msg, "array element type '{}' cannot cast into array element type '{}'", .{29548 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),29549 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29548 });29550 });
29549 cur = pair.child;29551 cur = pair.child;
...@@ -29555,19 +29557,19 @@ const InMemoryCoercionResult = union(enum) {...@@ -29555,19 +29557,19 @@ const InMemoryCoercionResult = union(enum) {
29555 break;29557 break;
29556 },29558 },
29557 .vector_elem => |pair| {29559 .vector_elem => |pair| {
29558 try sema.errNote(src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{29560 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),29561 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29560 });29562 });
29561 cur = pair.child;29563 cur = pair.child;
29562 },29564 },
29563 .optional_shape => |pair| {29565 .optional_shape => |pair| {
29564 try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{29566 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),29567 pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt),
29566 });29568 });
29567 break;29569 break;
29568 },29570 },
29569 .optional_child => |pair| {29571 .optional_child => |pair| {
29570 try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{29572 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),29573 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29572 });29574 });
29573 cur = pair.child;29575 cur = pair.child;
...@@ -29578,7 +29580,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29578,7 +29580,7 @@ const InMemoryCoercionResult = union(enum) {
29578 },29580 },
29579 .missing_error => |missing_errors| {29581 .missing_error => |missing_errors| {
29580 for (missing_errors) |err| {29582 for (missing_errors) |err| {
29581 try sema.errNote(src, msg, "'error.{}' not a member of destination error set", .{err.fmt(&pt.zcu.intern_pool)});29583 try sema.errNote(src, msg, "'error.{f}' not a member of destination error set", .{err.fmt(&pt.zcu.intern_pool)});
29582 }29584 }
29583 break;29585 break;
29584 },29586 },
...@@ -29631,7 +29633,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29631,7 +29633,7 @@ const InMemoryCoercionResult = union(enum) {
29631 break;29633 break;
29632 },29634 },
29633 .fn_param => |param| {29635 .fn_param => |param| {
29634 try sema.errNote(src, msg, "parameter {d} '{}' cannot cast into '{}'", .{29636 try sema.errNote(src, msg, "parameter {d} '{f}' cannot cast into '{f}'", .{
29635 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),29637 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),
29636 });29638 });
29637 cur = param.child;29639 cur = param.child;
...@@ -29641,13 +29643,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29641,13 +29643,13 @@ const InMemoryCoercionResult = union(enum) {
29641 break;29643 break;
29642 },29644 },
29643 .fn_return_type => |pair| {29645 .fn_return_type => |pair| {
29644 try sema.errNote(src, msg, "return type '{}' cannot cast into return type '{}'", .{29646 try sema.errNote(src, msg, "return type '{f}' cannot cast into return type '{f}'", .{
29645 pair.actual.fmt(pt), pair.wanted.fmt(pt),29647 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29646 });29648 });
29647 cur = pair.child;29649 cur = pair.child;
29648 },29650 },
29649 .ptr_child => |pair| {29651 .ptr_child => |pair| {
29650 try sema.errNote(src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{29652 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),29653 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29652 });29654 });
29653 cur = pair.child;29655 cur = pair.child;
...@@ -29658,11 +29660,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29658,11 +29660,11 @@ const InMemoryCoercionResult = union(enum) {
29658 },29660 },
29659 .ptr_sentinel => |sentinel| {29661 .ptr_sentinel => |sentinel| {
29660 if (sentinel.actual.toIntern() != .unreachable_value) {29662 if (sentinel.actual.toIntern() != .unreachable_value) {
29661 try sema.errNote(src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{29663 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),29664 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29663 });29665 });
29664 } else {29666 } else {
29665 try sema.errNote(src, msg, "destination pointer requires '{}' sentinel", .{29667 try sema.errNote(src, msg, "destination pointer requires '{f}' sentinel", .{
29666 sentinel.wanted.fmtValueSema(pt, sema),29668 sentinel.wanted.fmtValueSema(pt, sema),
29667 });29669 });
29668 }29670 }
...@@ -29676,11 +29678,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29676,11 +29678,11 @@ const InMemoryCoercionResult = union(enum) {
29676 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);29678 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);
29677 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);29679 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);
29678 if (actual_allow_zero and !wanted_allow_zero) {29680 if (actual_allow_zero and !wanted_allow_zero) {
29679 try sema.errNote(src, msg, "'{}' could have null values which are illegal in type '{}'", .{29681 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),29682 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29681 });29683 });
29682 } else {29684 } else {
29683 try sema.errNote(src, msg, "mutable '{}' would allow illegal null values stored to type '{}'", .{29685 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),29686 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29685 });29687 });
29686 }29688 }
...@@ -29692,7 +29694,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29692,7 +29694,7 @@ const InMemoryCoercionResult = union(enum) {
29692 if (actual_const and !wanted_const) {29694 if (actual_const and !wanted_const) {
29693 try sema.errNote(src, msg, "cast discards const qualifier", .{});29695 try sema.errNote(src, msg, "cast discards const qualifier", .{});
29694 } else {29696 } else {
29695 try sema.errNote(src, msg, "mutable '{}' would allow illegal const pointers stored to type '{}'", .{29697 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),29698 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29697 });29699 });
29698 }29700 }
...@@ -29704,7 +29706,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29704,7 +29706,7 @@ const InMemoryCoercionResult = union(enum) {
29704 if (actual_volatile and !wanted_volatile) {29706 if (actual_volatile and !wanted_volatile) {
29705 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});29707 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});
29706 } else {29708 } else {
29707 try sema.errNote(src, msg, "mutable '{}' would allow illegal volatile pointers stored to type '{}'", .{29709 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),29710 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29709 });29711 });
29710 }29712 }
...@@ -29712,12 +29714,12 @@ const InMemoryCoercionResult = union(enum) {...@@ -29712,12 +29714,12 @@ const InMemoryCoercionResult = union(enum) {
29712 },29714 },
29713 .ptr_bit_range => |bit_range| {29715 .ptr_bit_range => |bit_range| {
29714 if (bit_range.actual_host != bit_range.wanted_host) {29716 if (bit_range.actual_host != bit_range.wanted_host) {
29715 try sema.errNote(src, msg, "pointer host size '{}' cannot cast into pointer host size '{}'", .{29717 try sema.errNote(src, msg, "pointer host size '{d}' cannot cast into pointer host size '{d}'", .{
29716 bit_range.actual_host, bit_range.wanted_host,29718 bit_range.actual_host, bit_range.wanted_host,
29717 });29719 });
29718 }29720 }
29719 if (bit_range.actual_offset != bit_range.wanted_offset) {29721 if (bit_range.actual_offset != bit_range.wanted_offset) {
29720 try sema.errNote(src, msg, "pointer bit offset '{}' cannot cast into pointer bit offset '{}'", .{29722 try sema.errNote(src, msg, "pointer bit offset '{d}' cannot cast into pointer bit offset '{d}'", .{
29721 bit_range.actual_offset, bit_range.wanted_offset,29723 bit_range.actual_offset, bit_range.wanted_offset,
29722 });29724 });
29723 }29725 }
...@@ -29730,13 +29732,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29730,13 +29732,13 @@ const InMemoryCoercionResult = union(enum) {
29730 break;29732 break;
29731 },29733 },
29732 .double_ptr_to_anyopaque => |pair| {29734 .double_ptr_to_anyopaque => |pair| {
29733 try sema.errNote(src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{29735 try sema.errNote(src, msg, "cannot implicitly cast double pointer '{f}' to anyopaque pointer '{f}'", .{
29734 pair.actual.fmt(pt), pair.wanted.fmt(pt),29736 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29735 });29737 });
29736 break;29738 break;
29737 },29739 },
29738 .slice_to_anyopaque => |pair| {29740 .slice_to_anyopaque => |pair| {
29739 try sema.errNote(src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{29741 try sema.errNote(src, msg, "cannot implicitly cast slice '{f}' to anyopaque pointer '{f}'", .{
29740 pair.actual.fmt(pt), pair.wanted.fmt(pt),29742 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29741 });29743 });
29742 try sema.errNote(src, msg, "consider using '.ptr'", .{});29744 try sema.errNote(src, msg, "consider using '.ptr'", .{});
...@@ -30510,7 +30512,7 @@ fn coerceVarArgParam(...@@ -30510,7 +30512,7 @@ fn coerceVarArgParam(
30510 const coerced_ty = sema.typeOf(coerced);30512 const coerced_ty = sema.typeOf(coerced);
30511 if (!try sema.validateExternType(coerced_ty, .param_ty)) {30513 if (!try sema.validateExternType(coerced_ty, .param_ty)) {
30512 const msg = msg: {30514 const msg = msg: {
30513 const msg = try sema.errMsg(inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(pt)});30515 const msg = try sema.errMsg(inst_src, "cannot pass '{f}' to variadic function", .{coerced_ty.fmt(pt)});
30514 errdefer msg.destroy(sema.gpa);30516 errdefer msg.destroy(sema.gpa);
3051530517
30516 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);30518 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);
...@@ -30613,7 +30615,7 @@ fn storePtr2(...@@ -30613,7 +30615,7 @@ fn storePtr2(
30613 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.30615 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.
30614 if (try elem_ty.comptimeOnlySema(pt)) {30616 if (try elem_ty.comptimeOnlySema(pt)) {
30615 return sema.failWithOwnedErrorMsg(block, msg: {30617 return sema.failWithOwnedErrorMsg(block, msg: {
30616 const msg = try sema.errMsg(src, "cannot store comptime-only type '{}' at runtime", .{elem_ty.fmt(pt)});30618 const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)});
30617 errdefer msg.destroy(sema.gpa);30619 errdefer msg.destroy(sema.gpa);
30618 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});30620 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});
30619 break :msg msg;30621 break :msg msg;
...@@ -30646,7 +30648,7 @@ fn storePtr2(...@@ -30646,7 +30648,7 @@ fn storePtr2(
30646 });30648 });
30647 return;30649 return;
30648 }30650 }
30649 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{30651 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
30650 ptr_ty.fmt(pt),30652 ptr_ty.fmt(pt),
30651 });30653 });
30652 }30654 }
...@@ -30815,19 +30817,19 @@ fn storePtrVal(...@@ -30815,19 +30817,19 @@ fn storePtrVal(
30815 .{},30817 .{},
30816 ),30818 ),
30817 .undef => return sema.failWithUseOfUndef(block, src),30819 .undef => return sema.failWithUseOfUndef(block, src),
30818 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {}", .{err_name.fmt(ip)}),30820 .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", .{}),30821 .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", .{}),30822 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
30821 .needed_well_defined => |ty| return sema.fail(30823 .needed_well_defined => |ty| return sema.fail(
30822 block,30824 block,
30823 src,30825 src,
30824 "comptime dereference requires '{}' to have a well-defined layout",30826 "comptime dereference requires '{f}' to have a well-defined layout",
30825 .{ty.fmt(pt)},30827 .{ty.fmt(pt)},
30826 ),30828 ),
30827 .out_of_bounds => |ty| return sema.fail(30829 .out_of_bounds => |ty| return sema.fail(
30828 block,30830 block,
30829 src,30831 src,
30830 "dereference of '{}' exceeds bounds of containing decl of type '{}'",30832 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
30831 .{ ptr_ty.fmt(pt), ty.fmt(pt) },30833 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
30832 ),30834 ),
30833 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),30835 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),
...@@ -30853,7 +30855,7 @@ fn bitCast(...@@ -30853,7 +30855,7 @@ fn bitCast(
30853 const old_bits = old_ty.bitSize(zcu);30855 const old_bits = old_ty.bitSize(zcu);
3085430856
30855 if (old_bits != dest_bits) {30857 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", .{30858 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),30859 dest_ty.fmt(pt),
30858 dest_bits,30860 dest_bits,
30859 old_ty.fmt(pt),30861 old_ty.fmt(pt),
...@@ -30971,7 +30973,7 @@ fn coerceCompatiblePtrs(...@@ -30971,7 +30973,7 @@ fn coerceCompatiblePtrs(
30971 const inst_ty = sema.typeOf(inst);30973 const inst_ty = sema.typeOf(inst);
30972 if (try sema.resolveValue(inst)) |val| {30974 if (try sema.resolveValue(inst)) |val| {
30973 if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) {30975 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)});30976 return sema.fail(block, inst_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)});
30975 }30977 }
30976 // The comptime Value representation is compatible with both types.30978 // The comptime Value representation is compatible with both types.
30977 return Air.internedToRef(30979 return Air.internedToRef(
...@@ -31017,7 +31019,7 @@ fn coerceEnumToUnion(...@@ -31017,7 +31019,7 @@ fn coerceEnumToUnion(
3101731019
31018 const tag_ty = union_ty.unionTagType(zcu) orelse {31020 const tag_ty = union_ty.unionTagType(zcu) orelse {
31019 const msg = msg: {31021 const msg = msg: {
31020 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{31022 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
31021 union_ty.fmt(pt), inst_ty.fmt(pt),31023 union_ty.fmt(pt), inst_ty.fmt(pt),
31022 });31024 });
31023 errdefer msg.destroy(sema.gpa);31025 errdefer msg.destroy(sema.gpa);
...@@ -31031,7 +31033,7 @@ fn coerceEnumToUnion(...@@ -31031,7 +31033,7 @@ fn coerceEnumToUnion(
31031 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);31033 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);
31032 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {31034 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {
31033 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {31035 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {
31034 return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{31036 return sema.fail(block, inst_src, "union '{f}' has no tag with value '{f}'", .{
31035 union_ty.fmt(pt), val.fmtValueSema(pt, sema),31037 union_ty.fmt(pt), val.fmtValueSema(pt, sema),
31036 });31038 });
31037 };31039 };
...@@ -31045,7 +31047,7 @@ fn coerceEnumToUnion(...@@ -31045,7 +31047,7 @@ fn coerceEnumToUnion(
31045 errdefer msg.destroy(sema.gpa);31047 errdefer msg.destroy(sema.gpa);
3104631048
31047 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31049 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31048 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{31050 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
31049 field_name.fmt(ip),31051 field_name.fmt(ip),
31050 });31052 });
31051 try sema.addDeclaredHereNote(msg, union_ty);31053 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -31056,13 +31058,13 @@ fn coerceEnumToUnion(...@@ -31056,13 +31058,13 @@ fn coerceEnumToUnion(
31056 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {31058 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
31057 const msg = msg: {31059 const msg = msg: {
31058 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31060 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 '{}'", .{31061 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),31062 inst_ty.fmt(pt), union_ty.fmt(pt),
31061 field_ty.fmt(pt), field_name.fmt(ip),31063 field_ty.fmt(pt), field_name.fmt(ip),
31062 });31064 });
31063 errdefer msg.destroy(sema.gpa);31065 errdefer msg.destroy(sema.gpa);
3106431066
31065 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{31067 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
31066 field_name.fmt(ip),31068 field_name.fmt(ip),
31067 });31069 });
31068 try sema.addDeclaredHereNote(msg, union_ty);31070 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -31078,7 +31080,7 @@ fn coerceEnumToUnion(...@@ -31078,7 +31080,7 @@ fn coerceEnumToUnion(
3107831080
31079 if (tag_ty.isNonexhaustiveEnum(zcu)) {31081 if (tag_ty.isNonexhaustiveEnum(zcu)) {
31080 const msg = msg: {31082 const msg = msg: {
31081 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{31083 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{f}' from non-exhaustive enum", .{
31082 union_ty.fmt(pt),31084 union_ty.fmt(pt),
31083 });31085 });
31084 errdefer msg.destroy(sema.gpa);31086 errdefer msg.destroy(sema.gpa);
...@@ -31097,7 +31099,7 @@ fn coerceEnumToUnion(...@@ -31097,7 +31099,7 @@ fn coerceEnumToUnion(
31097 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {31099 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {
31098 const err_msg = msg orelse try sema.errMsg(31100 const err_msg = msg orelse try sema.errMsg(
31099 inst_src,31101 inst_src,
31100 "runtime coercion from enum '{}' to union '{}' which has a 'noreturn' field",31102 "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field",
31101 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },31103 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
31102 );31104 );
31103 msg = err_msg;31105 msg = err_msg;
...@@ -31120,7 +31122,7 @@ fn coerceEnumToUnion(...@@ -31120,7 +31122,7 @@ fn coerceEnumToUnion(
31120 const msg = msg: {31122 const msg = msg: {
31121 const msg = try sema.errMsg(31123 const msg = try sema.errMsg(
31122 inst_src,31124 inst_src,
31123 "runtime coercion from enum '{}' to union '{}' which has non-void fields",31125 "runtime coercion from enum '{f}' to union '{f}' which has non-void fields",
31124 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },31126 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
31125 );31127 );
31126 errdefer msg.destroy(sema.gpa);31128 errdefer msg.destroy(sema.gpa);
...@@ -31129,7 +31131,7 @@ fn coerceEnumToUnion(...@@ -31129,7 +31131,7 @@ fn coerceEnumToUnion(
31129 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31131 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]);31132 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
31131 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;31133 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;
31132 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{31134 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{
31133 field_name.fmt(ip),31135 field_name.fmt(ip),
31134 field_ty.fmt(pt),31136 field_ty.fmt(pt),
31135 });31137 });
...@@ -31170,7 +31172,7 @@ fn coerceArrayLike(...@@ -31170,7 +31172,7 @@ fn coerceArrayLike(
31170 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));31172 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));
31171 if (dest_len != inst_len) {31173 if (dest_len != inst_len) {
31172 const msg = msg: {31174 const msg = msg: {
31173 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{31175 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
31174 dest_ty.fmt(pt), inst_ty.fmt(pt),31176 dest_ty.fmt(pt), inst_ty.fmt(pt),
31175 });31177 });
31176 errdefer msg.destroy(sema.gpa);31178 errdefer msg.destroy(sema.gpa);
...@@ -31258,7 +31260,7 @@ fn coerceTupleToArray(...@@ -31258,7 +31260,7 @@ fn coerceTupleToArray(
3125831260
31259 if (dest_len != inst_len) {31261 if (dest_len != inst_len) {
31260 const msg = msg: {31262 const msg = msg: {
31261 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{31263 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
31262 dest_ty.fmt(pt), inst_ty.fmt(pt),31264 dest_ty.fmt(pt), inst_ty.fmt(pt),
31263 });31265 });
31264 errdefer msg.destroy(sema.gpa);31266 errdefer msg.destroy(sema.gpa);
...@@ -31734,10 +31736,10 @@ fn analyzeLoad(...@@ -31734,10 +31736,10 @@ fn analyzeLoad(
31734 const ptr_ty = sema.typeOf(ptr);31736 const ptr_ty = sema.typeOf(ptr);
31735 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {31737 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {
31736 .pointer => ptr_ty.childType(zcu),31738 .pointer => ptr_ty.childType(zcu),
31737 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(pt)}),31739 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}),
31738 };31740 };
31739 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {31741 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {
31740 return sema.fail(block, ptr_src, "cannot load opaque type '{}'", .{elem_ty.fmt(pt)});31742 return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)});
31741 }31743 }
3174231744
31743 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {31745 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {
...@@ -31758,7 +31760,7 @@ fn analyzeLoad(...@@ -31758,7 +31760,7 @@ fn analyzeLoad(
31758 const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;31760 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);31761 return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
31760 }31762 }
31761 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{31763 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
31762 ptr_ty.fmt(pt),31764 ptr_ty.fmt(pt),
31763 });31765 });
31764 }31766 }
...@@ -32046,7 +32048,7 @@ fn analyzeSlice(...@@ -32046,7 +32048,7 @@ fn analyzeSlice(
32046 const ptr_ptr_ty = sema.typeOf(ptr_ptr);32048 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
32047 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {32049 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {
32048 .pointer => ptr_ptr_ty.childType(zcu),32050 .pointer => ptr_ptr_ty.childType(zcu),
32049 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(pt)}),32051 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ptr_ty.fmt(pt)}),
32050 };32052 };
3205132053
32052 var array_ty = ptr_ptr_child_ty;32054 var array_ty = ptr_ptr_child_ty;
...@@ -32095,7 +32097,7 @@ fn analyzeSlice(...@@ -32095,7 +32097,7 @@ fn analyzeSlice(
32095 try sema.errNote(32097 try sema.errNote(
32096 start_src,32098 start_src,
32097 msg,32099 msg,
32098 "expected '{}', found '{}'",32100 "expected '{f}', found '{f}'",
32099 .{32101 .{
32100 Value.zero_comptime_int.fmtValueSema(pt, sema),32102 Value.zero_comptime_int.fmtValueSema(pt, sema),
32101 start_value.fmtValueSema(pt, sema),32103 start_value.fmtValueSema(pt, sema),
...@@ -32111,7 +32113,7 @@ fn analyzeSlice(...@@ -32111,7 +32113,7 @@ fn analyzeSlice(
32111 try sema.errNote(32113 try sema.errNote(
32112 end_src,32114 end_src,
32113 msg,32115 msg,
32114 "expected '{}', found '{}'",32116 "expected '{f}', found '{f}'",
32115 .{32117 .{
32116 Value.one_comptime_int.fmtValueSema(pt, sema),32118 Value.one_comptime_int.fmtValueSema(pt, sema),
32117 end_value.fmtValueSema(pt, sema),32119 end_value.fmtValueSema(pt, sema),
...@@ -32126,7 +32128,7 @@ fn analyzeSlice(...@@ -32126,7 +32128,7 @@ fn analyzeSlice(
32126 return sema.fail(32128 return sema.fail(
32127 block,32129 block,
32128 end_src,32130 end_src,
32129 "end index {} out of bounds for slice of single-item pointer",32131 "end index {f} out of bounds for slice of single-item pointer",
32130 .{end_value.fmtValueSema(pt, sema)},32132 .{end_value.fmtValueSema(pt, sema)},
32131 );32133 );
32132 }32134 }
...@@ -32173,7 +32175,7 @@ fn analyzeSlice(...@@ -32173,7 +32175,7 @@ fn analyzeSlice(
32173 elem_ty = ptr_ptr_child_ty.childType(zcu);32175 elem_ty = ptr_ptr_child_ty.childType(zcu);
32174 },32176 },
32175 },32177 },
32176 else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(pt)}),32178 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}),
32177 }32179 }
3217832180
32179 const ptr = if (slice_ty.isSlice(zcu))32181 const ptr = if (slice_ty.isSlice(zcu))
...@@ -32220,7 +32222,7 @@ fn analyzeSlice(...@@ -32220,7 +32222,7 @@ fn analyzeSlice(
32220 return sema.fail(32222 return sema.fail(
32221 block,32223 block,
32222 end_src,32224 end_src,
32223 "end index {} out of bounds for array of length {}{s}",32225 "end index {f} out of bounds for array of length {f}{s}",
32224 .{32226 .{
32225 end_val.fmtValueSema(pt, sema),32227 end_val.fmtValueSema(pt, sema),
32226 len_val.fmtValueSema(pt, sema),32228 len_val.fmtValueSema(pt, sema),
...@@ -32265,7 +32267,7 @@ fn analyzeSlice(...@@ -32265,7 +32267,7 @@ fn analyzeSlice(
32265 return sema.fail(32267 return sema.fail(
32266 block,32268 block,
32267 end_src,32269 end_src,
32268 "end index {} out of bounds for slice of length {d}{s}",32270 "end index {f} out of bounds for slice of length {d}{s}",
32269 .{32271 .{
32270 end_val.fmtValueSema(pt, sema),32272 end_val.fmtValueSema(pt, sema),
32271 try slice_val.sliceLen(pt),32273 try slice_val.sliceLen(pt),
...@@ -32324,7 +32326,7 @@ fn analyzeSlice(...@@ -32324,7 +32326,7 @@ fn analyzeSlice(
32324 return sema.fail(32326 return sema.fail(
32325 block,32327 block,
32326 start_src,32328 start_src,
32327 "start index {} is larger than end index {}",32329 "start index {f} is larger than end index {f}",
32328 .{32330 .{
32329 start_val.fmtValueSema(pt, sema),32331 start_val.fmtValueSema(pt, sema),
32330 end_val.fmtValueSema(pt, sema),32332 end_val.fmtValueSema(pt, sema),
...@@ -32348,13 +32350,13 @@ fn analyzeSlice(...@@ -32348,13 +32350,13 @@ fn analyzeSlice(
32348 .needed_well_defined => |ty| return sema.fail(32350 .needed_well_defined => |ty| return sema.fail(
32349 block,32351 block,
32350 src,32352 src,
32351 "comptime dereference requires '{}' to have a well-defined layout",32353 "comptime dereference requires '{f}' to have a well-defined layout",
32352 .{ty.fmt(pt)},32354 .{ty.fmt(pt)},
32353 ),32355 ),
32354 .out_of_bounds => |ty| return sema.fail(32356 .out_of_bounds => |ty| return sema.fail(
32355 block,32357 block,
32356 end_src,32358 end_src,
32357 "slice end index {d} exceeds bounds of containing decl of type '{}'",32359 "slice end index {d} exceeds bounds of containing decl of type '{f}'",
32358 .{ end_int, ty.fmt(pt) },32360 .{ end_int, ty.fmt(pt) },
32359 ),32361 ),
32360 };32362 };
...@@ -32363,7 +32365,7 @@ fn analyzeSlice(...@@ -32363,7 +32365,7 @@ fn analyzeSlice(
32363 const msg = msg: {32365 const msg = msg: {
32364 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});32366 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});
32365 errdefer msg.destroy(sema.gpa);32367 errdefer msg.destroy(sema.gpa);
32366 try sema.errNote(src, msg, "expected '{}', found '{}'", .{32368 try sema.errNote(src, msg, "expected '{f}', found '{f}'", .{
32367 expected_sentinel.fmtValueSema(pt, sema),32369 expected_sentinel.fmtValueSema(pt, sema),
32368 actual_sentinel.fmtValueSema(pt, sema),32370 actual_sentinel.fmtValueSema(pt, sema),
32369 });32371 });
...@@ -33251,7 +33253,7 @@ const PeerResolveResult = union(enum) {...@@ -33251,7 +33253,7 @@ const PeerResolveResult = union(enum) {
33251 };33253 };
33252 },33254 },
33253 .field_error => |field_error| {33255 .field_error => |field_error| {
33254 const fmt = "struct field '{}' has conflicting types";33256 const fmt = "struct field '{f}' has conflicting types";
33255 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};33257 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};
33256 if (opt_msg) |msg| {33258 if (opt_msg) |msg| {
33257 try sema.errNote(src, msg, fmt, args);33259 try sema.errNote(src, msg, fmt, args);
...@@ -33282,7 +33284,7 @@ const PeerResolveResult = union(enum) {...@@ -33282,7 +33284,7 @@ const PeerResolveResult = union(enum) {
33282 candidate_srcs.resolve(block, conflict_idx[1]),33284 candidate_srcs.resolve(block, conflict_idx[1]),
33283 };33285 };
3328433286
33285 const fmt = "incompatible types: '{}' and '{}'";33287 const fmt = "incompatible types: '{f}' and '{f}'";
33286 const args = .{33288 const args = .{
33287 conflict_tys[0].fmt(pt),33289 conflict_tys[0].fmt(pt),
33288 conflict_tys[1].fmt(pt),33290 conflict_tys[1].fmt(pt),
...@@ -33296,8 +33298,8 @@ const PeerResolveResult = union(enum) {...@@ -33296,8 +33298,8 @@ const PeerResolveResult = union(enum) {
33296 break :msg msg;33298 break :msg msg;
33297 };33299 };
3329833300
33299 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(pt)});33301 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)});33302 if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[1].fmt(pt)});
3330133303
33302 // No child error33304 // No child error
33303 break;33305 break;
...@@ -34609,7 +34611,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34609,7 +34611,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34609 if (struct_type.setLayoutWip(ip)) {34611 if (struct_type.setLayoutWip(ip)) {
34610 const msg = try sema.errMsg(34612 const msg = try sema.errMsg(
34611 ty.srcLoc(zcu),34613 ty.srcLoc(zcu),
34612 "struct '{}' depends on itself",34614 "struct '{f}' depends on itself",
34613 .{ty.fmt(pt)},34615 .{ty.fmt(pt)},
34614 );34616 );
34615 return sema.failWithOwnedErrorMsg(null, msg);34617 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -34828,13 +34830,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_...@@ -34828,13 +34830,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_
34828 const zcu = pt.zcu;34830 const zcu = pt.zcu;
3482934831
34830 if (!backing_int_ty.isInt(zcu)) {34832 if (!backing_int_ty.isInt(zcu)) {
34831 return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(pt)});34833 return sema.fail(block, src, "expected backing integer type, found '{f}'", .{backing_int_ty.fmt(pt)});
34832 }34834 }
34833 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {34835 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {
34834 return sema.fail(34836 return sema.fail(
34835 block,34837 block,
34836 src,34838 src,
34837 "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}",34839 "backing integer type '{f}' has bit size {d} but the struct fields have a total bit size of {d}",
34838 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },34840 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },
34839 );34841 );
34840 }34842 }
...@@ -34844,7 +34846,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -34844,7 +34846,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
34844 const pt = sema.pt;34846 const pt = sema.pt;
34845 if (!ty.isIndexable(pt.zcu)) {34847 if (!ty.isIndexable(pt.zcu)) {
34846 const msg = msg: {34848 const msg = msg: {
34847 const msg = try sema.errMsg(src, "type '{}' does not support indexing", .{ty.fmt(pt)});34849 const msg = try sema.errMsg(src, "type '{f}' does not support indexing", .{ty.fmt(pt)});
34848 errdefer msg.destroy(sema.gpa);34850 errdefer msg.destroy(sema.gpa);
34849 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});34851 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});
34850 break :msg msg;34852 break :msg msg;
...@@ -34868,7 +34870,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void...@@ -34868,7 +34870,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
34868 }34870 }
34869 }34871 }
34870 const msg = msg: {34872 const msg = msg: {
34871 const msg = try sema.errMsg(src, "type '{}' is not an indexable pointer", .{ty.fmt(pt)});34873 const msg = try sema.errMsg(src, "type '{f}' is not an indexable pointer", .{ty.fmt(pt)});
34872 errdefer msg.destroy(sema.gpa);34874 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", .{});34875 try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});
34874 break :msg msg;34876 break :msg msg;
...@@ -34936,7 +34938,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34936,7 +34938,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
34936 .field_types_wip, .layout_wip => {34938 .field_types_wip, .layout_wip => {
34937 const msg = try sema.errMsg(34939 const msg = try sema.errMsg(
34938 ty.srcLoc(pt.zcu),34940 ty.srcLoc(pt.zcu),
34939 "union '{}' depends on itself",34941 "union '{f}' depends on itself",
34940 .{ty.fmt(pt)},34942 .{ty.fmt(pt)},
34941 );34943 );
34942 return sema.failWithOwnedErrorMsg(null, msg);34944 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35124,7 +35126,7 @@ pub fn resolveStructFieldTypes(...@@ -35124,7 +35126,7 @@ pub fn resolveStructFieldTypes(
35124 if (struct_type.setFieldTypesWip(ip)) {35126 if (struct_type.setFieldTypesWip(ip)) {
35125 const msg = try sema.errMsg(35127 const msg = try sema.errMsg(
35126 Type.fromInterned(ty).srcLoc(zcu),35128 Type.fromInterned(ty).srcLoc(zcu),
35127 "struct '{}' depends on itself",35129 "struct '{f}' depends on itself",
35128 .{Type.fromInterned(ty).fmt(pt)},35130 .{Type.fromInterned(ty).fmt(pt)},
35129 );35131 );
35130 return sema.failWithOwnedErrorMsg(null, msg);35132 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35153,7 +35155,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -35153,7 +35155,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
35153 if (struct_type.setInitsWip(ip)) {35155 if (struct_type.setInitsWip(ip)) {
35154 const msg = try sema.errMsg(35156 const msg = try sema.errMsg(
35155 ty.srcLoc(zcu),35157 ty.srcLoc(zcu),
35156 "struct '{}' depends on itself",35158 "struct '{f}' depends on itself",
35157 .{ty.fmt(pt)},35159 .{ty.fmt(pt)},
35158 );35160 );
35159 return sema.failWithOwnedErrorMsg(null, msg);35161 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35177,11 +35179,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -35177,11 +35179,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
35177 switch (union_type.flagsUnordered(ip).status) {35179 switch (union_type.flagsUnordered(ip).status) {
35178 .none => {},35180 .none => {},
35179 .field_types_wip => {35181 .field_types_wip => {
35180 const msg = try sema.errMsg(35182 const msg = try sema.errMsg(ty.srcLoc(zcu), "union '{f}' depends on itself", .{ty.fmt(pt)});
35181 ty.srcLoc(zcu),
35182 "union '{}' depends on itself",
35183 .{ty.fmt(pt)},
35184 );
35185 return sema.failWithOwnedErrorMsg(null, msg);35183 return sema.failWithOwnedErrorMsg(null, msg);
35186 },35184 },
35187 .have_field_types,35185 .have_field_types,
...@@ -35549,7 +35547,7 @@ fn structFields(...@@ -35549,7 +35547,7 @@ fn structFields(
35549 switch (struct_type.layout) {35547 switch (struct_type.layout) {
35550 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {35548 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
35551 const msg = msg: {35549 const msg = msg: {
35552 const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});35550 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);35551 errdefer msg.destroy(sema.gpa);
3555435552
35555 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);35553 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);
...@@ -35561,7 +35559,7 @@ fn structFields(...@@ -35561,7 +35559,7 @@ fn structFields(
35561 },35559 },
35562 .@"packed" => if (!try sema.validatePackedType(field_ty)) {35560 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
35563 const msg = msg: {35561 const msg = msg: {
35564 const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});35562 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);35563 errdefer msg.destroy(sema.gpa);
3556635564
35567 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);35565 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
...@@ -35808,7 +35806,7 @@ fn unionFields(...@@ -35808,7 +35806,7 @@ fn unionFields(
35808 // The provided type is an integer type and we must construct the enum tag type here.35806 // The provided type is an integer type and we must construct the enum tag type here.
35809 int_tag_ty = provided_ty;35807 int_tag_ty = provided_ty;
35810 if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) {35808 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)});35809 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{f}'", .{int_tag_ty.fmt(pt)});
35812 }35810 }
3581335811
35814 if (fields_len > 0) {35812 if (fields_len > 0) {
...@@ -35817,7 +35815,7 @@ fn unionFields(...@@ -35817,7 +35815,7 @@ fn unionFields(
35817 const msg = msg: {35815 const msg = msg: {
35818 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});35816 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});
35819 errdefer msg.destroy(sema.gpa);35817 errdefer msg.destroy(sema.gpa);
35820 try sema.errNote(tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{35818 try sema.errNote(tag_ty_src, msg, "type '{f}' cannot fit values in range 0...{d}", .{
35821 int_tag_ty.fmt(pt),35819 int_tag_ty.fmt(pt),
35822 fields_len - 1,35820 fields_len - 1,
35823 });35821 });
...@@ -35832,7 +35830,7 @@ fn unionFields(...@@ -35832,7 +35830,7 @@ fn unionFields(
35832 // The provided type is the enum tag type.35830 // The provided type is the enum tag type.
35833 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {35831 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
35834 .enum_type => ip.loadEnumType(provided_ty.toIntern()),35832 .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)}),35833 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}),
35836 };35834 };
35837 union_type.setTagType(ip, provided_ty.toIntern());35835 union_type.setTagType(ip, provided_ty.toIntern());
35838 // The fields of the union must match the enum exactly.35836 // The fields of the union must match the enum exactly.
...@@ -35929,7 +35927,7 @@ fn unionFields(...@@ -35929,7 +35927,7 @@ fn unionFields(
35929 if (result.overflow) return sema.fail(35927 if (result.overflow) return sema.fail(
35930 &block_scope,35928 &block_scope,
35931 value_src,35929 value_src,
35932 "enumeration value '{}' too large for type '{}'",35930 "enumeration value '{f}' too large for type '{f}'",
35933 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },35931 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
35934 );35932 );
35935 last_tag_val = result.val;35933 last_tag_val = result.val;
...@@ -35947,7 +35945,7 @@ fn unionFields(...@@ -35947,7 +35945,7 @@ fn unionFields(
35947 const msg = msg: {35945 const msg = msg: {
35948 const msg = try sema.errMsg(35946 const msg = try sema.errMsg(
35949 value_src,35947 value_src,
35950 "enum tag value {} already taken",35948 "enum tag value {f} already taken",
35951 .{enum_tag_val.fmtValueSema(pt, sema)},35949 .{enum_tag_val.fmtValueSema(pt, sema)},
35952 );35950 );
35953 errdefer msg.destroy(gpa);35951 errdefer msg.destroy(gpa);
...@@ -35975,7 +35973,7 @@ fn unionFields(...@@ -35975,7 +35973,7 @@ fn unionFields(
35975 const tag_ty = union_type.tagTypeUnordered(ip);35973 const tag_ty = union_type.tagTypeUnordered(ip);
35976 const tag_info = ip.loadEnumType(tag_ty);35974 const tag_info = ip.loadEnumType(tag_ty);
35977 const enum_index = tag_info.nameIndex(ip, field_name) orelse {35975 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
35978 return sema.fail(&block_scope, name_src, "no field named '{}' in enum '{}'", .{35976 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),35977 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),
35980 });35978 });
35981 };35979 };
...@@ -35992,7 +35990,7 @@ fn unionFields(...@@ -35992,7 +35990,7 @@ fn unionFields(
35992 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,35990 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,
35993 .offset = .{ .container_field_name = enum_index },35991 .offset = .{ .container_field_name = enum_index },
35994 };35992 };
35995 const msg = try sema.errMsg(name_src, "union field '{}' ordered differently than corresponding enum field", .{35993 const msg = try sema.errMsg(name_src, "union field '{f}' ordered differently than corresponding enum field", .{
35996 field_name.fmt(ip),35994 field_name.fmt(ip),
35997 });35995 });
35998 errdefer msg.destroy(sema.gpa);35996 errdefer msg.destroy(sema.gpa);
...@@ -36018,7 +36016,7 @@ fn unionFields(...@@ -36018,7 +36016,7 @@ fn unionFields(
36018 !try sema.validateExternType(field_ty, .union_field))36016 !try sema.validateExternType(field_ty, .union_field))
36019 {36017 {
36020 const msg = msg: {36018 const msg = msg: {
36021 const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});36019 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);36020 errdefer msg.destroy(sema.gpa);
3602336021
36024 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);36022 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);
...@@ -36029,7 +36027,7 @@ fn unionFields(...@@ -36029,7 +36027,7 @@ fn unionFields(
36029 return sema.failWithOwnedErrorMsg(&block_scope, msg);36027 return sema.failWithOwnedErrorMsg(&block_scope, msg);
36030 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {36028 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
36031 const msg = msg: {36029 const msg = msg: {
36032 const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});36030 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);36031 errdefer msg.destroy(sema.gpa);
3603436032
36035 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);36033 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);
...@@ -36065,7 +36063,7 @@ fn unionFields(...@@ -36065,7 +36063,7 @@ fn unionFields(
3606536063
36066 for (tag_info.names.get(ip), 0..) |field_name, field_index| {36064 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
36067 if (explicit_tags_seen[field_index]) continue;36065 if (explicit_tags_seen[field_index]) continue;
36068 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{}' missing, declared here", .{36066 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{f}' missing, declared here", .{
36069 field_name.fmt(ip),36067 field_name.fmt(ip),
36070 });36068 });
36071 }36069 }
...@@ -36101,7 +36099,7 @@ fn generateUnionTagTypeNumbered(...@@ -36101,7 +36099,7 @@ fn generateUnionTagTypeNumbered(
36101 const name = try ip.getOrPutStringFmt(36099 const name = try ip.getOrPutStringFmt(
36102 gpa,36100 gpa,
36103 pt.tid,36101 pt.tid,
36104 "@typeInfo({}).@\"union\".tag_type.?",36102 "@typeInfo({f}).@\"union\".tag_type.?",
36105 .{union_name.fmt(ip)},36103 .{union_name.fmt(ip)},
36106 .no_embedded_nulls,36104 .no_embedded_nulls,
36107 );36105 );
...@@ -36137,7 +36135,7 @@ fn generateUnionTagTypeSimple(...@@ -36137,7 +36135,7 @@ fn generateUnionTagTypeSimple(
36137 const name = try ip.getOrPutStringFmt(36135 const name = try ip.getOrPutStringFmt(
36138 gpa,36136 gpa,
36139 pt.tid,36137 pt.tid,
36140 "@typeInfo({}).@\"union\".tag_type.?",36138 "@typeInfo({f}).@\"union\".tag_type.?",
36141 .{union_name.fmt(ip)},36139 .{union_name.fmt(ip)},
36142 .no_embedded_nulls,36140 .no_embedded_nulls,
36143 );36141 );
...@@ -36671,13 +36669,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr...@@ -36671,13 +36669,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
36671 .needed_well_defined => |ty| return sema.fail(36669 .needed_well_defined => |ty| return sema.fail(
36672 block,36670 block,
36673 src,36671 src,
36674 "comptime dereference requires '{}' to have a well-defined layout",36672 "comptime dereference requires '{f}' to have a well-defined layout",
36675 .{ty.fmt(pt)},36673 .{ty.fmt(pt)},
36676 ),36674 ),
36677 .out_of_bounds => |ty| return sema.fail(36675 .out_of_bounds => |ty| return sema.fail(
36678 block,36676 block,
36679 src,36677 src,
36680 "dereference of '{}' exceeds bounds of containing decl of type '{}'",36678 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
36681 .{ ptr_ty.fmt(pt), ty.fmt(pt) },36679 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
36682 ),36680 ),
36683 }36681 }
...@@ -36697,7 +36695,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -36697,7 +36695,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
36697 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },36695 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },
36698 .runtime_load => return .runtime_load,36696 .runtime_load => return .runtime_load,
36699 .undef => return sema.failWithUseOfUndef(block, src),36697 .undef => return sema.failWithUseOfUndef(block, src),
36700 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {}", .{err_name.fmt(ip)}),36698 .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", .{}),36699 .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", .{}),36700 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
36703 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },36701 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },
...@@ -36822,12 +36820,12 @@ fn intFromFloatScalar(...@@ -36822,12 +36820,12 @@ fn intFromFloatScalar(
3682236820
36823 const float = val.toFloat(f128, zcu);36821 const float = val.toFloat(f128, zcu);
36824 if (std.math.isNan(float)) {36822 if (std.math.isNan(float)) {
36825 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{36823 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{f}'", .{
36826 int_ty.fmt(pt),36824 int_ty.fmt(pt),
36827 });36825 });
36828 }36826 }
36829 if (std.math.isInf(float)) {36827 if (std.math.isInf(float)) {
36830 return sema.fail(block, src, "float value Inf cannot be stored in integer type '{}'", .{36828 return sema.fail(block, src, "float value Inf cannot be stored in integer type '{f}'", .{
36831 int_ty.fmt(pt),36829 int_ty.fmt(pt),
36832 });36830 });
36833 }36831 }
...@@ -36842,7 +36840,7 @@ fn intFromFloatScalar(...@@ -36842,7 +36840,7 @@ fn intFromFloatScalar(
36842 .exact => return sema.fail(36840 .exact => return sema.fail(
36843 block,36841 block,
36844 src,36842 src,
36845 "fractional component prevents float value '{}' from coercion to type '{}'",36843 "fractional component prevents float value '{f}' from coercion to type '{f}'",
36846 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },36844 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },
36847 ),36845 ),
36848 .truncate => {},36846 .truncate => {},
...@@ -36854,7 +36852,7 @@ fn intFromFloatScalar(...@@ -36854,7 +36852,7 @@ fn intFromFloatScalar(
3685436852
36855 const int_info = int_ty.intInfo(zcu);36853 const int_info = int_ty.intInfo(zcu);
36856 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {36854 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 '{}'", .{36855 return sema.fail(block, src, "float value '{f}' cannot be stored in integer type '{f}'", .{
36858 val.fmtValueSema(pt, sema), int_ty.fmt(pt),36856 val.fmtValueSema(pt, sema), int_ty.fmt(pt),
36859 });36857 });
36860 }36858 }
...@@ -37175,7 +37173,14 @@ fn explainWhyValueContainsReferenceToComptimeVar(sema: *Sema, msg: *Zcu.ErrorMsg...@@ -37175,7 +37173,14 @@ fn explainWhyValueContainsReferenceToComptimeVar(sema: *Sema, msg: *Zcu.ErrorMsg
37175 }37173 }
37176}37174}
3717737175
37178fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc, val: Value, intermediate_value_count: u32, start_value_name: InternPool.NullTerminatedString) Allocator.Error!union(enum) {37176fn notePathToComptimeAllocPtr(
37177 sema: *Sema,
37178 msg: *Zcu.ErrorMsg,
37179 src: LazySrcLoc,
37180 val: Value,
37181 intermediate_value_count: u32,
37182 start_value_name: InternPool.NullTerminatedString,
37183) Allocator.Error!union(enum) {
37179 done,37184 done,
37180 new_val: Value,37185 new_val: Value,
37181} {37186} {
...@@ -37186,9 +37191,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37186,9 +37191,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3718637191
37187 var first_path: std.ArrayListUnmanaged(u8) = .empty;37192 var first_path: std.ArrayListUnmanaged(u8) = .empty;
37188 if (intermediate_value_count == 0) {37193 if (intermediate_value_count == 0) {
37189 try first_path.writer(arena).print("{i}", .{start_value_name.fmt(ip)});37194 try first_path.print(arena, "{f}", .{start_value_name.fmt(ip)});
37190 } else {37195 } else {
37191 try first_path.writer(arena).print("v{}", .{intermediate_value_count - 1});37196 try first_path.print(arena, "v{d}", .{intermediate_value_count - 1});
37192 }37197 }
3719337198
37194 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);37199 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);
...@@ -37213,30 +37218,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37213,30 +37218,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
37213 error.AnalysisFail => unreachable,37218 error.AnalysisFail => unreachable,
37214 };37219 };
3721537220
37216 var second_path: std.ArrayListUnmanaged(u8) = .empty;37221 var second_path_aw: std.io.Writer.Allocating = .init(arena);
37222 defer second_path_aw.deinit();
37217 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});37223 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});
37218 const deriv_start = @import("print_value.zig").printPtrDerivation(37224 const deriv_start = @import("print_value.zig").printPtrDerivation(
37219 derivation,37225 derivation,
37220 second_path.writer(arena),37226 &second_path_aw.writer,
37221 pt,37227 pt,
37222 .lvalue,37228 .lvalue,
37223 .{ .str = inter_name },37229 .{ .str = inter_name },
37224 20,37230 20,
37225 ) catch |err| switch (err) {37231 ) catch return error.OutOfMemory;
37226 error.OutOfMemory => |e| return e,
37227 error.AnalysisFail => unreachable,
37228 error.ComptimeReturn => unreachable,
37229 error.ComptimeBreak => unreachable,
37230 };
3723137232
37232 switch (deriv_start) {37233 switch (deriv_start) {
37233 .int, .nav_ptr => unreachable,37234 .int, .nav_ptr => unreachable,
37234 .uav_ptr => |uav| {37235 .uav_ptr => |uav| {
37235 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });37236 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
37236 return .{ .new_val = .fromInterned(uav.val) };37237 return .{ .new_val = .fromInterned(uav.val) };
37237 },37238 },
37238 .comptime_alloc_ptr => |cta_info| {37239 .comptime_alloc_ptr => |cta_info| {
37239 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });37240 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);37241 const cta = sema.getComptimeAlloc(cta_info.idx);
37241 if (cta.is_const) {37242 if (cta.is_const) {
37242 return .{ .new_val = cta_info.val };37243 return .{ .new_val = cta_info.val };
...@@ -37246,7 +37247,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37246,7 +37247,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
37246 }37247 }
37247 },37248 },
37248 .comptime_field_ptr => {37249 .comptime_field_ptr => {
37249 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });37250 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});37251 try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name});
37251 return .done;37252 return .done;
37252 },37253 },
...@@ -37286,7 +37287,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList...@@ -37286,7 +37287,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
37286 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);37287 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);
37287 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;37288 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;
37288 const field_name = backing_enum.enumFieldName(field_idx, zcu);37289 const field_name = backing_enum.enumFieldName(field_idx, zcu);
37289 try path.writer(arena).print(".{i}", .{field_name.fmt(ip)});37290 try path.print(arena, ".{f}", .{field_name.fmt(ip)});
37290 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);37291 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);
37291 },37292 },
37292 .aggregate => |agg| {37293 .aggregate => |agg| {
...@@ -37301,17 +37302,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList...@@ -37301,17 +37302,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
37301 };37302 };
37302 const agg_ty: Type = .fromInterned(agg.ty);37303 const agg_ty: Type = .fromInterned(agg.ty);
37303 switch (agg_ty.zigTypeTag(zcu)) {37304 switch (agg_ty.zigTypeTag(zcu)) {
37304 .array, .vector => try path.writer(arena).print("[{d}]", .{elem_idx}),37305 .array, .vector => try path.print(arena, "[{d}]", .{elem_idx}),
37305 .pointer => switch (elem_idx) {37306 .pointer => switch (elem_idx) {
37306 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),37307 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),
37307 Value.slice_len_index => try path.appendSlice(arena, ".len"),37308 Value.slice_len_index => try path.appendSlice(arena, ".len"),
37308 else => unreachable,37309 else => unreachable,
37309 },37310 },
37310 .@"struct" => if (agg_ty.isTuple(zcu)) {37311 .@"struct" => if (agg_ty.isTuple(zcu)) {
37311 try path.writer(arena).print("[{d}]", .{elem_idx});37312 try path.print(arena, "[{d}]", .{elem_idx});
37312 } else {37313 } else {
37313 const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;37314 const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;
37314 try path.writer(arena).print(".{i}", .{name.fmt(ip)});37315 try path.print(arena, ".{f}", .{name.fmt(ip)});
37315 },37316 },
37316 else => unreachable,37317 else => unreachable,
37317 }37318 }
...@@ -37588,7 +37589,7 @@ fn resolveDeclaredEnumInner(...@@ -37588,7 +37589,7 @@ fn resolveDeclaredEnumInner(
37588 if (tag_type_ref != .none) {37589 if (tag_type_ref != .none) {
37589 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);37590 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
37590 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {37591 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)});37592 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{f}'", .{ty.fmt(pt)});
37592 }37593 }
37593 break :ty ty;37594 break :ty ty;
37594 } else if (fields_len == 0) {37595 } else if (fields_len == 0) {
...@@ -37642,7 +37643,7 @@ fn resolveDeclaredEnumInner(...@@ -37642,7 +37643,7 @@ fn resolveDeclaredEnumInner(
37642 .offset = .{ .container_field_value = conflict.prev_field_idx },37643 .offset = .{ .container_field_value = conflict.prev_field_idx },
37643 };37644 };
37644 const msg = msg: {37645 const msg = msg: {
37645 const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});37646 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37646 errdefer msg.destroy(gpa);37647 errdefer msg.destroy(gpa);
37647 try sema.errNote(other_field_src, msg, "other occurrence here", .{});37648 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37648 break :msg msg;37649 break :msg msg;
...@@ -37665,7 +37666,7 @@ fn resolveDeclaredEnumInner(...@@ -37665,7 +37666,7 @@ fn resolveDeclaredEnumInner(
37665 .offset = .{ .container_field_value = conflict.prev_field_idx },37666 .offset = .{ .container_field_value = conflict.prev_field_idx },
37666 };37667 };
37667 const msg = msg: {37668 const msg = msg: {
37668 const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});37669 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37669 errdefer msg.destroy(gpa);37670 errdefer msg.destroy(gpa);
37670 try sema.errNote(other_field_src, msg, "other occurrence here", .{});37671 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37671 break :msg msg;37672 break :msg msg;
...@@ -37682,7 +37683,7 @@ fn resolveDeclaredEnumInner(...@@ -37682,7 +37683,7 @@ fn resolveDeclaredEnumInner(
37682 };37683 };
3768337684
37684 if (tag_overflow) {37685 if (tag_overflow) {
37685 const msg = try sema.errMsg(value_src, "enumeration value '{}' too large for type '{}'", .{37686 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),37687 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),
37687 });37688 });
37688 return sema.failWithOwnedErrorMsg(block, msg);37689 return sema.failWithOwnedErrorMsg(block, msg);
src/Sema/LowerZon.zig+17-21
...@@ -338,7 +338,7 @@ fn failUnsupportedResultType(...@@ -338,7 +338,7 @@ fn failUnsupportedResultType(
338 const gpa = sema.gpa;338 const gpa = sema.gpa;
339 const pt = sema.pt;339 const pt = sema.pt;
340 return sema.failWithOwnedErrorMsg(self.block, msg: {340 return sema.failWithOwnedErrorMsg(self.block, msg: {
341 const msg = try sema.errMsg(self.import_loc, "type '{}' is not available in ZON", .{ty.fmt(pt)});341 const msg = try sema.errMsg(self.import_loc, "type '{f}' is not available in ZON", .{ty.fmt(pt)});
342 errdefer msg.destroy(gpa);342 errdefer msg.destroy(gpa);
343 if (opt_note) |n| try sema.errNote(self.import_loc, msg, "{s}", .{n});343 if (opt_note) |n| try sema.errNote(self.import_loc, msg, "{s}", .{n});
344 break :msg msg;344 break :msg msg;
...@@ -360,11 +360,7 @@ fn fail(...@@ -360,11 +360,7 @@ fn fail(
360fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index {360fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index {
361 const pt = self.sema.pt;361 const pt = self.sema.pt;
362 return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) {362 return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) {
363 error.WrongType => return self.fail(363 error.WrongType => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(pt)}),
364 node,
365 "expected type '{}'",
366 .{res_ty.fmt(pt)},
367 ),
368 else => |e| return e,364 else => |e| return e,
369 };365 };
370}366}
...@@ -428,7 +424,7 @@ fn lowerExprKnownResTyInner(...@@ -428,7 +424,7 @@ fn lowerExprKnownResTyInner(
428 .frame,424 .frame,
429 .@"anyframe",425 .@"anyframe",
430 .void,426 .void,
431 => return self.fail(node, "type '{}' not available in ZON", .{res_ty.fmt(pt)}),427 => return self.fail(node, "type '{f}' not available in ZON", .{res_ty.fmt(pt)}),
432 }428 }
433}429}
434430
...@@ -458,7 +454,7 @@ fn lowerInt(...@@ -458,7 +454,7 @@ fn lowerInt(
458 // If lhs is unsigned and rhs is less than 0, we're out of bounds454 // If lhs is unsigned and rhs is less than 0, we're out of bounds
459 if (lhs_info.signedness == .unsigned and rhs < 0) return self.fail(455 if (lhs_info.signedness == .unsigned and rhs < 0) return self.fail(
460 node,456 node,
461 "type '{}' cannot represent integer value '{}'",457 "type '{f}' cannot represent integer value '{d}'",
462 .{ res_ty.fmt(self.sema.pt), rhs },458 .{ res_ty.fmt(self.sema.pt), rhs },
463 );459 );
464460
...@@ -478,7 +474,7 @@ fn lowerInt(...@@ -478,7 +474,7 @@ fn lowerInt(
478 if (rhs < min_int or rhs > max_int) {474 if (rhs < min_int or rhs > max_int) {
479 return self.fail(475 return self.fail(
480 node,476 node,
481 "type '{}' cannot represent integer value '{}'",477 "type '{f}' cannot represent integer value '{d}'",
482 .{ res_ty.fmt(self.sema.pt), rhs },478 .{ res_ty.fmt(self.sema.pt), rhs },
483 );479 );
484 }480 }
...@@ -496,7 +492,7 @@ fn lowerInt(...@@ -496,7 +492,7 @@ fn lowerInt(
496 if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) {492 if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) {
497 return self.fail(493 return self.fail(
498 node,494 node,
499 "type '{}' cannot represent integer value '{}'",495 "type '{f}' cannot represent integer value '{d}'",
500 .{ res_ty.fmt(self.sema.pt), val },496 .{ res_ty.fmt(self.sema.pt), val },
501 );497 );
502 }498 }
...@@ -517,7 +513,7 @@ fn lowerInt(...@@ -517,7 +513,7 @@ fn lowerInt(
517 switch (big_int.setFloat(val, .trunc)) {513 switch (big_int.setFloat(val, .trunc)) {
518 .inexact => return self.fail(514 .inexact => return self.fail(
519 node,515 node,
520 "fractional component prevents float value '{}' from coercion to type '{}'",516 "fractional component prevents float value '{d}' from coercion to type '{f}'",
521 .{ val, res_ty.fmt(self.sema.pt) },517 .{ val, res_ty.fmt(self.sema.pt) },
522 ),518 ),
523 .exact => {},519 .exact => {},
...@@ -528,8 +524,8 @@ fn lowerInt(...@@ -528,8 +524,8 @@ fn lowerInt(
528 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {524 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {
529 return self.fail(525 return self.fail(
530 node,526 node,
531 "type '{}' cannot represent integer value '{}'",527 "type '{f}' cannot represent integer value '{d}'",
532 .{ val, res_ty.fmt(self.sema.pt) },528 .{ res_ty.fmt(self.sema.pt), val },
533 );529 );
534 }530 }
535531
...@@ -550,7 +546,7 @@ fn lowerInt(...@@ -550,7 +546,7 @@ fn lowerInt(
550 if (val >= out_of_range) {546 if (val >= out_of_range) {
551 return self.fail(547 return self.fail(
552 node,548 node,
553 "type '{}' cannot represent integer value '{}'",549 "type '{f}' cannot represent integer value '{d}'",
554 .{ res_ty.fmt(self.sema.pt), val },550 .{ res_ty.fmt(self.sema.pt), val },
555 );551 );
556 }552 }
...@@ -584,7 +580,7 @@ fn lowerFloat(...@@ -584,7 +580,7 @@ fn lowerFloat(
584 .pos_inf => b: {580 .pos_inf => b: {
585 if (res_ty.toIntern() == .comptime_float_type) return self.fail(581 if (res_ty.toIntern() == .comptime_float_type) return self.fail(
586 node,582 node,
587 "expected type '{}'",583 "expected type '{f}'",
588 .{res_ty.fmt(self.sema.pt)},584 .{res_ty.fmt(self.sema.pt)},
589 );585 );
590 break :b try self.sema.pt.floatValue(res_ty, std.math.inf(f128));586 break :b try self.sema.pt.floatValue(res_ty, std.math.inf(f128));
...@@ -592,7 +588,7 @@ fn lowerFloat(...@@ -592,7 +588,7 @@ fn lowerFloat(
592 .neg_inf => b: {588 .neg_inf => b: {
593 if (res_ty.toIntern() == .comptime_float_type) return self.fail(589 if (res_ty.toIntern() == .comptime_float_type) return self.fail(
594 node,590 node,
595 "expected type '{}'",591 "expected type '{f}'",
596 .{res_ty.fmt(self.sema.pt)},592 .{res_ty.fmt(self.sema.pt)},
597 );593 );
598 break :b try self.sema.pt.floatValue(res_ty, -std.math.inf(f128));594 break :b try self.sema.pt.floatValue(res_ty, -std.math.inf(f128));
...@@ -600,7 +596,7 @@ fn lowerFloat(...@@ -600,7 +596,7 @@ fn lowerFloat(
600 .nan => b: {596 .nan => b: {
601 if (res_ty.toIntern() == .comptime_float_type) return self.fail(597 if (res_ty.toIntern() == .comptime_float_type) return self.fail(
602 node,598 node,
603 "expected type '{}'",599 "expected type '{f}'",
604 .{res_ty.fmt(self.sema.pt)},600 .{res_ty.fmt(self.sema.pt)},
605 );601 );
606 break :b try self.sema.pt.floatValue(res_ty, std.math.nan(f128));602 break :b try self.sema.pt.floatValue(res_ty, std.math.nan(f128));
...@@ -661,7 +657,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I...@@ -661,7 +657,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 {657 const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse {
662 return self.fail(658 return self.fail(
663 node,659 node,
664 "enum {} has no member named '{}'",660 "enum {f} has no member named '{f}'",
665 .{661 .{
666 res_ty.fmt(self.sema.pt),662 res_ty.fmt(self.sema.pt),
667 std.zig.fmtId(field_name.get(self.file.zoir.?)),663 std.zig.fmtId(field_name.get(self.file.zoir.?)),
...@@ -795,7 +791,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool...@@ -795,7 +791,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
795 const field_node = fields.vals.at(@intCast(i));791 const field_node = fields.vals.at(@intCast(i));
796792
797 const name_index = struct_info.nameIndex(ip, field_name) orelse {793 const name_index = struct_info.nameIndex(ip, field_name) orelse {
798 return self.fail(field_node, "unexpected field '{}'", .{field_name.fmt(ip)});794 return self.fail(field_node, "unexpected field '{f}'", .{field_name.fmt(ip)});
799 };795 };
800796
801 const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]);797 const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]);
...@@ -816,7 +812,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool...@@ -816,7 +812,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
816812
817 const field_names = struct_info.field_names.get(ip);813 const field_names = struct_info.field_names.get(ip);
818 for (field_values, field_names) |*value, name| {814 for (field_values, field_names) |*value, name| {
819 if (value.* == .none) return self.fail(node, "missing field '{}'", .{name.fmt(ip)});815 if (value.* == .none) return self.fail(node, "missing field '{f}'", .{name.fmt(ip)});
820 }816 }
821817
822 return self.sema.pt.intern(.{ .aggregate = .{818 return self.sema.pt.intern(.{ .aggregate = .{
...@@ -934,7 +930,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -934,7 +930,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
934 .struct_literal => b: {930 .struct_literal => b: {
935 const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {931 const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {
936 .struct_literal => |fields| fields,932 .struct_literal => |fields| fields,
937 else => return self.fail(node, "expected type '{}'", .{res_ty.fmt(self.sema.pt)}),933 else => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(self.sema.pt)}),
938 };934 };
939 if (fields.names.len != 1) {935 if (fields.names.len != 1) {
940 return error.WrongType;936 return error.WrongType;
src/Type.zig+23-37
...@@ -121,15 +121,13 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool {...@@ -121,15 +121,13 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool {
121 return a.toIntern() == b.toIntern();121 return a.toIntern() == b.toIntern();
122}122}
123123
124pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {124pub fn format(ty: Type, writer: *std.io.Writer) !void {
125 _ = ty;125 _ = ty;
126 _ = unused_fmt_string;
127 _ = options;
128 _ = writer;126 _ = writer;
129 @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");127 @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");
130}128}
131129
132pub const Formatter = std.fmt.Formatter(format2);130pub const Formatter = std.fmt.Formatter(Format, Format.default);
133131
134pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter {132pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter {
135 return .{ .data = .{133 return .{ .data = .{
...@@ -138,42 +136,28 @@ pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter {...@@ -138,42 +136,28 @@ pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter {
138 } };136 } };
139}137}
140138
141const FormatContext = struct {139const Format = struct {
142 ty: Type,140 ty: Type,
143 pt: Zcu.PerThread,141 pt: Zcu.PerThread,
144};
145142
146fn format2(143 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
147 ctx: FormatContext,144 return print(f.ty, writer, f.pt);
148 comptime unused_format_string: []const u8,145 }
149 options: std.fmt.FormatOptions,146};
150 writer: anytype,
151) !void {
152 comptime assert(unused_format_string.len == 0);
153 _ = options;
154 return print(ctx.ty, writer, ctx.pt);
155}
156147
157pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {148pub fn fmtDebug(ty: Type) std.fmt.Formatter(Type, dump) {
158 return .{ .data = ty };149 return .{ .data = ty };
159}150}
160151
161/// This is a debug function. In order to print types in a meaningful way152/// This is a debug function. In order to print types in a meaningful way
162/// we also need access to the module.153/// we also need access to the module.
163pub fn dump(154pub fn dump(start_type: Type, writer: *std.io.Writer) std.io.Writer.Error!void {
164 start_type: Type,
165 comptime unused_format_string: []const u8,
166 options: std.fmt.FormatOptions,
167 writer: anytype,
168) @TypeOf(writer).Error!void {
169 _ = options;
170 comptime assert(unused_format_string.len == 0);
171 return writer.print("{any}", .{start_type.ip_index});155 return writer.print("{any}", .{start_type.ip_index});
172}156}
173157
174/// Prints a name suitable for `@typeName`.158/// Prints a name suitable for `@typeName`.
175/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.159/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.
176pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error!void {160pub fn print(ty: Type, writer: *std.io.Writer, pt: Zcu.PerThread) std.io.Writer.Error!void {
177 const zcu = pt.zcu;161 const zcu = pt.zcu;
178 const ip = &zcu.intern_pool;162 const ip = &zcu.intern_pool;
179 switch (ip.indexToKey(ty.toIntern())) {163 switch (ip.indexToKey(ty.toIntern())) {
...@@ -190,8 +174,8 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -190,8 +174,8 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
190174
191 if (info.sentinel != .none) switch (info.flags.size) {175 if (info.sentinel != .none) switch (info.flags.size) {
192 .one, .c => unreachable,176 .one, .c => unreachable,
193 .many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),177 .many => try writer.print("[*:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),
194 .slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),178 .slice => try writer.print("[:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),
195 } else switch (info.flags.size) {179 } else switch (info.flags.size) {
196 .one => try writer.writeAll("*"),180 .one => try writer.writeAll("*"),
197 .many => try writer.writeAll("[*]"),181 .many => try writer.writeAll("[*]"),
...@@ -235,7 +219,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -235,7 +219,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
235 try writer.print("[{d}]", .{array_type.len});219 try writer.print("[{d}]", .{array_type.len});
236 try print(Type.fromInterned(array_type.child), writer, pt);220 try print(Type.fromInterned(array_type.child), writer, pt);
237 } else {221 } else {
238 try writer.print("[{d}:{}]", .{222 try writer.print("[{d}:{f}]", .{
239 array_type.len,223 array_type.len,
240 Value.fromInterned(array_type.sentinel).fmtValue(pt),224 Value.fromInterned(array_type.sentinel).fmtValue(pt),
241 });225 });
...@@ -265,7 +249,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -265,7 +249,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
265 },249 },
266 .inferred_error_set_type => |func_index| {250 .inferred_error_set_type => |func_index| {
267 const func_nav = ip.getNav(zcu.funcInfo(func_index).owner_nav);251 const func_nav = ip.getNav(zcu.funcInfo(func_index).owner_nav);
268 try writer.print("@typeInfo(@typeInfo(@TypeOf({})).@\"fn\".return_type.?).error_union.error_set", .{252 try writer.print("@typeInfo(@typeInfo(@TypeOf({f})).@\"fn\".return_type.?).error_union.error_set", .{
269 func_nav.fqn.fmt(ip),253 func_nav.fqn.fmt(ip),
270 });254 });
271 },255 },
...@@ -274,7 +258,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -274,7 +258,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
274 try writer.writeAll("error{");258 try writer.writeAll("error{");
275 for (names.get(ip), 0..) |name, i| {259 for (names.get(ip), 0..) |name, i| {
276 if (i != 0) try writer.writeByte(',');260 if (i != 0) try writer.writeByte(',');
277 try writer.print("{}", .{name.fmt(ip)});261 try writer.print("{f}", .{name.fmt(ip)});
278 }262 }
279 try writer.writeAll("}");263 try writer.writeAll("}");
280 },264 },
...@@ -317,7 +301,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -317,7 +301,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
317 },301 },
318 .struct_type => {302 .struct_type => {
319 const name = ip.loadStructType(ty.toIntern()).name;303 const name = ip.loadStructType(ty.toIntern()).name;
320 try writer.print("{}", .{name.fmt(ip)});304 try writer.print("{f}", .{name.fmt(ip)});
321 },305 },
322 .tuple_type => |tuple| {306 .tuple_type => |tuple| {
323 if (tuple.types.len == 0) {307 if (tuple.types.len == 0) {
...@@ -328,22 +312,22 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -328,22 +312,22 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
328 try writer.writeAll(if (i == 0) " " else ", ");312 try writer.writeAll(if (i == 0) " " else ", ");
329 if (val != .none) try writer.writeAll("comptime ");313 if (val != .none) try writer.writeAll("comptime ");
330 try print(Type.fromInterned(field_ty), writer, pt);314 try print(Type.fromInterned(field_ty), writer, pt);
331 if (val != .none) try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(pt)});315 if (val != .none) try writer.print(" = {f}", .{Value.fromInterned(val).fmtValue(pt)});
332 }316 }
333 try writer.writeAll(" }");317 try writer.writeAll(" }");
334 },318 },
335319
336 .union_type => {320 .union_type => {
337 const name = ip.loadUnionType(ty.toIntern()).name;321 const name = ip.loadUnionType(ty.toIntern()).name;
338 try writer.print("{}", .{name.fmt(ip)});322 try writer.print("{f}", .{name.fmt(ip)});
339 },323 },
340 .opaque_type => {324 .opaque_type => {
341 const name = ip.loadOpaqueType(ty.toIntern()).name;325 const name = ip.loadOpaqueType(ty.toIntern()).name;
342 try writer.print("{}", .{name.fmt(ip)});326 try writer.print("{f}", .{name.fmt(ip)});
343 },327 },
344 .enum_type => {328 .enum_type => {
345 const name = ip.loadEnumType(ty.toIntern()).name;329 const name = ip.loadEnumType(ty.toIntern()).name;
346 try writer.print("{}", .{name.fmt(ip)});330 try writer.print("{f}", .{name.fmt(ip)});
347 },331 },
348 .func_type => |fn_info| {332 .func_type => |fn_info| {
349 if (fn_info.is_noinline) {333 if (fn_info.is_noinline) {
...@@ -382,7 +366,9 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -382,7 +366,9 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
382 }366 }
383 }367 }
384 switch (fn_info.cc) {368 switch (fn_info.cc) {
385 .auto, .async, .naked, .@"inline" => try writer.print("callconv(.{}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),369 .auto, .async, .naked, .@"inline" => try writer.print("callconv(.{f}) ", .{
370 std.zig.fmtId(@tagName(fn_info.cc)),
371 }),
386 else => try writer.print("callconv({any}) ", .{fn_info.cc}),372 else => try writer.print("callconv({any}) ", .{fn_info.cc}),
387 }373 }
388 }374 }
src/Value.zig+7-15
...@@ -15,31 +15,23 @@ const Value = @This();...@@ -15,31 +15,23 @@ const Value = @This();
1515
16ip_index: InternPool.Index,16ip_index: InternPool.Index,
1717
18pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {18pub fn format(val: Value, writer: *std.io.Writer) !void {
19 _ = val;19 _ = val;
20 _ = fmt;
21 _ = options;
22 _ = writer;20 _ = writer;
23 @compileError("do not use format values directly; use either fmtDebug or fmtValue");21 @compileError("do not use format values directly; use either fmtDebug or fmtValue");
24}22}
2523
26/// This is a debug function. In order to print values in a meaningful way24/// This is a debug function. In order to print values in a meaningful way
27/// we also need access to the type.25/// we also need access to the type.
28pub fn dump(26pub fn dump(start_val: Value, w: std.io.Writer) std.io.Writer.Error!void {
29 start_val: Value,27 try w.print("(interned: {})", .{start_val.toIntern()});
30 comptime fmt: []const u8,
31 _: std.fmt.FormatOptions,
32 out_stream: anytype,
33) !void {
34 comptime assert(fmt.len == 0);
35 try out_stream.print("(interned: {})", .{start_val.toIntern()});
36}28}
3729
38pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) {30pub fn fmtDebug(val: Value) std.fmt.Formatter(Value, dump) {
39 return .{ .data = val };31 return .{ .data = val };
40}32}
4133
42pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.format) {34pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.FormatContext, print_value.format) {
43 return .{ .data = .{35 return .{ .data = .{
44 .val = val,36 .val = val,
45 .pt = pt,37 .pt = pt,
...@@ -48,7 +40,7 @@ pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.for...@@ -48,7 +40,7 @@ pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.for
48 } };40 } };
49}41}
5042
51pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatter(print_value.formatSema) {43pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatter(print_value.FormatContext, print_value.formatSema) {
52 return .{ .data = .{44 return .{ .data = .{
53 .val = val,45 .val = val,
54 .pt = pt,46 .pt = pt,
...@@ -57,7 +49,7 @@ pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatte...@@ -57,7 +49,7 @@ pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatte
57 } };49 } };
58}50}
5951
60pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Formatter(print_value.formatSema) {52pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Formatter(print_value.FormatContext, print_value.formatSema) {
61 return .{ .data = ctx };53 return .{ .data = ctx };
62}54}
6355
src/Zcu.zig+123-206
...@@ -15,6 +15,7 @@ const BigIntConst = std.math.big.int.Const;...@@ -15,6 +15,7 @@ const BigIntConst = std.math.big.int.Const;
15const BigIntMutable = std.math.big.int.Mutable;15const BigIntMutable = std.math.big.int.Mutable;
16const Target = std.Target;16const Target = std.Target;
17const Ast = std.zig.Ast;17const Ast = std.zig.Ast;
18const Writer = std.io.Writer;
1819
19const Zcu = @This();20const Zcu = @This();
20const Compilation = @import("Compilation.zig");21const Compilation = @import("Compilation.zig");
...@@ -858,7 +859,7 @@ pub const Namespace = struct {...@@ -858,7 +859,7 @@ pub const Namespace = struct {
858 try ns.fileScope(zcu).renderFullyQualifiedDebugName(writer);859 try ns.fileScope(zcu).renderFullyQualifiedDebugName(writer);
859 break :sep ':';860 break :sep ':';
860 };861 };
861 if (name != .empty) try writer.print("{c}{}", .{ sep, name.fmt(&zcu.intern_pool) });862 if (name != .empty) try writer.print("{c}{f}", .{ sep, name.fmt(&zcu.intern_pool) });
862 }863 }
863864
864 pub fn internFullyQualifiedName(865 pub fn internFullyQualifiedName(
...@@ -870,7 +871,7 @@ pub const Namespace = struct {...@@ -870,7 +871,7 @@ pub const Namespace = struct {
870 ) !InternPool.NullTerminatedString {871 ) !InternPool.NullTerminatedString {
871 const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip);872 const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip);
872 if (name == .empty) return ns_name;873 if (name == .empty) return ns_name;
873 return ip.getOrPutStringFmt(gpa, tid, "{}.{}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls);874 return ip.getOrPutStringFmt(gpa, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls);
874 }875 }
875};876};
876877
...@@ -1039,12 +1040,12 @@ pub const File = struct {...@@ -1039,12 +1040,12 @@ pub const File = struct {
1039 if (stat.size > std.math.maxInt(u32))1040 if (stat.size > std.math.maxInt(u32))
1040 return error.FileTooBig;1041 return error.FileTooBig;
10411042
1042 const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);1043 const source = try gpa.allocSentinel(u8, @intCast(stat.size), 0);
1043 errdefer gpa.free(source);1044 errdefer gpa.free(source);
10441045
1045 const amt = try f.readAll(source);1046 var file_reader = f.reader(&.{});
1046 if (amt != stat.size)1047 file_reader.size = stat.size;
1047 return error.UnexpectedEndOfFile;1048 try file_reader.interface.readSliceAll(source);
10481049
1049 // Here we do not modify stat fields because this function is the one1050 // Here we do not modify stat fields because this function is the one
1050 // used for error reporting. We need to keep the stat fields stale so that1051 // used for error reporting. We need to keep the stat fields stale so that
...@@ -1097,11 +1098,10 @@ pub const File = struct {...@@ -1097,11 +1098,10 @@ pub const File = struct {
1097 const gpa = pt.zcu.gpa;1098 const gpa = pt.zcu.gpa;
1098 const ip = &pt.zcu.intern_pool;1099 const ip = &pt.zcu.intern_pool;
1099 const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);1100 const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);
1100 const slice = try strings.addManyAsSlice(file.fullyQualifiedNameLen());1101 var w: Writer = .fixed((try strings.addManyAsSlice(file.fullyQualifiedNameLen()))[0]);
1101 var fbs = std.io.fixedBufferStream(slice[0]);1102 file.renderFullyQualifiedName(&w) catch unreachable;
1102 file.renderFullyQualifiedName(fbs.writer()) catch unreachable;1103 assert(w.end == w.buffer.len);
1103 assert(fbs.pos == slice[0].len);1104 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(w.end), .no_embedded_nulls);
1104 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(slice[0].len), .no_embedded_nulls);
1105 }1105 }
11061106
1107 pub const Index = InternPool.FileIndex;1107 pub const Index = InternPool.FileIndex;
...@@ -1112,7 +1112,7 @@ pub const File = struct {...@@ -1112,7 +1112,7 @@ pub const File = struct {
1112 eb: *std.zig.ErrorBundle.Wip,1112 eb: *std.zig.ErrorBundle.Wip,
1113 ) !std.zig.ErrorBundle.SourceLocationIndex {1113 ) !std.zig.ErrorBundle.SourceLocationIndex {
1114 return eb.addSourceLocation(.{1114 return eb.addSourceLocation(.{
1115 .src_path = try eb.printString("{}", .{file.path.fmt(zcu.comp)}),1115 .src_path = try eb.printString("{f}", .{file.path.fmt(zcu.comp)}),
1116 .span_start = 0,1116 .span_start = 0,
1117 .span_main = 0,1117 .span_main = 0,
1118 .span_end = 0,1118 .span_end = 0,
...@@ -1133,7 +1133,7 @@ pub const File = struct {...@@ -1133,7 +1133,7 @@ pub const File = struct {
1133 const end = start + tree.tokenSlice(tok).len;1133 const end = start + tree.tokenSlice(tok).len;
1134 const loc = std.zig.findLineColumn(source.bytes, start);1134 const loc = std.zig.findLineColumn(source.bytes, start);
1135 return eb.addSourceLocation(.{1135 return eb.addSourceLocation(.{
1136 .src_path = try eb.printString("{}", .{file.path.fmt(zcu.comp)}),1136 .src_path = try eb.printString("{f}", .{file.path.fmt(zcu.comp)}),
1137 .span_start = start,1137 .span_start = start,
1138 .span_main = start,1138 .span_main = start,
1139 .span_end = @intCast(end),1139 .span_end = @intCast(end),
...@@ -1190,13 +1190,8 @@ pub const ErrorMsg = struct {...@@ -1190,13 +1190,8 @@ pub const ErrorMsg = struct {
1190 gpa.destroy(err_msg);1190 gpa.destroy(err_msg);
1191 }1191 }
11921192
1193 pub fn init(1193 pub fn init(gpa: Allocator, src_loc: LazySrcLoc, comptime format: []const u8, args: anytype) !ErrorMsg {
1194 gpa: Allocator,1194 return .{
1195 src_loc: LazySrcLoc,
1196 comptime format: []const u8,
1197 args: anytype,
1198 ) !ErrorMsg {
1199 return ErrorMsg{
1200 .src_loc = src_loc,1195 .src_loc = src_loc,
1201 .msg = try std.fmt.allocPrint(gpa, format, args),1196 .msg = try std.fmt.allocPrint(gpa, format, args),
1202 };1197 };
...@@ -2811,10 +2806,18 @@ comptime {...@@ -2811,10 +2806,18 @@ comptime {
2811}2806}
28122807
2813pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {2808pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
2814 return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file);2809 var buffer: [2000]u8 = undefined;
2810 var file_reader = cache_file.reader(&buffer);
2811 return result: {
2812 const header = file_reader.interface.takeStruct(Zir.Header) catch |err| break :result err;
2813 break :result loadZirCacheBody(gpa, header.*, &file_reader.interface);
2814 } catch |err| switch (err) {
2815 error.ReadFailed => return file_reader.err.?,
2816 else => |e| return e,
2817 };
2815}2818}
28162819
2817pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {2820pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *std.io.Reader) !Zir {
2818 var instructions: std.MultiArrayList(Zir.Inst) = .{};2821 var instructions: std.MultiArrayList(Zir.Inst) = .{};
2819 errdefer instructions.deinit(gpa);2822 errdefer instructions.deinit(gpa);
28202823
...@@ -2837,34 +2840,16 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F...@@ -2837,34 +2840,16 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F
2837 undefined;2840 undefined;
2838 defer if (data_has_safety_tag) gpa.free(safety_buffer);2841 defer if (data_has_safety_tag) gpa.free(safety_buffer);
28392842
2840 const data_ptr = if (data_has_safety_tag)2843 var vecs = [_][]u8{
2841 @as([*]u8, @ptrCast(safety_buffer.ptr))2844 @ptrCast(zir.instructions.items(.tag)),
2842 else2845 if (data_has_safety_tag)
2843 @as([*]u8, @ptrCast(zir.instructions.items(.data).ptr));2846 @ptrCast(safety_buffer)
28442847 else
2845 var iovecs = [_]std.posix.iovec{2848 @ptrCast(zir.instructions.items(.data)),
2846 .{2849 zir.string_bytes,
2847 .base = @as([*]u8, @ptrCast(zir.instructions.items(.tag).ptr)),2850 @ptrCast(zir.extra),
2848 .len = header.instructions_len,
2849 },
2850 .{
2851 .base = data_ptr,
2852 .len = header.instructions_len * 8,
2853 },
2854 .{
2855 .base = zir.string_bytes.ptr,
2856 .len = header.string_bytes_len,
2857 },
2858 .{
2859 .base = @as([*]u8, @ptrCast(zir.extra.ptr)),
2860 .len = header.extra_len * 4,
2861 },
2862 };2851 };
2863 const amt_read = try cache_file.readvAll(&iovecs);2852 try cache_br.readVecAll(&vecs);
2864 const amt_expected = zir.instructions.len * 9 +
2865 zir.string_bytes.len +
2866 zir.extra.len * 4;
2867 if (amt_read != amt_expected) return error.UnexpectedFileSize;
2868 if (data_has_safety_tag) {2853 if (data_has_safety_tag) {
2869 const tags = zir.instructions.items(.tag);2854 const tags = zir.instructions.items(.tag);
2870 for (zir.instructions.items(.data), 0..) |*data, i| {2855 for (zir.instructions.items(.data), 0..) |*data, i| {
...@@ -2876,7 +2861,6 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F...@@ -2876,7 +2861,6 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F
2876 };2861 };
2877 }2862 }
2878 }2863 }
2879
2880 return zir;2864 return zir;
2881}2865}
28822866
...@@ -2887,14 +2871,6 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S...@@ -2887,14 +2871,6 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S
2887 undefined;2871 undefined;
2888 defer if (data_has_safety_tag) gpa.free(safety_buffer);2872 defer if (data_has_safety_tag) gpa.free(safety_buffer);
28892873
2890 const data_ptr: [*]const u8 = if (data_has_safety_tag)
2891 if (zir.instructions.len == 0)
2892 undefined
2893 else
2894 @ptrCast(safety_buffer.ptr)
2895 else
2896 @ptrCast(zir.instructions.items(.data).ptr);
2897
2898 if (data_has_safety_tag) {2874 if (data_has_safety_tag) {
2899 // The `Data` union has a safety tag but in the file format we store it without.2875 // The `Data` union has a safety tag but in the file format we store it without.
2900 for (zir.instructions.items(.data), 0..) |*data, i| {2876 for (zir.instructions.items(.data), 0..) |*data, i| {
...@@ -2912,29 +2888,20 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S...@@ -2912,29 +2888,20 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S
2912 .stat_inode = stat.inode,2888 .stat_inode = stat.inode,
2913 .stat_mtime = stat.mtime,2889 .stat_mtime = stat.mtime,
2914 };2890 };
2915 var iovecs: [5]std.posix.iovec_const = .{2891 var vecs = [_][]const u8{
2916 .{2892 @ptrCast((&header)[0..1]),
2917 .base = @ptrCast(&header),2893 @ptrCast(zir.instructions.items(.tag)),
2918 .len = @sizeOf(Zir.Header),2894 if (data_has_safety_tag)
2919 },2895 @ptrCast(safety_buffer)
2920 .{2896 else
2921 .base = @ptrCast(zir.instructions.items(.tag).ptr),2897 @ptrCast(zir.instructions.items(.data)),
2922 .len = zir.instructions.len,2898 zir.string_bytes,
2923 },2899 @ptrCast(zir.extra),
2924 .{2900 };
2925 .base = data_ptr,2901 var cache_fw = cache_file.writer(&.{});
2926 .len = zir.instructions.len * 8,2902 cache_fw.interface.writeVecAll(&vecs) catch |err| switch (err) {
2927 },2903 error.WriteFailed => return cache_fw.err.?,
2928 .{
2929 .base = zir.string_bytes.ptr,
2930 .len = zir.string_bytes.len,
2931 },
2932 .{
2933 .base = @ptrCast(zir.extra.ptr),
2934 .len = zir.extra.len * 4,
2935 },
2936 };2904 };
2937 try cache_file.writevAll(&iovecs);
2938}2905}
29392906
2940pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir) std.fs.File.WriteError!void {2907pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir) std.fs.File.WriteError!void {
...@@ -2950,48 +2917,24 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir...@@ -2950,48 +2917,24 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir
2950 .stat_inode = stat.inode,2917 .stat_inode = stat.inode,
2951 .stat_mtime = stat.mtime,2918 .stat_mtime = stat.mtime,
2952 };2919 };
2953 var iovecs: [9]std.posix.iovec_const = .{2920 var vecs = [_][]const u8{
2954 .{2921 @ptrCast((&header)[0..1]),
2955 .base = @ptrCast(&header),2922 @ptrCast(zoir.nodes.items(.tag)),
2956 .len = @sizeOf(Zoir.Header),2923 @ptrCast(zoir.nodes.items(.data)),
2957 },2924 @ptrCast(zoir.nodes.items(.ast_node)),
2958 .{2925 @ptrCast(zoir.extra),
2959 .base = @ptrCast(zoir.nodes.items(.tag)),2926 @ptrCast(zoir.limbs),
2960 .len = zoir.nodes.len * @sizeOf(Zoir.Node.Repr.Tag),2927 zoir.string_bytes,
2961 },2928 @ptrCast(zoir.compile_errors),
2962 .{2929 @ptrCast(zoir.error_notes),
2963 .base = @ptrCast(zoir.nodes.items(.data)),2930 };
2964 .len = zoir.nodes.len * 4,2931 var cache_fw = cache_file.writer(&.{});
2965 },2932 cache_fw.interface.writeVecAll(&vecs) catch |err| switch (err) {
2966 .{2933 error.WriteFailed => return cache_fw.err.?,
2967 .base = @ptrCast(zoir.nodes.items(.ast_node)),
2968 .len = zoir.nodes.len * 4,
2969 },
2970 .{
2971 .base = @ptrCast(zoir.extra),
2972 .len = zoir.extra.len * 4,
2973 },
2974 .{
2975 .base = @ptrCast(zoir.limbs),
2976 .len = zoir.limbs.len * @sizeOf(std.math.big.Limb),
2977 },
2978 .{
2979 .base = zoir.string_bytes.ptr,
2980 .len = zoir.string_bytes.len,
2981 },
2982 .{
2983 .base = @ptrCast(zoir.compile_errors),
2984 .len = zoir.compile_errors.len * @sizeOf(Zoir.CompileError),
2985 },
2986 .{
2987 .base = @ptrCast(zoir.error_notes),
2988 .len = zoir.error_notes.len * @sizeOf(Zoir.CompileError.Note),
2989 },
2990 };2934 };
2991 try cache_file.writevAll(&iovecs);
2992}2935}
29932936
2994pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs.File) !Zoir {2937pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_br: *std.io.Reader) !Zoir {
2995 var zoir: Zoir = .{2938 var zoir: Zoir = .{
2996 .nodes = .empty,2939 .nodes = .empty,
2997 .extra = &.{},2940 .extra = &.{},
...@@ -3017,49 +2960,17 @@ pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs...@@ -3017,49 +2960,17 @@ pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs
3017 zoir.compile_errors = try gpa.alloc(Zoir.CompileError, header.compile_errors_len);2960 zoir.compile_errors = try gpa.alloc(Zoir.CompileError, header.compile_errors_len);
3018 zoir.error_notes = try gpa.alloc(Zoir.CompileError.Note, header.error_notes_len);2961 zoir.error_notes = try gpa.alloc(Zoir.CompileError.Note, header.error_notes_len);
30192962
3020 var iovecs: [8]std.posix.iovec = .{2963 var vecs = [_][]u8{
3021 .{2964 @ptrCast(zoir.nodes.items(.tag)),
3022 .base = @ptrCast(zoir.nodes.items(.tag)),2965 @ptrCast(zoir.nodes.items(.data)),
3023 .len = header.nodes_len * @sizeOf(Zoir.Node.Repr.Tag),2966 @ptrCast(zoir.nodes.items(.ast_node)),
3024 },2967 @ptrCast(zoir.extra),
3025 .{2968 @ptrCast(zoir.limbs),
3026 .base = @ptrCast(zoir.nodes.items(.data)),2969 zoir.string_bytes,
3027 .len = header.nodes_len * 4,2970 @ptrCast(zoir.compile_errors),
3028 },2971 @ptrCast(zoir.error_notes),
3029 .{
3030 .base = @ptrCast(zoir.nodes.items(.ast_node)),
3031 .len = header.nodes_len * 4,
3032 },
3033 .{
3034 .base = @ptrCast(zoir.extra),
3035 .len = header.extra_len * 4,
3036 },
3037 .{
3038 .base = @ptrCast(zoir.limbs),
3039 .len = header.limbs_len * @sizeOf(std.math.big.Limb),
3040 },
3041 .{
3042 .base = zoir.string_bytes.ptr,
3043 .len = header.string_bytes_len,
3044 },
3045 .{
3046 .base = @ptrCast(zoir.compile_errors),
3047 .len = header.compile_errors_len * @sizeOf(Zoir.CompileError),
3048 },
3049 .{
3050 .base = @ptrCast(zoir.error_notes),
3051 .len = header.error_notes_len * @sizeOf(Zoir.CompileError.Note),
3052 },
3053 };
3054
3055 const bytes_expected = expected: {
3056 var n: usize = 0;
3057 for (iovecs) |v| n += v.len;
3058 break :expected n;
3059 };2972 };
30602973 try cache_br.readVecAll(&vecs);
3061 const bytes_read = try cache_file.readvAll(&iovecs);
3062 if (bytes_read != bytes_expected) return error.UnexpectedFileSize;
3063 return zoir;2974 return zoir;
3064}2975}
30652976
...@@ -3071,7 +2982,7 @@ pub fn markDependeeOutdated(...@@ -3071,7 +2982,7 @@ pub fn markDependeeOutdated(
3071 marked_po: enum { not_marked_po, marked_po },2982 marked_po: enum { not_marked_po, marked_po },
3072 dependee: InternPool.Dependee,2983 dependee: InternPool.Dependee,
3073) !void {2984) !void {
3074 log.debug("outdated dependee: {}", .{zcu.fmtDependee(dependee)});2985 log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
3075 var it = zcu.intern_pool.dependencyIterator(dependee);2986 var it = zcu.intern_pool.dependencyIterator(dependee);
3076 while (it.next()) |depender| {2987 while (it.next()) |depender| {
3077 if (zcu.outdated.getPtr(depender)) |po_dep_count| {2988 if (zcu.outdated.getPtr(depender)) |po_dep_count| {
...@@ -3079,9 +2990,9 @@ pub fn markDependeeOutdated(...@@ -3079,9 +2990,9 @@ pub fn markDependeeOutdated(
3079 .not_marked_po => {},2990 .not_marked_po => {},
3080 .marked_po => {2991 .marked_po => {
3081 po_dep_count.* -= 1;2992 po_dep_count.* -= 1;
3082 log.debug("outdated {} => already outdated {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });2993 log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
3083 if (po_dep_count.* == 0) {2994 if (po_dep_count.* == 0) {
3084 log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)});2995 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3085 try zcu.outdated_ready.put(zcu.gpa, depender, {});2996 try zcu.outdated_ready.put(zcu.gpa, depender, {});
3086 }2997 }
3087 },2998 },
...@@ -3102,9 +3013,9 @@ pub fn markDependeeOutdated(...@@ -3102,9 +3013,9 @@ pub fn markDependeeOutdated(
3102 depender,3013 depender,
3103 new_po_dep_count,3014 new_po_dep_count,
3104 );3015 );
3105 log.debug("outdated {} => new outdated {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count });3016 log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count });
3106 if (new_po_dep_count == 0) {3017 if (new_po_dep_count == 0) {
3107 log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)});3018 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3108 try zcu.outdated_ready.put(zcu.gpa, depender, {});3019 try zcu.outdated_ready.put(zcu.gpa, depender, {});
3109 }3020 }
3110 // If this is a Decl and was not previously PO, we must recursively3021 // If this is a Decl and was not previously PO, we must recursively
...@@ -3117,16 +3028,16 @@ pub fn markDependeeOutdated(...@@ -3117,16 +3028,16 @@ pub fn markDependeeOutdated(
3117}3028}
31183029
3119pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {3030pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
3120 log.debug("up-to-date dependee: {}", .{zcu.fmtDependee(dependee)});3031 log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)});
3121 var it = zcu.intern_pool.dependencyIterator(dependee);3032 var it = zcu.intern_pool.dependencyIterator(dependee);
3122 while (it.next()) |depender| {3033 while (it.next()) |depender| {
3123 if (zcu.outdated.getPtr(depender)) |po_dep_count| {3034 if (zcu.outdated.getPtr(depender)) |po_dep_count| {
3124 // This depender is already outdated, but it now has one3035 // This depender is already outdated, but it now has one
3125 // less PO dependency!3036 // less PO dependency!
3126 po_dep_count.* -= 1;3037 po_dep_count.* -= 1;
3127 log.debug("up-to-date {} => {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });3038 log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
3128 if (po_dep_count.* == 0) {3039 if (po_dep_count.* == 0) {
3129 log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)});3040 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3130 try zcu.outdated_ready.put(zcu.gpa, depender, {});3041 try zcu.outdated_ready.put(zcu.gpa, depender, {});
3131 }3042 }
3132 continue;3043 continue;
...@@ -3140,11 +3051,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -3140,11 +3051,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
3140 };3051 };
3141 if (ptr.* > 1) {3052 if (ptr.* > 1) {
3142 ptr.* -= 1;3053 ptr.* -= 1;
3143 log.debug("up-to-date {} => {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* });3054 log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* });
3144 continue;3055 continue;
3145 }3056 }
31463057
3147 log.debug("up-to-date {} => {} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) });3058 log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) });
31483059
3149 // This dependency is no longer PO, i.e. is known to be up-to-date.3060 // This dependency is no longer PO, i.e. is known to be up-to-date.
3150 assert(zcu.potentially_outdated.swapRemove(depender));3061 assert(zcu.potentially_outdated.swapRemove(depender));
...@@ -3173,7 +3084,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni...@@ -3173,7 +3084,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
3173 .func => |func_index| .{ .interned = func_index }, // IES3084 .func => |func_index| .{ .interned = func_index }, // IES
3174 .memoized_state => |stage| .{ .memoized_state = stage },3085 .memoized_state => |stage| .{ .memoized_state = stage },
3175 };3086 };
3176 log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});3087 log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
3177 var it = ip.dependencyIterator(dependee);3088 var it = ip.dependencyIterator(dependee);
3178 while (it.next()) |po| {3089 while (it.next()) |po| {
3179 if (zcu.outdated.getPtr(po)) |po_dep_count| {3090 if (zcu.outdated.getPtr(po)) |po_dep_count| {
...@@ -3183,17 +3094,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni...@@ -3183,17 +3094,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
3183 _ = zcu.outdated_ready.swapRemove(po);3094 _ = zcu.outdated_ready.swapRemove(po);
3184 }3095 }
3185 po_dep_count.* += 1;3096 po_dep_count.* += 1;
3186 log.debug("po {} => {} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* });3097 log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* });
3187 continue;3098 continue;
3188 }3099 }
3189 if (zcu.potentially_outdated.getPtr(po)) |n| {3100 if (zcu.potentially_outdated.getPtr(po)) |n| {
3190 // There is now one more PO dependency.3101 // There is now one more PO dependency.
3191 n.* += 1;3102 n.* += 1;
3192 log.debug("po {} => {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* });3103 log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* });
3193 continue;3104 continue;
3194 }3105 }
3195 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);3106 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);
3196 log.debug("po {} => {} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) });3107 log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) });
3197 // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO.3108 // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO.
3198 try zcu.markTransitiveDependersPotentiallyOutdated(po);3109 try zcu.markTransitiveDependersPotentiallyOutdated(po);
3199 }3110 }
...@@ -3222,7 +3133,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -3222,7 +3133,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
32223133
3223 if (zcu.outdated_ready.count() > 0) {3134 if (zcu.outdated_ready.count() > 0) {
3224 const unit = zcu.outdated_ready.keys()[0];3135 const unit = zcu.outdated_ready.keys()[0];
3225 log.debug("findOutdatedToAnalyze: trivial {}", .{zcu.fmtAnalUnit(unit)});3136 log.debug("findOutdatedToAnalyze: trivial {f}", .{zcu.fmtAnalUnit(unit)});
3226 return unit;3137 return unit;
3227 }3138 }
32283139
...@@ -3273,7 +3184,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -3273,7 +3184,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
3273 }3184 }
3274 }3185 }
32753186
3276 log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{3187 log.debug("findOutdatedToAnalyze: heuristic returned '{f}' ({d} dependers)", .{
3277 zcu.fmtAnalUnit(chosen_unit.?),3188 zcu.fmtAnalUnit(chosen_unit.?),
3278 chosen_unit_dependers,3189 chosen_unit_dependers,
3279 });3190 });
...@@ -4072,7 +3983,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4072,7 +3983,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4072 const referencer = kv.value;3983 const referencer = kv.value;
4073 try checked_types.putNoClobber(gpa, ty, {});3984 try checked_types.putNoClobber(gpa, ty, {});
40743985
4075 log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});3986 log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
40763987
4077 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.3988 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.
4078 const has_resolution: bool = switch (ip.indexToKey(ty)) {3989 const has_resolution: bool = switch (ip.indexToKey(ty)) {
...@@ -4108,7 +4019,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4108,7 +4019,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4108 // `comptime` decls are always analyzed.4019 // `comptime` decls are always analyzed.
4109 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });4020 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
4110 if (!result.contains(unit)) {4021 if (!result.contains(unit)) {
4111 log.debug("type '{}': ref comptime %{}", .{4022 log.debug("type '{f}': ref comptime %{}", .{
4112 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4023 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4113 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),4024 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),
4114 });4025 });
...@@ -4139,7 +4050,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4139,7 +4050,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4139 },4050 },
4140 };4051 };
4141 if (want_analysis) {4052 if (want_analysis) {
4142 log.debug("type '{}': ref test %{}", .{4053 log.debug("type '{f}': ref test %{}", .{
4143 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4054 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4144 @intFromEnum(inst_info.inst),4055 @intFromEnum(inst_info.inst),
4145 });4056 });
...@@ -4158,7 +4069,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4158,7 +4069,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4158 if (decl.linkage == .@"export") {4069 if (decl.linkage == .@"export") {
4159 const unit: AnalUnit = .wrap(.{ .nav_val = nav });4070 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
4160 if (!result.contains(unit)) {4071 if (!result.contains(unit)) {
4161 log.debug("type '{}': ref named %{}", .{4072 log.debug("type '{f}': ref named %{}", .{
4162 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4073 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4163 @intFromEnum(inst_info.inst),4074 @intFromEnum(inst_info.inst),
4164 });4075 });
...@@ -4174,7 +4085,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4174,7 +4085,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4174 if (decl.linkage == .@"export") {4085 if (decl.linkage == .@"export") {
4175 const unit: AnalUnit = .wrap(.{ .nav_val = nav });4086 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
4176 if (!result.contains(unit)) {4087 if (!result.contains(unit)) {
4177 log.debug("type '{}': ref named %{}", .{4088 log.debug("type '{f}': ref named %{}", .{
4178 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4089 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4179 @intFromEnum(inst_info.inst),4090 @intFromEnum(inst_info.inst),
4180 });4091 });
...@@ -4199,7 +4110,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4199,7 +4110,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4199 try unit_queue.put(gpa, other, kv.value); // same reference location4110 try unit_queue.put(gpa, other, kv.value); // same reference location
4200 }4111 }
42014112
4202 log.debug("handle unit '{}'", .{zcu.fmtAnalUnit(unit)});4113 log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});
42034114
4204 if (zcu.reference_table.get(unit)) |first_ref_idx| {4115 if (zcu.reference_table.get(unit)) |first_ref_idx| {
4205 assert(first_ref_idx != std.math.maxInt(u32));4116 assert(first_ref_idx != std.math.maxInt(u32));
...@@ -4207,7 +4118,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4207,7 +4118,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4207 while (ref_idx != std.math.maxInt(u32)) {4118 while (ref_idx != std.math.maxInt(u32)) {
4208 const ref = zcu.all_references.items[ref_idx];4119 const ref = zcu.all_references.items[ref_idx];
4209 if (!result.contains(ref.referenced)) {4120 if (!result.contains(ref.referenced)) {
4210 log.debug("unit '{}': ref unit '{}'", .{4121 log.debug("unit '{f}': ref unit '{f}'", .{
4211 zcu.fmtAnalUnit(unit),4122 zcu.fmtAnalUnit(unit),
4212 zcu.fmtAnalUnit(ref.referenced),4123 zcu.fmtAnalUnit(ref.referenced),
4213 });4124 });
...@@ -4226,7 +4137,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4226,7 +4137,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4226 while (ref_idx != std.math.maxInt(u32)) {4137 while (ref_idx != std.math.maxInt(u32)) {
4227 const ref = zcu.all_type_references.items[ref_idx];4138 const ref = zcu.all_type_references.items[ref_idx];
4228 if (!checked_types.contains(ref.referenced)) {4139 if (!checked_types.contains(ref.referenced)) {
4229 log.debug("unit '{}': ref type '{}'", .{4140 log.debug("unit '{f}': ref type '{f}'", .{
4230 zcu.fmtAnalUnit(unit),4141 zcu.fmtAnalUnit(unit),
4231 Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip),4142 Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip),
4232 });4143 });
...@@ -4307,15 +4218,19 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {...@@ -4307,15 +4218,19 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {
4307 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));4218 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));
4308}4219}
43094220
4310pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) {4221pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(FormatAnalUnit, formatAnalUnit) {
4311 return .{ .data = .{ .unit = unit, .zcu = zcu } };4222 return .{ .data = .{ .unit = unit, .zcu = zcu } };
4312}4223}
4313pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(formatDependee) {4224pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(FormatDependee, formatDependee) {
4314 return .{ .data = .{ .dependee = d, .zcu = zcu } };4225 return .{ .data = .{ .dependee = d, .zcu = zcu } };
4315}4226}
43164227
4317fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {4228const FormatAnalUnit = struct {
4318 _ = .{ fmt, options };4229 unit: AnalUnit,
4230 zcu: *Zcu,
4231};
4232
4233fn formatAnalUnit(data: FormatAnalUnit, writer: *std.io.Writer) std.io.Writer.Error!void {
4319 const zcu = data.zcu;4234 const zcu = data.zcu;
4320 const ip = &zcu.intern_pool;4235 const ip = &zcu.intern_pool;
4321 switch (data.unit.unwrap()) {4236 switch (data.unit.unwrap()) {
...@@ -4323,23 +4238,25 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co...@@ -4323,23 +4238,25 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
4323 const cu = ip.getComptimeUnit(cu_id);4238 const cu = ip.getComptimeUnit(cu_id);
4324 if (cu.zir_index.resolveFull(ip)) |resolved| {4239 if (cu.zir_index.resolveFull(ip)) |resolved| {
4325 const file_path = zcu.fileByIndex(resolved.file).path;4240 const file_path = zcu.fileByIndex(resolved.file).path;
4326 return writer.print("comptime(inst=('{}', %{}) [{}])", .{ file_path.fmt(zcu.comp), @intFromEnum(resolved.inst), @intFromEnum(cu_id) });4241 return writer.print("comptime(inst=('{f}', %{}) [{}])", .{ file_path.fmt(zcu.comp), @intFromEnum(resolved.inst), @intFromEnum(cu_id) });
4327 } else {4242 } else {
4328 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});4243 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});
4329 }4244 }
4330 },4245 },
4331 .nav_val => |nav| return writer.print("nav_val('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),4246 .nav_val => |nav| return writer.print("nav_val('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4332 .nav_ty => |nav| return writer.print("nav_ty('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),4247 .nav_ty => |nav| return writer.print("nav_ty('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4333 .type => |ty| return writer.print("ty('{}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),4248 .type => |ty| return writer.print("ty('{f}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
4334 .func => |func| {4249 .func => |func| {
4335 const nav = zcu.funcInfo(func).owner_nav;4250 const nav = zcu.funcInfo(func).owner_nav;
4336 return writer.print("func('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });4251 return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });
4337 },4252 },
4338 .memoized_state => return writer.writeAll("memoized_state"),4253 .memoized_state => return writer.writeAll("memoized_state"),
4339 }4254 }
4340}4255}
4341fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {4256
4342 _ = .{ fmt, options };4257const FormatDependee = struct { dependee: InternPool.Dependee, zcu: *Zcu };
4258
4259fn formatDependee(data: FormatDependee, writer: *std.io.Writer) std.io.Writer.Error!void {
4343 const zcu = data.zcu;4260 const zcu = data.zcu;
4344 const ip = &zcu.intern_pool;4261 const ip = &zcu.intern_pool;
4345 switch (data.dependee) {4262 switch (data.dependee) {
...@@ -4348,42 +4265,42 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com...@@ -4348,42 +4265,42 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
4348 return writer.writeAll("inst(<lost>)");4265 return writer.writeAll("inst(<lost>)");
4349 };4266 };
4350 const file_path = zcu.fileByIndex(info.file).path;4267 const file_path = zcu.fileByIndex(info.file).path;
4351 return writer.print("inst('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });4268 return writer.print("inst('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4352 },4269 },
4353 .nav_val => |nav| {4270 .nav_val => |nav| {
4354 const fqn = ip.getNav(nav).fqn;4271 const fqn = ip.getNav(nav).fqn;
4355 return writer.print("nav_val('{}')", .{fqn.fmt(ip)});4272 return writer.print("nav_val('{f}')", .{fqn.fmt(ip)});
4356 },4273 },
4357 .nav_ty => |nav| {4274 .nav_ty => |nav| {
4358 const fqn = ip.getNav(nav).fqn;4275 const fqn = ip.getNav(nav).fqn;
4359 return writer.print("nav_ty('{}')", .{fqn.fmt(ip)});4276 return writer.print("nav_ty('{f}')", .{fqn.fmt(ip)});
4360 },4277 },
4361 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {4278 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
4362 .struct_type, .union_type, .enum_type => return writer.print("type('{}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),4279 .struct_type, .union_type, .enum_type => return writer.print("type('{f}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),
4363 .func => |f| return writer.print("ies('{}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}),4280 .func => |f| return writer.print("ies('{f}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}),
4364 else => unreachable,4281 else => unreachable,
4365 },4282 },
4366 .zon_file => |file| {4283 .zon_file => |file| {
4367 const file_path = zcu.fileByIndex(file).path;4284 const file_path = zcu.fileByIndex(file).path;
4368 return writer.print("zon_file('{}')", .{file_path.fmt(zcu.comp)});4285 return writer.print("zon_file('{f}')", .{file_path.fmt(zcu.comp)});
4369 },4286 },
4370 .embed_file => |ef_idx| {4287 .embed_file => |ef_idx| {
4371 const ef = ef_idx.get(zcu);4288 const ef = ef_idx.get(zcu);
4372 return writer.print("embed_file('{}')", .{ef.path.fmt(zcu.comp)});4289 return writer.print("embed_file('{f}')", .{ef.path.fmt(zcu.comp)});
4373 },4290 },
4374 .namespace => |ti| {4291 .namespace => |ti| {
4375 const info = ti.resolveFull(ip) orelse {4292 const info = ti.resolveFull(ip) orelse {
4376 return writer.writeAll("namespace(<lost>)");4293 return writer.writeAll("namespace(<lost>)");
4377 };4294 };
4378 const file_path = zcu.fileByIndex(info.file).path;4295 const file_path = zcu.fileByIndex(info.file).path;
4379 return writer.print("namespace('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });4296 return writer.print("namespace('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4380 },4297 },
4381 .namespace_name => |k| {4298 .namespace_name => |k| {
4382 const info = k.namespace.resolveFull(ip) orelse {4299 const info = k.namespace.resolveFull(ip) orelse {
4383 return writer.print("namespace(<lost>, '{}')", .{k.name.fmt(ip)});4300 return writer.print("namespace(<lost>, '{f}')", .{k.name.fmt(ip)});
4384 };4301 };
4385 const file_path = zcu.fileByIndex(info.file).path;4302 const file_path = zcu.fileByIndex(info.file).path;
4386 return writer.print("namespace('{}', %{d}, '{}')", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst), k.name.fmt(ip) });4303 return writer.print("namespace('{f}', %{d}, '{f}')", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst), k.name.fmt(ip) });
4387 },4304 },
4388 .memoized_state => return writer.writeAll("memoized_state"),4305 .memoized_state => return writer.writeAll("memoized_state"),
4389 }4306 }
src/Zcu/PerThread.zig+65-58
...@@ -53,7 +53,7 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {...@@ -53,7 +53,7 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {
53 const zcu = pt.zcu;53 const zcu = pt.zcu;
54 const gpa = zcu.gpa;54 const gpa = zcu.gpa;
55 const file = zcu.fileByIndex(file_index);55 const file = zcu.fileByIndex(file_index);
56 log.debug("deinit File {}", .{file.path.fmt(zcu.comp)});56 log.debug("deinit File {f}", .{file.path.fmt(zcu.comp)});
57 file.path.deinit(gpa);57 file.path.deinit(gpa);
58 file.unload(gpa);58 file.unload(gpa);
59 if (file.prev_zir) |prev_zir| {59 if (file.prev_zir) |prev_zir| {
...@@ -117,7 +117,7 @@ pub fn updateFile(...@@ -117,7 +117,7 @@ pub fn updateFile(
117 var lock: std.fs.File.Lock = switch (file.status) {117 var lock: std.fs.File.Lock = switch (file.status) {
118 .never_loaded, .retryable_failure => lock: {118 .never_loaded, .retryable_failure => lock: {
119 // First, load the cached ZIR code, if any.119 // First, load the cached ZIR code, if any.
120 log.debug("AstGen checking cache: {} (local={}, digest={s})", .{120 log.debug("AstGen checking cache: {f} (local={}, digest={s})", .{
121 file.path.fmt(comp), want_local_cache, &hex_digest,121 file.path.fmt(comp), want_local_cache, &hex_digest,
122 });122 });
123123
...@@ -130,11 +130,11 @@ pub fn updateFile(...@@ -130,11 +130,11 @@ pub fn updateFile(
130 stat.inode == file.stat.inode;130 stat.inode == file.stat.inode;
131131
132 if (unchanged_metadata) {132 if (unchanged_metadata) {
133 log.debug("unmodified metadata of file: {}", .{file.path.fmt(comp)});133 log.debug("unmodified metadata of file: {f}", .{file.path.fmt(comp)});
134 return;134 return;
135 }135 }
136136
137 log.debug("metadata changed: {}", .{file.path.fmt(comp)});137 log.debug("metadata changed: {f}", .{file.path.fmt(comp)});
138138
139 break :lock .exclusive;139 break :lock .exclusive;
140 },140 },
...@@ -190,7 +190,7 @@ pub fn updateFile(...@@ -190,7 +190,7 @@ pub fn updateFile(
190 // failure was a race, or ENOENT, indicating deletion of the190 // failure was a race, or ENOENT, indicating deletion of the
191 // directory of our open handle.191 // directory of our open handle.
192 if (builtin.os.tag != .macos) {192 if (builtin.os.tag != .macos) {
193 std.process.fatal("cache directory '{}' unexpectedly removed during compiler execution", .{193 std.process.fatal("cache directory '{f}' unexpectedly removed during compiler execution", .{
194 cache_directory,194 cache_directory,
195 });195 });
196 }196 }
...@@ -202,7 +202,7 @@ pub fn updateFile(...@@ -202,7 +202,7 @@ pub fn updateFile(
202 }) catch |excl_err| switch (excl_err) {202 }) catch |excl_err| switch (excl_err) {
203 error.PathAlreadyExists => continue,203 error.PathAlreadyExists => continue,
204 error.FileNotFound => {204 error.FileNotFound => {
205 std.process.fatal("cache directory '{}' unexpectedly removed during compiler execution", .{205 std.process.fatal("cache directory '{f}' unexpectedly removed during compiler execution", .{
206 cache_directory,206 cache_directory,
207 });207 });
208 },208 },
...@@ -221,12 +221,12 @@ pub fn updateFile(...@@ -221,12 +221,12 @@ pub fn updateFile(
221 };221 };
222 switch (result) {222 switch (result) {
223 .success => {223 .success => {
224 log.debug("AstGen cached success: {}", .{file.path.fmt(comp)});224 log.debug("AstGen cached success: {f}", .{file.path.fmt(comp)});
225 break false;225 break false;
226 },226 },
227 .invalid => {},227 .invalid => {},
228 .truncated => log.warn("unexpected EOF reading cached ZIR for {}", .{file.path.fmt(comp)}),228 .truncated => log.warn("unexpected EOF reading cached ZIR for {f}", .{file.path.fmt(comp)}),
229 .stale => log.debug("AstGen cache stale: {}", .{file.path.fmt(comp)}),229 .stale => log.debug("AstGen cache stale: {f}", .{file.path.fmt(comp)}),
230 }230 }
231231
232 // If we already have the exclusive lock then it is our job to update.232 // If we already have the exclusive lock then it is our job to update.
...@@ -249,11 +249,14 @@ pub fn updateFile(...@@ -249,11 +249,14 @@ pub fn updateFile(
249 if (stat.size > std.math.maxInt(u32))249 if (stat.size > std.math.maxInt(u32))
250 return error.FileTooBig;250 return error.FileTooBig;
251251
252 const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);252 const source = try gpa.allocSentinel(u8, @intCast(stat.size), 0);
253 defer if (file.source == null) gpa.free(source);253 defer if (file.source == null) gpa.free(source);
254 const amt = try source_file.readAll(source);254 var source_fr = source_file.reader(&.{});
255 if (amt != stat.size)255 source_fr.size = stat.size;
256 return error.UnexpectedEndOfFile;256 source_fr.interface.readSliceAll(source) catch |err| switch (err) {
257 error.ReadFailed => return source_fr.err.?,
258 error.EndOfStream => return error.UnexpectedEndOfFile,
259 };
257260
258 file.source = source;261 file.source = source;
259262
...@@ -265,7 +268,7 @@ pub fn updateFile(...@@ -265,7 +268,7 @@ pub fn updateFile(
265 file.zir = try AstGen.generate(gpa, file.tree.?);268 file.zir = try AstGen.generate(gpa, file.tree.?);
266 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {269 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {
267 error.OutOfMemory => |e| return e,270 error.OutOfMemory => |e| return e,
268 else => log.warn("unable to write cached ZIR code for {} to {}{s}: {s}", .{271 else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {s}", .{
269 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),272 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
270 }),273 }),
271 };274 };
...@@ -273,14 +276,14 @@ pub fn updateFile(...@@ -273,14 +276,14 @@ pub fn updateFile(
273 .zon => {276 .zon => {
274 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});277 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});
275 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {278 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {
276 log.warn("unable to write cached ZOIR code for {} to {}{s}: {s}", .{279 log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {s}", .{
277 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),280 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
278 });281 });
279 };282 };
280 },283 },
281 }284 }
282285
283 log.debug("AstGen fresh success: {}", .{file.path.fmt(comp)});286 log.debug("AstGen fresh success: {f}", .{file.path.fmt(comp)});
284 }287 }
285288
286 file.stat = .{289 file.stat = .{
...@@ -340,13 +343,19 @@ fn loadZirZoirCache(...@@ -340,13 +343,19 @@ fn loadZirZoirCache(
340 .zon => Zoir.Header,343 .zon => Zoir.Header,
341 };344 };
342345
346 var buffer: [2000]u8 = undefined;
347 var cache_fr = cache_file.reader(&buffer);
348 cache_fr.size = stat.size;
349 const cache_br = &cache_fr.interface;
350
343 // First we read the header to determine the lengths of arrays.351 // First we read the header to determine the lengths of arrays.
344 const header = cache_file.reader().readStruct(Header) catch |err| switch (err) {352 const header = (cache_br.takeStruct(Header) catch |err| switch (err) {
353 error.ReadFailed => return cache_fr.err.?,
345 // This can happen if Zig bails out of this function between creating354 // This can happen if Zig bails out of this function between creating
346 // the cached file and writing it.355 // the cached file and writing it.
347 error.EndOfStream => return .invalid,356 error.EndOfStream => return .invalid,
348 else => |e| return e,357 else => |e| return e,
349 };358 }).*;
350359
351 const unchanged_metadata =360 const unchanged_metadata =
352 stat.size == header.stat_size and361 stat.size == header.stat_size and
...@@ -358,17 +367,15 @@ fn loadZirZoirCache(...@@ -358,17 +367,15 @@ fn loadZirZoirCache(
358 }367 }
359368
360 switch (mode) {369 switch (mode) {
361 .zig => {370 .zig => file.zir = Zcu.loadZirCacheBody(gpa, header, cache_br) catch |err| switch (err) {
362 file.zir = Zcu.loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) {371 error.ReadFailed => return cache_fr.err.?,
363 error.UnexpectedFileSize => return .truncated,372 error.EndOfStream => return .truncated,
364 else => |e| return e,373 else => |e| return e,
365 };
366 },374 },
367 .zon => {375 .zon => file.zoir = Zcu.loadZoirCacheBody(gpa, header, cache_br) catch |err| switch (err) {
368 file.zoir = Zcu.loadZoirCacheBody(gpa, header, cache_file) catch |err| switch (err) {376 error.ReadFailed => return cache_fr.err.?,
369 error.UnexpectedFileSize => return .truncated,377 error.EndOfStream => return .truncated,
370 else => |e| return e,378 else => |e| return e,
371 };
372 },379 },
373 }380 }
374381
...@@ -477,11 +484,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -477,11 +484,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
477 if (std.zig.srcHashEql(old_hash, new_hash)) {484 if (std.zig.srcHashEql(old_hash, new_hash)) {
478 break :hash_changed;485 break :hash_changed;
479 }486 }
480 log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{487 log.debug("hash for (%{d} -> %{d}) changed: {x} -> {x}", .{
481 old_inst,488 old_inst, new_inst, &old_hash, &new_hash,
482 new_inst,
483 std.fmt.fmtSliceHexLower(&old_hash),
484 std.fmt.fmtSliceHexLower(&new_hash),
485 });489 });
486 }490 }
487 // The source hash associated with this instruction changed - invalidate relevant dependencies.491 // The source hash associated with this instruction changed - invalidate relevant dependencies.
...@@ -649,7 +653,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized...@@ -649,7 +653,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
649 // If this unit caused the error, it would have an entry in `failed_analysis`.653 // If this unit caused the error, it would have an entry in `failed_analysis`.
650 // Since it does not, this must be a transitive failure.654 // Since it does not, this must be a transitive failure.
651 try zcu.transitive_failed_analysis.put(gpa, unit, {});655 try zcu.transitive_failed_analysis.put(gpa, unit, {});
652 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(unit)});656 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(unit)});
653 }657 }
654 break :res .{ !prev_failed, true };658 break :res .{ !prev_failed, true };
655 },659 },
...@@ -754,7 +758,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -754,7 +758,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
754758
755 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });759 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
756760
757 log.debug("ensureComptimeUnitUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});761 log.debug("ensureComptimeUnitUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
758762
759 assert(!zcu.analysis_in_progress.contains(anal_unit));763 assert(!zcu.analysis_in_progress.contains(anal_unit));
760764
...@@ -805,7 +809,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -805,7 +809,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
805 // If this unit caused the error, it would have an entry in `failed_analysis`.809 // If this unit caused the error, it would have an entry in `failed_analysis`.
806 // Since it does not, this must be a transitive failure.810 // Since it does not, this must be a transitive failure.
807 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});811 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
808 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});812 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
809 }813 }
810 return error.AnalysisFail;814 return error.AnalysisFail;
811 },815 },
...@@ -835,7 +839,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -835,7 +839,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
835 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });839 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
836 const comptime_unit = ip.getComptimeUnit(cu_id);840 const comptime_unit = ip.getComptimeUnit(cu_id);
837841
838 log.debug("analyzeComptimeUnit {}", .{zcu.fmtAnalUnit(anal_unit)});842 log.debug("analyzeComptimeUnit {f}", .{zcu.fmtAnalUnit(anal_unit)});
839843
840 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;844 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
841 const file = zcu.fileByIndex(inst_resolved.file);845 const file = zcu.fileByIndex(inst_resolved.file);
...@@ -881,7 +885,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -881,7 +885,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
881 .r = .{ .simple = .comptime_keyword },885 .r = .{ .simple = .comptime_keyword },
882 } },886 } },
883 .src_base_inst = comptime_unit.zir_index,887 .src_base_inst = comptime_unit.zir_index,
884 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{888 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.comptime", .{
885 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),889 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
886 }, .no_embedded_nulls),890 }, .no_embedded_nulls),
887 };891 };
...@@ -933,7 +937,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu...@@ -933,7 +937,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
933 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });937 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
934 const nav = ip.getNav(nav_id);938 const nav = ip.getNav(nav_id);
935939
936 log.debug("ensureNavValUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});940 log.debug("ensureNavValUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
937941
938 // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the942 // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the
939 // status is `.unresolved`, which indicates that the value is outdated because it has *never*943 // status is `.unresolved`, which indicates that the value is outdated because it has *never*
...@@ -991,7 +995,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu...@@ -991,7 +995,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
991 // If this unit caused the error, it would have an entry in `failed_analysis`.995 // If this unit caused the error, it would have an entry in `failed_analysis`.
992 // Since it does not, this must be a transitive failure.996 // Since it does not, this must be a transitive failure.
993 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});997 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
994 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});998 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
995 }999 }
996 break :res .{ !prev_failed, true };1000 break :res .{ !prev_failed, true };
997 },1001 },
...@@ -1062,7 +1066,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1062,7 +1066,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1062 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });1066 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
1063 const old_nav = ip.getNav(nav_id);1067 const old_nav = ip.getNav(nav_id);
10641068
1065 log.debug("analyzeNavVal {}", .{zcu.fmtAnalUnit(anal_unit)});1069 log.debug("analyzeNavVal {f}", .{zcu.fmtAnalUnit(anal_unit)});
10661070
1067 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1071 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1068 const file = zcu.fileByIndex(inst_resolved.file);1072 const file = zcu.fileByIndex(inst_resolved.file);
...@@ -1321,7 +1325,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc...@@ -1321,7 +1325,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
1321 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });1325 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1322 const nav = ip.getNav(nav_id);1326 const nav = ip.getNav(nav_id);
13231327
1324 log.debug("ensureNavTypeUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});1328 log.debug("ensureNavTypeUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
13251329
1326 const type_resolved_by_value: bool = from_val: {1330 const type_resolved_by_value: bool = from_val: {
1327 const analysis = nav.analysis orelse break :from_val false;1331 const analysis = nav.analysis orelse break :from_val false;
...@@ -1391,7 +1395,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc...@@ -1391,7 +1395,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
1391 // If this unit caused the error, it would have an entry in `failed_analysis`.1395 // If this unit caused the error, it would have an entry in `failed_analysis`.
1392 // Since it does not, this must be a transitive failure.1396 // Since it does not, this must be a transitive failure.
1393 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});1397 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1394 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});1398 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1395 }1399 }
1396 break :res .{ !prev_failed, true };1400 break :res .{ !prev_failed, true };
1397 },1401 },
...@@ -1433,7 +1437,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr...@@ -1433,7 +1437,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
1433 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });1437 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1434 const old_nav = ip.getNav(nav_id);1438 const old_nav = ip.getNav(nav_id);
14351439
1436 log.debug("analyzeNavType {}", .{zcu.fmtAnalUnit(anal_unit)});1440 log.debug("analyzeNavType {f}", .{zcu.fmtAnalUnit(anal_unit)});
14371441
1438 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1442 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1439 const file = zcu.fileByIndex(inst_resolved.file);1443 const file = zcu.fileByIndex(inst_resolved.file);
...@@ -1563,7 +1567,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -1563,7 +1567,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
1563 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);1567 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);
1564 const anal_unit: AnalUnit = .wrap(.{ .func = func_index });1568 const anal_unit: AnalUnit = .wrap(.{ .func = func_index });
15651569
1566 log.debug("ensureFuncBodyUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});1570 log.debug("ensureFuncBodyUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
15671571
1568 const func = zcu.funcInfo(maybe_coerced_func_index);1572 const func = zcu.funcInfo(maybe_coerced_func_index);
15691573
...@@ -1607,7 +1611,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -1607,7 +1611,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
1607 // If this function caused the error, it would have an entry in `failed_analysis`.1611 // If this function caused the error, it would have an entry in `failed_analysis`.
1608 // Since it does not, this must be a transitive failure.1612 // Since it does not, this must be a transitive failure.
1609 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});1613 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1610 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});1614 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1611 }1615 }
1612 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,1616 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
1613 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting1617 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
...@@ -1677,7 +1681,7 @@ fn analyzeFuncBody(...@@ -1677,7 +1681,7 @@ fn analyzeFuncBody(
1677 else1681 else
1678 .none;1682 .none;
16791683
1680 log.debug("analyze and generate fn body {}", .{zcu.fmtAnalUnit(anal_unit)});1684 log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)});
16811685
1682 var air = try pt.analyzeFnBodyInner(func_index);1686 var air = try pt.analyzeFnBodyInner(func_index);
1683 errdefer air.deinit(gpa);1687 errdefer air.deinit(gpa);
...@@ -2299,7 +2303,7 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi...@@ -2299,7 +2303,7 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi
22992303
2300 Builtin.updateFileOnDisk(file, comp) catch |err| comp.setMiscFailure(2304 Builtin.updateFileOnDisk(file, comp) catch |err| comp.setMiscFailure(
2301 .write_builtin_zig,2305 .write_builtin_zig,
2302 "unable to write '{}': {s}",2306 "unable to write '{f}': {s}",
2303 .{ file.path.fmt(comp), @errorName(err) },2307 .{ file.path.fmt(comp), @errorName(err) },
2304 );2308 );
2305}2309}
...@@ -2414,8 +2418,12 @@ fn updateEmbedFileInner(...@@ -2414,8 +2418,12 @@ fn updateEmbedFileInner(
2414 const old_len = strings.mutate.len;2418 const old_len = strings.mutate.len;
2415 errdefer strings.shrinkRetainingCapacity(old_len);2419 errdefer strings.shrinkRetainingCapacity(old_len);
2416 const bytes = (try strings.addManyAsSlice(size_plus_one))[0];2420 const bytes = (try strings.addManyAsSlice(size_plus_one))[0];
2417 const actual_read = try file.readAll(bytes[0..size]);2421 var fr = file.reader(&.{});
2418 if (actual_read != size) return error.UnexpectedEof;2422 fr.size = stat.size;
2423 fr.interface.readSliceAll(bytes[0..size]) catch |err| switch (err) {
2424 error.ReadFailed => return fr.err.?,
2425 error.EndOfStream => return error.UnexpectedEof,
2426 };
2419 bytes[size] = 0;2427 bytes[size] = 0;
2420 break :str try ip.getOrPutTrailingString(gpa, tid, @intCast(bytes.len), .maybe_embedded_nulls);2428 break :str try ip.getOrPutTrailingString(gpa, tid, @intCast(bytes.len), .maybe_embedded_nulls);
2421 };2429 };
...@@ -2584,7 +2592,7 @@ const ScanDeclIter = struct {...@@ -2584,7 +2592,7 @@ const ScanDeclIter = struct {
2584 var gop = try iter.seen_decls.getOrPut(gpa, name);2592 var gop = try iter.seen_decls.getOrPut(gpa, name);
2585 var next_suffix: u32 = 0;2593 var next_suffix: u32 = 0;
2586 while (gop.found_existing) {2594 while (gop.found_existing) {
2587 name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);2595 name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);
2588 gop = try iter.seen_decls.getOrPut(gpa, name);2596 gop = try iter.seen_decls.getOrPut(gpa, name);
2589 next_suffix += 1;2597 next_suffix += 1;
2590 }2598 }
...@@ -2716,7 +2724,7 @@ const ScanDeclIter = struct {...@@ -2716,7 +2724,7 @@ const ScanDeclIter = struct {
27162724
2717 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {2725 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {
2718 log.debug(2726 log.debug(
2719 "scanDecl queue analyze_comptime_unit file='{s}' unit={}",2727 "scanDecl queue analyze_comptime_unit file='{s}' unit={f}",
2720 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },2728 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },
2721 );2729 );
2722 try comp.queueJob(.{ .analyze_comptime_unit = unit });2730 try comp.queueJob(.{ .analyze_comptime_unit = unit });
...@@ -3134,7 +3142,7 @@ fn processExportsInner(...@@ -3134,7 +3142,7 @@ fn processExportsInner(
3134 if (gop.found_existing) {3142 if (gop.found_existing) {
3135 new_export.status = .failed_retryable;3143 new_export.status = .failed_retryable;
3136 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);3144 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
3137 const msg = try Zcu.ErrorMsg.create(gpa, new_export.src, "exported symbol collision: {}", .{3145 const msg = try Zcu.ErrorMsg.create(gpa, new_export.src, "exported symbol collision: {f}", .{
3138 new_export.opts.name.fmt(ip),3146 new_export.opts.name.fmt(ip),
3139 });3147 });
3140 errdefer msg.destroy(gpa);3148 errdefer msg.destroy(gpa);
...@@ -4376,12 +4384,11 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4376,12 +4384,11 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4376 defer liveness.deinit(gpa);4384 defer liveness.deinit(gpa);
43774385
4378 if (build_options.enable_debug_extensions and comp.verbose_air) {4386 if (build_options.enable_debug_extensions and comp.verbose_air) {
4379 std.debug.lockStdErr();4387 const stderr = std.debug.lockStderrWriter(&.{});
4380 defer std.debug.unlockStdErr();4388 defer std.debug.unlockStderrWriter();
4381 const stderr = std.io.getStdErr().writer();4389 stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {};
4382 stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {};
4383 air.write(stderr, pt, liveness);4390 air.write(stderr, pt, liveness);
4384 stderr.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}) catch {};4391 stderr.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}) catch {};
4385 }4392 }
43864393
4387 if (std.debug.runtime_safety) {4394 if (std.debug.runtime_safety) {
src/arch/riscv64/CodeGen.zig+53-74
...@@ -435,7 +435,7 @@ const InstTracking = struct {...@@ -435,7 +435,7 @@ const InstTracking = struct {
435 fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {435 fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
436 try function.freeValue(inst_tracking.short);436 try function.freeValue(inst_tracking.short);
437 inst_tracking.reuseFrame();437 inst_tracking.reuseFrame();
438 tracking_log.debug("%{d} => {} (spilled)", .{ inst, inst_tracking.* });438 tracking_log.debug("%{d} => {f} (spilled)", .{ inst, inst_tracking.* });
439 }439 }
440440
441 fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void {441 fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void {
...@@ -499,14 +499,14 @@ const InstTracking = struct {...@@ -499,14 +499,14 @@ const InstTracking = struct {
499 else => target.long,499 else => target.long,
500 } else target.long;500 } else target.long;
501 inst_tracking.short = target.short;501 inst_tracking.short = target.short;
502 tracking_log.debug("%{d} => {} (materialize)", .{ inst, inst_tracking.* });502 tracking_log.debug("%{d} => {f} (materialize)", .{ inst, inst_tracking.* });
503 }503 }
504504
505 fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {505 fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
506 switch (inst_tracking.short) {506 switch (inst_tracking.short) {
507 .dead => |die_generation| if (die_generation >= scope_generation) {507 .dead => |die_generation| if (die_generation >= scope_generation) {
508 inst_tracking.reuseFrame();508 inst_tracking.reuseFrame();
509 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, inst_tracking.* });509 tracking_log.debug("%{d} => {f} (resurrect)", .{ inst, inst_tracking.* });
510 },510 },
511 else => {},511 else => {},
512 }512 }
...@@ -516,7 +516,7 @@ const InstTracking = struct {...@@ -516,7 +516,7 @@ const InstTracking = struct {
516 if (inst_tracking.short == .dead) return;516 if (inst_tracking.short == .dead) return;
517 try function.freeValue(inst_tracking.short);517 try function.freeValue(inst_tracking.short);
518 inst_tracking.short = .{ .dead = function.scope_generation };518 inst_tracking.short = .{ .dead = function.scope_generation };
519 tracking_log.debug("%{d} => {} (death)", .{ inst, inst_tracking.* });519 tracking_log.debug("%{d} => {f} (death)", .{ inst, inst_tracking.* });
520 }520 }
521521
522 fn reuse(522 fn reuse(
...@@ -527,15 +527,15 @@ const InstTracking = struct {...@@ -527,15 +527,15 @@ const InstTracking = struct {
527 ) void {527 ) void {
528 inst_tracking.short = .{ .dead = function.scope_generation };528 inst_tracking.short = .{ .dead = function.scope_generation };
529 if (new_inst) |inst|529 if (new_inst) |inst|
530 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, inst_tracking.*, old_inst })530 tracking_log.debug("%{d} => {f} (reuse %{d})", .{ inst, inst_tracking.*, old_inst })
531 else531 else
532 tracking_log.debug("tmp => {} (reuse %{d})", .{ inst_tracking.*, old_inst });532 tracking_log.debug("tmp => {f} (reuse %{d})", .{ inst_tracking.*, old_inst });
533 }533 }
534534
535 fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void {535 fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void {
536 for (inst_tracking.getRegs()) |reg| {536 for (inst_tracking.getRegs()) |reg| {
537 if (function.register_manager.isRegFree(reg)) {537 if (function.register_manager.isRegFree(reg)) {
538 tracking_log.debug("%{d} => {} (live-out)", .{ inst, inst_tracking.* });538 tracking_log.debug("%{d} => {f} (live-out)", .{ inst, inst_tracking.* });
539 continue;539 continue;
540 }540 }
541541
...@@ -562,16 +562,11 @@ const InstTracking = struct {...@@ -562,16 +562,11 @@ const InstTracking = struct {
562 // Perform side-effects of freeValue manually.562 // Perform side-effects of freeValue manually.
563 function.register_manager.freeReg(reg);563 function.register_manager.freeReg(reg);
564564
565 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, inst_tracking.*, tracked_inst });565 tracking_log.debug("%{d} => {f} (live-out %{d})", .{ inst, inst_tracking.*, tracked_inst });
566 }566 }
567 }567 }
568568
569 pub fn format(569 pub fn format(inst_tracking: InstTracking, writer: *std.io.Writer) std.io.Writer.Error!void {
570 inst_tracking: InstTracking,
571 comptime _: []const u8,
572 _: std.fmt.FormatOptions,
573 writer: anytype,
574 ) @TypeOf(writer).Error!void {
575 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long});570 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long});
576 try writer.print("{}", .{inst_tracking.short});571 try writer.print("{}", .{inst_tracking.short});
577 }572 }
...@@ -802,7 +797,7 @@ pub fn generate(...@@ -802,7 +797,7 @@ pub fn generate(
802 function.mir_instructions.deinit(gpa);797 function.mir_instructions.deinit(gpa);
803 }798 }
804799
805 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});800 wip_mir_log.debug("{f}:", .{fmtNav(func.owner_nav, ip)});
806801
807 try function.frame_allocs.resize(gpa, FrameIndex.named_count);802 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
808 function.frame_allocs.set(803 function.frame_allocs.set(
...@@ -937,12 +932,7 @@ const FormatWipMirData = struct {...@@ -937,12 +932,7 @@ const FormatWipMirData = struct {
937 func: *Func,932 func: *Func,
938 inst: Mir.Inst.Index,933 inst: Mir.Inst.Index,
939};934};
940fn formatWipMir(935fn formatWipMir(data: FormatWipMirData, writer: *std.io.Writer) std.io.Writer.Error!void {
941 data: FormatWipMirData,
942 comptime _: []const u8,
943 _: std.fmt.FormatOptions,
944 writer: anytype,
945) @TypeOf(writer).Error!void {
946 const pt = data.func.pt;936 const pt = data.func.pt;
947 const comp = pt.zcu.comp;937 const comp = pt.zcu.comp;
948 var lower: Lower = .{938 var lower: Lower = .{
...@@ -982,7 +972,7 @@ fn formatWipMir(...@@ -982,7 +972,7 @@ fn formatWipMir(
982 first = false;972 first = false;
983 }973 }
984}974}
985fn fmtWipMir(func: *Func, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) {975fn fmtWipMir(func: *Func, inst: Mir.Inst.Index) std.fmt.Formatter(FormatWipMirData, formatWipMir) {
986 return .{ .data = .{ .func = func, .inst = inst } };976 return .{ .data = .{ .func = func, .inst = inst } };
987}977}
988978
...@@ -990,15 +980,10 @@ const FormatNavData = struct {...@@ -990,15 +980,10 @@ const FormatNavData = struct {
990 ip: *const InternPool,980 ip: *const InternPool,
991 nav_index: InternPool.Nav.Index,981 nav_index: InternPool.Nav.Index,
992};982};
993fn formatNav(983fn formatNav(data: FormatNavData, writer: *std.io.Writer) std.io.Writer.Error!void {
994 data: FormatNavData,984 try writer.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
995 comptime _: []const u8,985}
996 _: std.fmt.FormatOptions,986fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(FormatNavData, formatNav) {
997 writer: anytype,
998) @TypeOf(writer).Error!void {
999 try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1000}
1001fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {
1002 return .{ .data = .{987 return .{ .data = .{
1003 .ip = ip,988 .ip = ip,
1004 .nav_index = nav_index,989 .nav_index = nav_index,
...@@ -1009,31 +994,25 @@ const FormatAirData = struct {...@@ -1009,31 +994,25 @@ const FormatAirData = struct {
1009 func: *Func,994 func: *Func,
1010 inst: Air.Inst.Index,995 inst: Air.Inst.Index,
1011};996};
1012fn formatAir(997fn formatAir(data: FormatAirData, writer: *std.io.Writer) std.io.Writer.Error!void {
1013 data: FormatAirData,998 // Not acceptable implementation because it ignores `writer`:
1014 comptime _: []const u8,999 //data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness);
1015 _: std.fmt.FormatOptions,1000 _ = data;
1016 writer: anytype,1001 _ = writer;
1017) @TypeOf(writer).Error!void {1002 @panic("unimplemented");
1018 data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness);1003}
1019}1004fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(FormatAirData, formatAir) {
1020fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
1021 return .{ .data = .{ .func = func, .inst = inst } };1005 return .{ .data = .{ .func = func, .inst = inst } };
1022}1006}
10231007
1024const FormatTrackingData = struct {1008const FormatTrackingData = struct {
1025 func: *Func,1009 func: *Func,
1026};1010};
1027fn formatTracking(1011fn formatTracking(data: FormatTrackingData, writer: *std.io.Writer) std.io.Writer.Error!void {
1028 data: FormatTrackingData,
1029 comptime _: []const u8,
1030 _: std.fmt.FormatOptions,
1031 writer: anytype,
1032) @TypeOf(writer).Error!void {
1033 var it = data.func.inst_tracking.iterator();1012 var it = data.func.inst_tracking.iterator();
1034 while (it.next()) |entry| try writer.print("\n%{d} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });1013 while (it.next()) |entry| try writer.print("\n%{d} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });
1035}1014}
1036fn fmtTracking(func: *Func) std.fmt.Formatter(formatTracking) {1015fn fmtTracking(func: *Func) std.fmt.Formatter(FormatTrackingData, formatTracking) {
1037 return .{ .data = .{ .func = func } };1016 return .{ .data = .{ .func = func } };
1038}1017}
10391018
...@@ -1049,7 +1028,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -1049,7 +1028,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1049 .pseudo_dbg_epilogue_begin,1028 .pseudo_dbg_epilogue_begin,
1050 .pseudo_dead,1029 .pseudo_dead,
1051 => false,1030 => false,
1052 }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)});1031 }) wip_mir_log.debug("{f}", .{func.fmtWipMir(result_index)});
1053 return result_index;1032 return result_index;
1054}1033}
10551034
...@@ -1303,7 +1282,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -1303,7 +1282,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
1303 switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {1282 switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {
1304 .@"enum" => {1283 .@"enum" => {
1305 const enum_ty = Type.fromInterned(lazy_sym.ty);1284 const enum_ty = Type.fromInterned(lazy_sym.ty);
1306 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});1285 wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
13071286
1308 const param_regs = abi.Registers.Integer.function_arg_regs;1287 const param_regs = abi.Registers.Integer.function_arg_regs;
1309 const ret_reg = param_regs[0];1288 const ret_reg = param_regs[0];
...@@ -1385,7 +1364,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -1385,7 +1364,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
1385 });1364 });
1386 },1365 },
1387 else => return func.fail(1366 else => return func.fail(
1388 "TODO implement {s} for {}",1367 "TODO implement {s} for {f}",
1389 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },1368 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
1390 ),1369 ),
1391 }1370 }
...@@ -1399,8 +1378,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1399,8 +1378,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
13991378
1400 for (body) |inst| {1379 for (body) |inst| {
1401 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;1380 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;
1402 wip_mir_log.debug("{}", .{func.fmtAir(inst)});1381 wip_mir_log.debug("{f}", .{func.fmtAir(inst)});
1403 verbose_tracking_log.debug("{}", .{func.fmtTracking()});1382 verbose_tracking_log.debug("{f}", .{func.fmtTracking()});
14041383
1405 const old_air_bookkeeping = func.air_bookkeeping;1384 const old_air_bookkeeping = func.air_bookkeeping;
1406 try func.ensureProcessDeathCapacity(Air.Liveness.bpi);1385 try func.ensureProcessDeathCapacity(Air.Liveness.bpi);
...@@ -1679,18 +1658,18 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1679,18 +1658,18 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1679 var it = func.register_manager.free_registers.iterator(.{ .kind = .unset });1658 var it = func.register_manager.free_registers.iterator(.{ .kind = .unset });
1680 while (it.next()) |index| {1659 while (it.next()) |index| {
1681 const tracked_inst = func.register_manager.registers[index];1660 const tracked_inst = func.register_manager.registers[index];
1682 tracking_log.debug("tracked inst: {}", .{tracked_inst});1661 tracking_log.debug("tracked inst: {f}", .{tracked_inst});
1683 const tracking = func.getResolvedInstValue(tracked_inst);1662 const tracking = func.getResolvedInstValue(tracked_inst);
1684 for (tracking.getRegs()) |reg| {1663 for (tracking.getRegs()) |reg| {
1685 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;1664 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
1686 } else return std.debug.panic(1665 } else return std.debug.panic(
1687 \\%{} takes up these regs: {any}, however this regs {any}, don't use it1666 \\%{f} takes up these regs: {any}, however this regs {any}, don't use it
1688 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });1667 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });
1689 }1668 }
1690 }1669 }
1691 }1670 }
1692 }1671 }
1693 verbose_tracking_log.debug("{}", .{func.fmtTracking()});1672 verbose_tracking_log.debug("{f}", .{func.fmtTracking()});
1694}1673}
16951674
1696fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {1675fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {
...@@ -1713,7 +1692,7 @@ fn freeValue(func: *Func, value: MCValue) !void {...@@ -1713,7 +1692,7 @@ fn freeValue(func: *Func, value: MCValue) !void {
17131692
1714fn feed(func: *Func, bt: *Air.Liveness.BigTomb, operand: Air.Inst.Ref) !void {1693fn feed(func: *Func, bt: *Air.Liveness.BigTomb, operand: Air.Inst.Ref) !void {
1715 if (bt.feed()) if (operand.toIndex()) |inst| {1694 if (bt.feed()) if (operand.toIndex()) |inst| {
1716 log.debug("feed inst: %{}", .{inst});1695 log.debug("feed inst: %{f}", .{inst});
1717 try func.processDeath(inst);1696 try func.processDeath(inst);
1718 };1697 };
1719}1698}
...@@ -1843,7 +1822,7 @@ fn computeFrameLayout(func: *Func) !FrameLayout {...@@ -1843,7 +1822,7 @@ fn computeFrameLayout(func: *Func) !FrameLayout {
1843 total_alloc_size + 64 + args_frame_size + spill_frame_size + call_frame_size,1822 total_alloc_size + 64 + args_frame_size + spill_frame_size + call_frame_size,
1844 @intCast(frame_align[@intFromEnum(FrameIndex.base_ptr)].toByteUnits().?),1823 @intCast(frame_align[@intFromEnum(FrameIndex.base_ptr)].toByteUnits().?),
1845 );1824 );
1846 log.debug("frame size: {}", .{acc_frame_size});1825 log.debug("frame size: {d}", .{acc_frame_size});
18471826
1848 // store the ra at total_size - 8, so it's the very first thing in the stack1827 // store the ra at total_size - 8, so it's the very first thing in the stack
1849 // relative to the fp1828 // relative to the fp
...@@ -1907,7 +1886,7 @@ fn splitType(func: *Func, ty: Type) ![2]Type {...@@ -1907,7 +1886,7 @@ fn splitType(func: *Func, ty: Type) ![2]Type {
1907 else => return func.fail("TODO: splitType class {}", .{class}),1886 else => return func.fail("TODO: splitType class {}", .{class}),
1908 };1887 };
1909 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;1888 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;
1910 return func.fail("TODO implement splitType for {}", .{ty.fmt(func.pt)});1889 return func.fail("TODO implement splitType for {f}", .{ty.fmt(func.pt)});
1911}1890}
19121891
1913/// Truncates the value in the register in place.1892/// Truncates the value in the register in place.
...@@ -2020,7 +1999,7 @@ fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {...@@ -2020,7 +1999,7 @@ fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {
2020 const val_ty = ptr_ty.childType(zcu);1999 const val_ty = ptr_ty.childType(zcu);
2021 return func.allocFrameIndex(FrameAlloc.init(.{2000 return func.allocFrameIndex(FrameAlloc.init(.{
2022 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {2001 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
2023 return func.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(pt)});2002 return func.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(pt)});
2024 },2003 },
2025 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),2004 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
2026 }));2005 }));
...@@ -2160,7 +2139,7 @@ pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {...@@ -2160,7 +2139,7 @@ pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {
2160/// allocated. A second call to `copyToTmpRegister` may return the same register.2139/// allocated. A second call to `copyToTmpRegister` may return the same register.
2161/// This can have a side effect of spilling instructions to the stack to free up a register.2140/// This can have a side effect of spilling instructions to the stack to free up a register.
2162fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {2141fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {
2163 log.debug("copyToTmpRegister ty: {}", .{ty.fmt(func.pt)});2142 log.debug("copyToTmpRegister ty: {f}", .{ty.fmt(func.pt)});
2164 const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));2143 const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));
2165 try func.genSetReg(ty, reg, mcv);2144 try func.genSetReg(ty, reg, mcv);
2166 return reg;2145 return reg;
...@@ -2245,7 +2224,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -2245,7 +2224,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
2245 break :result null; // TODO2224 break :result null; // TODO
22462225
2247 break :result dst_mcv;2226 break :result dst_mcv;
2248 } orelse return func.fail("TODO: implement airIntCast from {} to {}", .{2227 } orelse return func.fail("TODO: implement airIntCast from {f} to {f}", .{
2249 src_ty.fmt(pt), dst_ty.fmt(pt),2228 src_ty.fmt(pt), dst_ty.fmt(pt),
2250 });2229 });
22512230
...@@ -2633,7 +2612,7 @@ fn genBinOp(...@@ -2633,7 +2612,7 @@ fn genBinOp(
2633 .add_sat,2612 .add_sat,
2634 => {2613 => {
2635 if (bit_size != 64 or !is_unsigned)2614 if (bit_size != 64 or !is_unsigned)
2636 return func.fail("TODO: genBinOp ty: {}", .{lhs_ty.fmt(pt)});2615 return func.fail("TODO: genBinOp ty: {f}", .{lhs_ty.fmt(pt)});
26372616
2638 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });2617 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
2639 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);2618 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
...@@ -4065,7 +4044,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {...@@ -4065,7 +4044,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
4065 );4044 );
4066 } else {4045 } else {
4067 return func.fail(4046 return func.fail(
4068 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {}, tag {}",4047 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {}, tag {f}",
4069 .{ frame_mcv, tag_ty.fmt(pt) },4048 .{ frame_mcv, tag_ty.fmt(pt) },
4070 );4049 );
4071 }4050 }
...@@ -4186,7 +4165,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -4186,7 +4165,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
41864165
4187 switch (scalar_ty.zigTypeTag(zcu)) {4166 switch (scalar_ty.zigTypeTag(zcu)) {
4188 .int => if (ty.zigTypeTag(zcu) == .vector) {4167 .int => if (ty.zigTypeTag(zcu) == .vector) {
4189 return func.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});4168 return func.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
4190 } else {4169 } else {
4191 const int_info = scalar_ty.intInfo(zcu);4170 const int_info = scalar_ty.intInfo(zcu);
4192 const int_bits = int_info.bits;4171 const int_bits = int_info.bits;
...@@ -4267,7 +4246,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -4267,7 +4246,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
42674246
4268 break :result return_mcv;4247 break :result return_mcv;
4269 },4248 },
4270 else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(pt)}),4249 else => return func.fail("TODO: implement airAbs {f}", .{scalar_ty.fmt(pt)}),
4271 }4250 }
42724251
4273 break :result .unreach;4252 break :result .unreach;
...@@ -4331,7 +4310,7 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {...@@ -4331,7 +4310,7 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {
43314310
4332 break :result dest_mcv;4311 break :result dest_mcv;
4333 },4312 },
4334 else => return func.fail("TODO: airByteSwap {}", .{ty.fmt(pt)}),4313 else => return func.fail("TODO: airByteSwap {f}", .{ty.fmt(pt)}),
4335 }4314 }
4336 };4315 };
4337 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });4316 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -4397,7 +4376,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -4397,7 +4376,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
4397 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),4376 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),
4398 }4377 }
4399 },4378 },
4400 else => return func.fail("TODO: airUnaryMath ty: {}", .{ty.fmt(pt)}),4379 else => return func.fail("TODO: airUnaryMath ty: {f}", .{ty.fmt(pt)}),
4401 }4380 }
44024381
4403 break :result MCValue{ .register = dst_reg };4382 break :result MCValue{ .register = dst_reg };
...@@ -4497,7 +4476,7 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro...@@ -4497,7 +4476,7 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
4497 const zcu = pt.zcu;4476 const zcu = pt.zcu;
4498 const dst_ty = ptr_ty.childType(zcu);4477 const dst_ty = ptr_ty.childType(zcu);
44994478
4500 log.debug("loading {}:{} into {}", .{ ptr_mcv, ptr_ty.fmt(pt), dst_mcv });4479 log.debug("loading {}:{f} into {}", .{ ptr_mcv, ptr_ty.fmt(pt), dst_mcv });
45014480
4502 switch (ptr_mcv) {4481 switch (ptr_mcv) {
4503 .none,4482 .none,
...@@ -4550,7 +4529,7 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -4550,7 +4529,7 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4550fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void {4529fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void {
4551 const zcu = func.pt.zcu;4530 const zcu = func.pt.zcu;
4552 const src_ty = ptr_ty.childType(zcu);4531 const src_ty = ptr_ty.childType(zcu);
4553 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });4532 log.debug("storing {}:{f} in {}:{f}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });
45544533
4555 switch (ptr_mcv) {4534 switch (ptr_mcv) {
4556 .none => unreachable,4535 .none => unreachable,
...@@ -7305,7 +7284,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -7305,7 +7284,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
7305 const bit_size = dst_ty.bitSize(zcu);7284 const bit_size = dst_ty.bitSize(zcu);
7306 if (abi_size * 8 <= bit_size) break :result dst_mcv;7285 if (abi_size * 8 <= bit_size) break :result dst_mcv;
73077286
7308 return func.fail("TODO: airBitCast {} to {}", .{ src_ty.fmt(pt), dst_ty.fmt(pt) });7287 return func.fail("TODO: airBitCast {f} to {f}", .{ src_ty.fmt(pt), dst_ty.fmt(pt) });
7309 };7288 };
7310 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });7289 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
7311}7290}
...@@ -8121,7 +8100,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {...@@ -8121,7 +8100,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {
8121 );8100 );
8122 break :result .{ .load_frame = .{ .index = frame_index } };8101 break :result .{ .load_frame = .{ .index = frame_index } };
8123 },8102 },
8124 else => return func.fail("TODO: airAggregate {}", .{result_ty.fmt(pt)}),8103 else => return func.fail("TODO: airAggregate {f}", .{result_ty.fmt(pt)}),
8125 }8104 }
8126 };8105 };
81278106
...@@ -8322,7 +8301,7 @@ fn resolveCallingConventionValues(...@@ -8322,7 +8301,7 @@ fn resolveCallingConventionValues(
8322 };8301 };
83238302
8324 result.return_value = switch (ret_tracking_i) {8303 result.return_value = switch (ret_tracking_i) {
8325 else => return func.fail("ty {} took {} tracking return indices", .{ ret_ty.fmt(pt), ret_tracking_i }),8304 else => return func.fail("ty {f} took {} tracking return indices", .{ ret_ty.fmt(pt), ret_tracking_i }),
8326 1 => ret_tracking[0],8305 1 => ret_tracking[0],
8327 2 => InstTracking.init(.{ .register_pair = .{8306 2 => InstTracking.init(.{ .register_pair = .{
8328 ret_tracking[0].short.register, ret_tracking[1].short.register,8307 ret_tracking[0].short.register, ret_tracking[1].short.register,
...@@ -8377,7 +8356,7 @@ fn resolveCallingConventionValues(...@@ -8377,7 +8356,7 @@ fn resolveCallingConventionValues(
8377 else => return func.fail("TODO: C calling convention arg class {}", .{class}),8356 else => return func.fail("TODO: C calling convention arg class {}", .{class}),
8378 } else {8357 } else {
8379 arg.* = switch (arg_mcv_i) {8358 arg.* = switch (arg_mcv_i) {
8380 else => return func.fail("ty {} took {} tracking arg indices", .{ ty.fmt(pt), arg_mcv_i }),8359 else => return func.fail("ty {f} took {} tracking arg indices", .{ ty.fmt(pt), arg_mcv_i }),
8381 1 => arg_mcv[0],8360 1 => arg_mcv[0],
8382 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },8361 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },
8383 };8362 };
src/arch/riscv64/Emit.zig+1-1
...@@ -172,7 +172,7 @@ const Reloc = struct {...@@ -172,7 +172,7 @@ const Reloc = struct {
172172
173fn fixupRelocs(emit: *Emit) Error!void {173fn fixupRelocs(emit: *Emit) Error!void {
174 for (emit.relocs.items) |reloc| {174 for (emit.relocs.items) |reloc| {
175 log.debug("target inst: {}", .{emit.lower.mir.instructions.get(reloc.target)});175 log.debug("target inst: {f}", .{emit.lower.mir.instructions.get(reloc.target)});
176 const target = emit.code_offset_mapping.get(reloc.target) orelse176 const target = emit.code_offset_mapping.get(reloc.target) orelse
177 return emit.fail("relocation target not found!", .{});177 return emit.fail("relocation target not found!", .{});
178178
src/arch/riscv64/Lower.zig+1-1
...@@ -61,7 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -61,7 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
61 defer lower.result_relocs_len = undefined;61 defer lower.result_relocs_len = undefined;
6262
63 const inst = lower.mir.instructions.get(index);63 const inst = lower.mir.instructions.get(index);
64 log.debug("lowerMir {}", .{inst});64 log.debug("lowerMir {f}", .{inst});
65 switch (inst.tag) {65 switch (inst.tag) {
66 else => try lower.generic(inst),66 else => try lower.generic(inst),
67 .pseudo_dbg_line_column,67 .pseudo_dbg_line_column,
src/arch/riscv64/Mir.zig+1-7
...@@ -92,13 +92,7 @@ pub const Inst = struct {...@@ -92,13 +92,7 @@ pub const Inst = struct {
92 },92 },
93 };93 };
9494
95 pub fn format(95 pub fn format(inst: Inst, writer: *std.io.Writer) std.io.Writer.Error!void {
96 inst: Inst,
97 comptime fmt: []const u8,
98 _: std.fmt.FormatOptions,
99 writer: anytype,
100 ) !void {
101 assert(fmt.len == 0);
102 try writer.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });96 try writer.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });
103 }97 }
104};98};
src/arch/riscv64/bits.zig-17
...@@ -255,23 +255,6 @@ pub const FrameIndex = enum(u32) {...@@ -255,23 +255,6 @@ pub const FrameIndex = enum(u32) {
255 pub fn isNamed(fi: FrameIndex) bool {255 pub fn isNamed(fi: FrameIndex) bool {
256 return @intFromEnum(fi) < named_count;256 return @intFromEnum(fi) < named_count;
257 }257 }
258
259 pub fn format(
260 fi: FrameIndex,
261 comptime fmt: []const u8,
262 options: std.fmt.FormatOptions,
263 writer: anytype,
264 ) @TypeOf(writer).Error!void {
265 try writer.writeAll("FrameIndex");
266 if (fi.isNamed()) {
267 try writer.writeByte('.');
268 try writer.writeAll(@tagName(fi));
269 } else {
270 try writer.writeByte('(');
271 try std.fmt.formatType(@intFromEnum(fi), fmt, options, writer, 0);
272 try writer.writeByte(')');
273 }
274 }
275};258};
276259
277/// A linker symbol not yet allocated in VM.260/// A linker symbol not yet allocated in VM.
src/arch/sparc64/CodeGen.zig+6-6
...@@ -723,7 +723,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -723,7 +723,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
723723
724 if (std.debug.runtime_safety) {724 if (std.debug.runtime_safety) {
725 if (self.air_bookkeeping < old_air_bookkeeping + 1) {725 if (self.air_bookkeeping < old_air_bookkeeping + 1) {
726 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });726 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{t}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });
727 }727 }
728 }728 }
729 }729 }
...@@ -1001,7 +1001,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {...@@ -1001,7 +1001,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {
1001 switch (self.args[arg_index]) {1001 switch (self.args[arg_index]) {
1002 .stack_offset => |off| {1002 .stack_offset => |off| {
1003 const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {1003 const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
1004 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});1004 return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(pt)});
1005 };1005 };
1006 const offset = off + abi_size;1006 const offset = off + abi_size;
1007 break :blk .{ .stack_offset = offset };1007 break :blk .{ .stack_offset = offset };
...@@ -2748,7 +2748,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -2748,7 +2748,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
2748 }2748 }
27492749
2750 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {2750 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
2751 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});2751 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
2752 };2752 };
2753 // TODO swap this for inst.ty.ptrAlign2753 // TODO swap this for inst.ty.ptrAlign
2754 const abi_align = elem_ty.abiAlignment(zcu);2754 const abi_align = elem_ty.abiAlignment(zcu);
...@@ -2760,7 +2760,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -2760,7 +2760,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
2760 const zcu = pt.zcu;2760 const zcu = pt.zcu;
2761 const elem_ty = self.typeOfIndex(inst);2761 const elem_ty = self.typeOfIndex(inst);
2762 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {2762 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
2763 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});2763 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
2764 };2764 };
2765 const abi_align = elem_ty.abiAlignment(zcu);2765 const abi_align = elem_ty.abiAlignment(zcu);
2766 self.stack_align = self.stack_align.max(abi_align);2766 self.stack_align = self.stack_align.max(abi_align);
...@@ -4111,7 +4111,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -4111,7 +4111,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
4111 while (true) {4111 while (true) {
4112 i -= 1;4112 i -= 1;
4113 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {4113 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {
4114 log.debug("getResolvedInstValue %{} => {}", .{ inst, mcv });4114 log.debug("getResolvedInstValue %{f} => {}", .{ inst, mcv });
4115 assert(mcv != .dead);4115 assert(mcv != .dead);
4116 return mcv;4116 return mcv;
4117 }4117 }
...@@ -4382,7 +4382,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -4382,7 +4382,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4382 const prev_value = self.getResolvedInstValue(inst);4382 const prev_value = self.getResolvedInstValue(inst);
4383 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4383 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
4384 branch.inst_table.putAssumeCapacity(inst, .dead);4384 branch.inst_table.putAssumeCapacity(inst, .dead);
4385 log.debug("%{} death: {} -> .dead", .{ inst, prev_value });4385 log.debug("%{f} death: {} -> .dead", .{ inst, prev_value });
4386 switch (prev_value) {4386 switch (prev_value) {
4387 .register => |reg| {4387 .register => |reg| {
4388 self.register_manager.freeReg(reg);4388 self.register_manager.freeReg(reg);
src/arch/wasm/CodeGen.zig+19-26
...@@ -1463,7 +1463,7 @@ fn allocStack(cg: *CodeGen, ty: Type) !WValue {...@@ -1463,7 +1463,7 @@ fn allocStack(cg: *CodeGen, ty: Type) !WValue {
1463 }1463 }
14641464
1465 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {1465 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
1466 return cg.fail("Type {} with ABI size of {d} exceeds stack frame size", .{1466 return cg.fail("Type {f} with ABI size of {d} exceeds stack frame size", .{
1467 ty.fmt(pt), ty.abiSize(zcu),1467 ty.fmt(pt), ty.abiSize(zcu),
1468 });1468 });
1469 };1469 };
...@@ -1497,7 +1497,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue {...@@ -1497,7 +1497,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue {
14971497
1498 const abi_alignment = ptr_ty.ptrAlignment(zcu);1498 const abi_alignment = ptr_ty.ptrAlignment(zcu);
1499 const abi_size = std.math.cast(u32, pointee_ty.abiSize(zcu)) orelse {1499 const abi_size = std.math.cast(u32, pointee_ty.abiSize(zcu)) orelse {
1500 return cg.fail("Type {} with ABI size of {d} exceeds stack frame size", .{1500 return cg.fail("Type {f} with ABI size of {d} exceeds stack frame size", .{
1501 pointee_ty.fmt(pt), pointee_ty.abiSize(zcu),1501 pointee_ty.fmt(pt), pointee_ty.abiSize(zcu),
1502 });1502 });
1503 };1503 };
...@@ -1959,7 +1959,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1959,7 +1959,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1959 .wasm_memory_size => cg.airWasmMemorySize(inst),1959 .wasm_memory_size => cg.airWasmMemorySize(inst),
1960 .wasm_memory_grow => cg.airWasmMemoryGrow(inst),1960 .wasm_memory_grow => cg.airWasmMemoryGrow(inst),
19611961
1962 .memcpy => cg.airMemcpy(inst),1962 .memcpy, .memmove => cg.airMemcpy(inst),
19631963
1964 .ret_addr => cg.airRetAddr(inst),1964 .ret_addr => cg.airRetAddr(inst),
1965 .tag_name => cg.airTagName(inst),1965 .tag_name => cg.airTagName(inst),
...@@ -1983,7 +1983,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1983,7 +1983,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1983 .c_va_copy,1983 .c_va_copy,
1984 .c_va_end,1984 .c_va_end,
1985 .c_va_start,1985 .c_va_start,
1986 .memmove,
1987 => |tag| return cg.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),1986 => |tag| return cg.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
19881987
1989 .atomic_load => cg.airAtomicLoad(inst),1988 .atomic_load => cg.airAtomicLoad(inst),
...@@ -2046,7 +2045,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2046,7 +2045,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2046 try cg.genInst(inst);2045 try cg.genInst(inst);
20472046
2048 if (std.debug.runtime_safety and cg.air_bookkeeping < old_bookkeeping_value + 1) {2047 if (std.debug.runtime_safety and cg.air_bookkeeping < old_bookkeeping_value + 1) {
2049 std.debug.panic("Missing call to `finishAir` in AIR instruction %{d} ('{}')", .{2048 std.debug.panic("Missing call to `finishAir` in AIR instruction %{d} ('{t}')", .{
2050 inst,2049 inst,
2051 cg.air.instructions.items(.tag)[@intFromEnum(inst)],2050 cg.air.instructions.items(.tag)[@intFromEnum(inst)],
2052 });2051 });
...@@ -2404,10 +2403,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr...@@ -2404,10 +2403,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
2404 try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) });2403 try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) });
2405 },2404 },
2406 else => if (abi_size > 8) {2405 else => if (abi_size > 8) {
2407 return cg.fail("TODO: `store` for type `{}` with abisize `{d}`", .{2406 return cg.fail("TODO: `store` for type `{f}` with abisize `{d}`", .{ ty.fmt(pt), abi_size });
2408 ty.fmt(pt),
2409 abi_size,
2410 });
2411 },2407 },
2412 }2408 }
2413 try cg.emitWValue(lhs);2409 try cg.emitWValue(lhs);
...@@ -2596,10 +2592,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV...@@ -2596,10 +2592,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV
2596 if (ty.zigTypeTag(zcu) == .int) {2592 if (ty.zigTypeTag(zcu) == .int) {
2597 return cg.binOpBigInt(lhs, rhs, ty, op);2593 return cg.binOpBigInt(lhs, rhs, ty, op);
2598 } else {2594 } else {
2599 return cg.fail(2595 return cg.fail("TODO: Implement binary operation for type: {f}", .{ty.fmt(pt)});
2600 "TODO: Implement binary operation for type: {}",
2601 .{ty.fmt(pt)},
2602 );
2603 }2596 }
2604 }2597 }
26052598
...@@ -2817,7 +2810,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2817,7 +2810,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28172810
2818 switch (scalar_ty.zigTypeTag(zcu)) {2811 switch (scalar_ty.zigTypeTag(zcu)) {
2819 .int => if (ty.zigTypeTag(zcu) == .vector) {2812 .int => if (ty.zigTypeTag(zcu) == .vector) {
2820 return cg.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});2813 return cg.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
2821 } else {2814 } else {
2822 const int_bits = ty.intInfo(zcu).bits;2815 const int_bits = ty.intInfo(zcu).bits;
2823 const wasm_bits = toWasmBits(int_bits) orelse {2816 const wasm_bits = toWasmBits(int_bits) orelse {
...@@ -3244,7 +3237,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3244,7 +3237,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3244 return .{ .imm32 = @intFromBool(!val.isNull(zcu)) };3237 return .{ .imm32 = @intFromBool(!val.isNull(zcu)) };
3245 },3238 },
3246 .aggregate => switch (ip.indexToKey(ty.ip_index)) {3239 .aggregate => switch (ip.indexToKey(ty.ip_index)) {
3247 .array_type => return cg.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(pt)}),3240 .array_type => return cg.fail("Wasm TODO: LowerConstant for {f}", .{ty.fmt(pt)}),
3248 .vector_type => {3241 .vector_type => {
3249 assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct);3242 assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct);
3250 var buf: [16]u8 = undefined;3243 var buf: [16]u8 = undefined;
...@@ -3332,7 +3325,7 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue {...@@ -3332,7 +3325,7 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue {
3332 },3325 },
3333 else => unreachable,3326 else => unreachable,
3334 },3327 },
3335 else => return cg.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag(zcu)}),3328 else => return cg.fail("Wasm TODO: emitUndefined for type: {t}\n", .{ty.zigTypeTag(zcu)}),
3336 }3329 }
3337}3330}
33383331
...@@ -3608,7 +3601,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3608,7 +3601,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3608 } else {3601 } else {
3609 const int_info = operand_ty.intInfo(zcu);3602 const int_info = operand_ty.intInfo(zcu);
3610 const wasm_bits = toWasmBits(int_info.bits) orelse {3603 const wasm_bits = toWasmBits(int_info.bits) orelse {
3611 return cg.fail("TODO: Implement binary NOT for {}", .{operand_ty.fmt(pt)});3604 return cg.fail("TODO: Implement binary NOT for {f}", .{operand_ty.fmt(pt)});
3612 };3605 };
36133606
3614 switch (wasm_bits) {3607 switch (wasm_bits) {
...@@ -3874,7 +3867,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3874,7 +3867,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3874 },3867 },
3875 else => result: {3868 else => result: {
3876 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse {3869 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse {
3877 return cg.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(pt)});3870 return cg.fail("Field type '{f}' too big to fit into stack frame", .{field_ty.fmt(pt)});
3878 };3871 };
3879 if (isByRef(field_ty, zcu, cg.target)) {3872 if (isByRef(field_ty, zcu, cg.target)) {
3880 switch (operand) {3873 switch (operand) {
...@@ -4360,7 +4353,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc...@@ -4360,7 +4353,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc
4360 // a pointer to the stack value4353 // a pointer to the stack value
4361 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {4354 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
4362 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {4355 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
4363 return cg.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(pt)});4356 return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)});
4364 };4357 };
4365 try cg.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });4358 try cg.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });
4366 }4359 }
...@@ -4430,7 +4423,7 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void...@@ -4430,7 +4423,7 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void
4430 }4423 }
44314424
4432 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {4425 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
4433 return cg.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(pt)});4426 return cg.fail("Optional type {f} too big to fit into stack frame", .{opt_ty.fmt(pt)});
4434 };4427 };
44354428
4436 try cg.emitWValue(operand);4429 try cg.emitWValue(operand);
...@@ -4462,7 +4455,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4462,7 +4455,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4462 break :result cg.reuseOperand(ty_op.operand, operand);4455 break :result cg.reuseOperand(ty_op.operand, operand);
4463 }4456 }
4464 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {4457 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
4465 return cg.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(pt)});4458 return cg.fail("Optional type {f} too big to fit into stack frame", .{op_ty.fmt(pt)});
4466 };4459 };
44674460
4468 // Create optional type, set the non-null bit, and store the operand inside the optional type4461 // Create optional type, set the non-null bit, and store the operand inside the optional type
...@@ -6196,7 +6189,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6196,7 +6189,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6196 _ = try cg.load(overflow_ret, Type.i32, 0);6189 _ = try cg.load(overflow_ret, Type.i32, 0);
6197 try cg.addLocal(.local_set, overflow_bit.local.value);6190 try cg.addLocal(.local_set, overflow_bit.local.value);
6198 break :blk res;6191 break :blk res;
6199 } else return cg.fail("TODO: @mulWithOverflow for {}", .{ty.fmt(pt)});6192 } else return cg.fail("TODO: @mulWithOverflow for {f}", .{ty.fmt(pt)});
6200 var bin_op_local = try mul.toLocal(cg, ty);6193 var bin_op_local = try mul.toLocal(cg, ty);
6201 defer bin_op_local.free(cg);6194 defer bin_op_local.free(cg);
62026195
...@@ -6749,7 +6742,7 @@ fn airMod(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6749,7 +6742,7 @@ fn airMod(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6749 const add = try cg.binOp(rem, rhs, ty, .add);6742 const add = try cg.binOp(rem, rhs, ty, .add);
6750 break :result try cg.binOp(add, rhs, ty, .rem);6743 break :result try cg.binOp(add, rhs, ty, .rem);
6751 }6744 }
6752 return cg.fail("TODO: @mod for {}", .{ty.fmt(pt)});6745 return cg.fail("TODO: @mod for {f}", .{ty.fmt(pt)});
6753 };6746 };
67546747
6755 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });6748 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
...@@ -6767,7 +6760,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6767,7 +6760,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6767 const lhs = try cg.resolveInst(bin_op.lhs);6760 const lhs = try cg.resolveInst(bin_op.lhs);
6768 const rhs = try cg.resolveInst(bin_op.rhs);6761 const rhs = try cg.resolveInst(bin_op.rhs);
6769 const wasm_bits = toWasmBits(int_info.bits) orelse {6762 const wasm_bits = toWasmBits(int_info.bits) orelse {
6770 return cg.fail("TODO: mul_sat for {}", .{ty.fmt(pt)});6763 return cg.fail("TODO: mul_sat for {f}", .{ty.fmt(pt)});
6771 };6764 };
67726765
6773 switch (wasm_bits) {6766 switch (wasm_bits) {
...@@ -6804,7 +6797,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6804,7 +6797,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6804 },6797 },
6805 64 => {6798 64 => {
6806 if (!(int_info.bits == 64 and int_info.signedness == .signed)) {6799 if (!(int_info.bits == 64 and int_info.signedness == .signed)) {
6807 return cg.fail("TODO: mul_sat for {}", .{ty.fmt(pt)});6800 return cg.fail("TODO: mul_sat for {f}", .{ty.fmt(pt)});
6808 }6801 }
6809 const overflow_ret = try cg.allocStack(Type.i32);6802 const overflow_ret = try cg.allocStack(Type.i32);
6810 _ = try cg.callIntrinsic(6803 _ = try cg.callIntrinsic(
...@@ -6822,7 +6815,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6822,7 +6815,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6822 },6815 },
6823 128 => {6816 128 => {
6824 if (!(int_info.bits == 128 and int_info.signedness == .signed)) {6817 if (!(int_info.bits == 128 and int_info.signedness == .signed)) {
6825 return cg.fail("TODO: mul_sat for {}", .{ty.fmt(pt)});6818 return cg.fail("TODO: mul_sat for {f}", .{ty.fmt(pt)});
6826 }6819 }
6827 const overflow_ret = try cg.allocStack(Type.i32);6820 const overflow_ret = try cg.allocStack(Type.i32);
6828 const ret = try cg.callIntrinsic(6821 const ret = try cg.callIntrinsic(
src/arch/x86_64/CodeGen.zig+226-256
...@@ -6,6 +6,7 @@ const log = std.log.scoped(.codegen);...@@ -6,6 +6,7 @@ const log = std.log.scoped(.codegen);
6const tracking_log = std.log.scoped(.tracking);6const tracking_log = std.log.scoped(.tracking);
7const verbose_tracking_log = std.log.scoped(.verbose_tracking);7const verbose_tracking_log = std.log.scoped(.verbose_tracking);
8const wip_mir_log = std.log.scoped(.wip_mir);8const wip_mir_log = std.log.scoped(.wip_mir);
9const Writer = std.io.Writer;
910
10const Air = @import("../../Air.zig");11const Air = @import("../../Air.zig");
11const Allocator = std.mem.Allocator;12const Allocator = std.mem.Allocator;
...@@ -524,52 +525,47 @@ pub const MCValue = union(enum) {...@@ -524,52 +525,47 @@ pub const MCValue = union(enum) {
524 };525 };
525 }526 }
526527
527 pub fn format(528 pub fn format(mcv: MCValue, w: *Writer) Writer.Error!void {
528 mcv: MCValue,
529 comptime _: []const u8,
530 _: std.fmt.FormatOptions,
531 writer: anytype,
532 ) @TypeOf(writer).Error!void {
533 switch (mcv) {529 switch (mcv) {
534 .none, .unreach, .dead, .undef => try writer.print("({s})", .{@tagName(mcv)}),530 .none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}),
535 .immediate => |pl| try writer.print("0x{x}", .{pl}),531 .immediate => |pl| try w.print("0x{x}", .{pl}),
536 .memory => |pl| try writer.print("[ds:0x{x}]", .{pl}),532 .memory => |pl| try w.print("[ds:0x{x}]", .{pl}),
537 inline .eflags, .register => |pl| try writer.print("{s}", .{@tagName(pl)}),533 inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}),
538 .register_pair => |pl| try writer.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),534 .register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
539 .register_triple => |pl| try writer.print("{s}:{s}:{s}", .{535 .register_triple => |pl| try w.print("{s}:{s}:{s}", .{
540 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),536 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
541 }),537 }),
542 .register_quadruple => |pl| try writer.print("{s}:{s}:{s}:{s}", .{538 .register_quadruple => |pl| try w.print("{s}:{s}:{s}:{s}", .{
543 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),539 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
544 }),540 }),
545 .register_offset => |pl| try writer.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),541 .register_offset => |pl| try w.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),
546 .register_overflow => |pl| try writer.print("{s}:{s}", .{542 .register_overflow => |pl| try w.print("{s}:{s}", .{
547 @tagName(pl.eflags),543 @tagName(pl.eflags),
548 @tagName(pl.reg),544 @tagName(pl.reg),
549 }),545 }),
550 .register_mask => |pl| try writer.print("mask({s},{}):{c}{s}", .{546 .register_mask => |pl| try w.print("mask({s},{f}):{c}{s}", .{
551 @tagName(pl.info.kind),547 @tagName(pl.info.kind),
552 pl.info.scalar,548 pl.info.scalar,
553 @as(u8, if (pl.info.inverted) '!' else ' '),549 @as(u8, if (pl.info.inverted) '!' else ' '),
554 @tagName(pl.reg),550 @tagName(pl.reg),
555 }),551 }),
556 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),552 .indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
557 .indirect_load_frame => |pl| try writer.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }),553 .indirect_load_frame => |pl| try w.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }),
558 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),554 .load_frame => |pl| try w.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
559 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),555 .lea_frame => |pl| try w.print("{} + 0x{x}", .{ pl.index, pl.off }),
560 .load_nav => |pl| try writer.print("[nav:{d}]", .{@intFromEnum(pl)}),556 .load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}),
561 .lea_nav => |pl| try writer.print("nav:{d}", .{@intFromEnum(pl)}),557 .lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}),
562 .load_uav => |pl| try writer.print("[uav:{d}]", .{@intFromEnum(pl.val)}),558 .load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
563 .lea_uav => |pl| try writer.print("uav:{d}", .{@intFromEnum(pl.val)}),559 .lea_uav => |pl| try w.print("uav:{d}", .{@intFromEnum(pl.val)}),
564 .load_lazy_sym => |pl| try writer.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),560 .load_lazy_sym => |pl| try w.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
565 .lea_lazy_sym => |pl| try writer.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),561 .lea_lazy_sym => |pl| try w.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
566 .load_extern_func => |pl| try writer.print("[extern:{d}]", .{@intFromEnum(pl)}),562 .load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}),
567 .lea_extern_func => |pl| try writer.print("extern:{d}", .{@intFromEnum(pl)}),563 .lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}),
568 .elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{564 .elementwise_args => |pl| try w.print("elementwise:{d}:[{} + 0x{x}]", .{
569 pl.regs, pl.frame_index, pl.frame_off,565 pl.regs, pl.frame_index, pl.frame_off,
570 }),566 }),
571 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),567 .reserved_frame => |pl| try w.print("(dead:{})", .{pl}),
572 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),568 .air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}),
573 }569 }
574 }570 }
575};571};
...@@ -639,7 +635,7 @@ const InstTracking = struct {...@@ -639,7 +635,7 @@ const InstTracking = struct {
639 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },635 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },
640 else => unreachable,636 else => unreachable,
641 }637 }
642 tracking_log.debug("spill {} from {} to {}", .{ inst, self.short, self.long });638 tracking_log.debug("spill {f} from {f} to {f}", .{ inst, self.short, self.long });
643 try cg.genCopy(cg.typeOfIndex(inst), self.long, self.short, .{});639 try cg.genCopy(cg.typeOfIndex(inst), self.long, self.short, .{});
644 for (self.short.getRegs()) |reg| if (reg.isClass(.x87)) try cg.asmRegister(.{ .f_, .free }, reg);640 for (self.short.getRegs()) |reg| if (reg.isClass(.x87)) try cg.asmRegister(.{ .f_, .free }, reg);
645 }641 }
...@@ -672,7 +668,7 @@ const InstTracking = struct {...@@ -672,7 +668,7 @@ const InstTracking = struct {
672 else => {}, // TODO process stack allocation death668 else => {}, // TODO process stack allocation death
673 }669 }
674 self.reuseFrame();670 self.reuseFrame();
675 tracking_log.debug("{} => {} (spilled)", .{ inst, self.* });671 tracking_log.debug("{f} => {f} (spilled)", .{ inst, self.* });
676 }672 }
677673
678 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {674 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {
...@@ -749,7 +745,7 @@ const InstTracking = struct {...@@ -749,7 +745,7 @@ const InstTracking = struct {
749 else => target.long,745 else => target.long,
750 } else target.long;746 } else target.long;
751 self.short = target.short;747 self.short = target.short;
752 tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });748 tracking_log.debug("{f} => {f} (materialize)", .{ inst, self.* });
753 }749 }
754750
755 fn resurrect(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index, scope_generation: u32) !void {751 fn resurrect(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index, scope_generation: u32) !void {
...@@ -757,7 +753,7 @@ const InstTracking = struct {...@@ -757,7 +753,7 @@ const InstTracking = struct {
757 .dead => |die_generation| if (die_generation >= scope_generation) {753 .dead => |die_generation| if (die_generation >= scope_generation) {
758 self.reuseFrame();754 self.reuseFrame();
759 try function.getValue(self.short, inst);755 try function.getValue(self.short, inst);
760 tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });756 tracking_log.debug("{f} => {f} (resurrect)", .{ inst, self.* });
761 },757 },
762 else => {},758 else => {},
763 }759 }
...@@ -768,7 +764,7 @@ const InstTracking = struct {...@@ -768,7 +764,7 @@ const InstTracking = struct {
768 try function.freeValue(self.short, opts);764 try function.freeValue(self.short, opts);
769 if (self.long == .none) self.long = self.short;765 if (self.long == .none) self.long = self.short;
770 self.short = .{ .dead = function.scope_generation };766 self.short = .{ .dead = function.scope_generation };
771 tracking_log.debug("{} => {} (death)", .{ inst, self.* });767 tracking_log.debug("{f} => {f} (death)", .{ inst, self.* });
772 }768 }
773769
774 fn reuse(770 fn reuse(
...@@ -778,13 +774,13 @@ const InstTracking = struct {...@@ -778,13 +774,13 @@ const InstTracking = struct {
778 old_inst: Air.Inst.Index,774 old_inst: Air.Inst.Index,
779 ) void {775 ) void {
780 self.short = .{ .dead = function.scope_generation };776 self.short = .{ .dead = function.scope_generation };
781 tracking_log.debug("{?} => {} (reuse {})", .{ new_inst, self.*, old_inst });777 tracking_log.debug("{?f} => {f} (reuse {f})", .{ new_inst, self.*, old_inst });
782 }778 }
783779
784 fn liveOut(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) void {780 fn liveOut(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) void {
785 for (self.getRegs()) |reg| {781 for (self.getRegs()) |reg| {
786 if (function.register_manager.isRegFree(reg)) {782 if (function.register_manager.isRegFree(reg)) {
787 tracking_log.debug("{} => {} (live-out)", .{ inst, self.* });783 tracking_log.debug("{f} => {f} (live-out)", .{ inst, self.* });
788 continue;784 continue;
789 }785 }
790786
...@@ -812,18 +808,13 @@ const InstTracking = struct {...@@ -812,18 +808,13 @@ const InstTracking = struct {
812 // Perform side-effects of freeValue manually.808 // Perform side-effects of freeValue manually.
813 function.register_manager.freeReg(reg);809 function.register_manager.freeReg(reg);
814810
815 tracking_log.debug("{} => {} (live-out {})", .{ inst, self.*, tracked_inst });811 tracking_log.debug("{f} => {f} (live-out {f})", .{ inst, self.*, tracked_inst });
816 }812 }
817 }813 }
818814
819 pub fn format(815 pub fn format(tracking: InstTracking, bw: *Writer) Writer.Error!void {
820 tracking: InstTracking,816 if (!std.meta.eql(tracking.long, tracking.short)) try bw.print("|{f}| ", .{tracking.long});
821 comptime _: []const u8,817 try bw.print("{f}", .{tracking.short});
822 _: std.fmt.FormatOptions,
823 writer: anytype,
824 ) @TypeOf(writer).Error!void {
825 if (!std.meta.eql(tracking.long, tracking.short)) try writer.print("|{}| ", .{tracking.long});
826 try writer.print("{}", .{tracking.short});
827 }818 }
828};819};
829820
...@@ -939,7 +930,7 @@ pub fn generate(...@@ -939,7 +930,7 @@ pub fn generate(
939 function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), .init(.none));930 function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), .init(.none));
940 }931 }
941932
942 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});933 wip_mir_log.debug("{f}:", .{fmtNav(func.owner_nav, ip)});
943934
944 try function.frame_allocs.resize(gpa, FrameIndex.named_count);935 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
945 function.frame_allocs.set(936 function.frame_allocs.set(
...@@ -1097,15 +1088,10 @@ const FormatNavData = struct {...@@ -1097,15 +1088,10 @@ const FormatNavData = struct {
1097 ip: *const InternPool,1088 ip: *const InternPool,
1098 nav_index: InternPool.Nav.Index,1089 nav_index: InternPool.Nav.Index,
1099};1090};
1100fn formatNav(1091fn formatNav(data: FormatNavData, w: *Writer) Writer.Error!void {
1101 data: FormatNavData,1092 try w.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1102 comptime _: []const u8,
1103 _: std.fmt.FormatOptions,
1104 writer: anytype,
1105) @TypeOf(writer).Error!void {
1106 try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1107}1093}
1108fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {1094fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(FormatNavData, formatNav) {
1109 return .{ .data = .{1095 return .{ .data = .{
1110 .ip = ip,1096 .ip = ip,
1111 .nav_index = nav_index,1097 .nav_index = nav_index,
...@@ -1116,15 +1102,14 @@ const FormatAirData = struct {...@@ -1116,15 +1102,14 @@ const FormatAirData = struct {
1116 self: *CodeGen,1102 self: *CodeGen,
1117 inst: Air.Inst.Index,1103 inst: Air.Inst.Index,
1118};1104};
1119fn formatAir(1105fn formatAir(data: FormatAirData, w: *std.io.Writer) Writer.Error!void {
1120 data: FormatAirData,1106 // not acceptable implementation because it ignores `w`:
1121 comptime _: []const u8,1107 //data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness);
1122 _: std.fmt.FormatOptions,1108 _ = data;
1123 writer: anytype,1109 _ = w;
1124) @TypeOf(writer).Error!void {1110 @panic("TODO: unimplemented");
1125 data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness);
1126}1111}
1127fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {1112fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(FormatAirData, formatAir) {
1128 return .{ .data = .{ .self = self, .inst = inst } };1113 return .{ .data = .{ .self = self, .inst = inst } };
1129}1114}
11301115
...@@ -1132,12 +1117,7 @@ const FormatWipMirData = struct {...@@ -1132,12 +1117,7 @@ const FormatWipMirData = struct {
1132 self: *CodeGen,1117 self: *CodeGen,
1133 inst: Mir.Inst.Index,1118 inst: Mir.Inst.Index,
1134};1119};
1135fn formatWipMir(1120fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
1136 data: FormatWipMirData,
1137 comptime _: []const u8,
1138 _: std.fmt.FormatOptions,
1139 writer: anytype,
1140) @TypeOf(writer).Error!void {
1141 var lower: Lower = .{1121 var lower: Lower = .{
1142 .target = data.self.target,1122 .target = data.self.target,
1143 .allocator = data.self.gpa,1123 .allocator = data.self.gpa,
...@@ -1152,27 +1132,22 @@ fn formatWipMir(...@@ -1152,27 +1132,22 @@ fn formatWipMir(
1152 lower.err_msg.?.deinit(data.self.gpa);1132 lower.err_msg.?.deinit(data.self.gpa);
1153 lower.err_msg = null;1133 lower.err_msg = null;
1154 }1134 }
1155 try writer.writeAll(lower.err_msg.?.msg);1135 try w.writeAll(lower.err_msg.?.msg);
1156 return;1136 return;
1157 },1137 },
1158 error.OutOfMemory, error.InvalidInstruction, error.CannotEncode => |e| {1138 else => |e| {
1159 try writer.writeAll(switch (e) {1139 try w.writeAll(@errorName(e));
1160 error.OutOfMemory => "Out of memory",
1161 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
1162 error.CannotEncode => "CodeGen failed to encode the instruction.",
1163 });
1164 return;1140 return;
1165 },1141 },
1166 else => |e| return e,
1167 }).insts) |lowered_inst| {1142 }).insts) |lowered_inst| {
1168 if (!first) try writer.writeAll("\ndebug(wip_mir): ");1143 if (!first) try w.writeAll("\ndebug(wip_mir): ");
1169 try writer.print(" | {}", .{lowered_inst});1144 try w.print(" | {f}", .{lowered_inst});
1170 first = false;1145 first = false;
1171 }1146 }
1172 if (first) {1147 if (first) {
1173 const ip = &data.self.pt.zcu.intern_pool;1148 const ip = &data.self.pt.zcu.intern_pool;
1174 const mir_inst = lower.mir.instructions.get(data.inst);1149 const mir_inst = lower.mir.instructions.get(data.inst);
1175 try writer.print(" | .{s}", .{@tagName(mir_inst.ops)});1150 try w.print(" | .{s}", .{@tagName(mir_inst.ops)});
1176 switch (mir_inst.ops) {1151 switch (mir_inst.ops) {
1177 else => unreachable,1152 else => unreachable,
1178 .pseudo_dbg_prologue_end_none,1153 .pseudo_dbg_prologue_end_none,
...@@ -1184,20 +1159,20 @@ fn formatWipMir(...@@ -1184,20 +1159,20 @@ fn formatWipMir(
1184 .pseudo_dbg_var_none,1159 .pseudo_dbg_var_none,
1185 .pseudo_dead_none,1160 .pseudo_dead_none,
1186 => {},1161 => {},
1187 .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print(1162 .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try w.print(
1188 " {[line]d}, {[column]d}",1163 " {[line]d}, {[column]d}",
1189 mir_inst.data.line_column,1164 mir_inst.data.line_column,
1190 ),1165 ),
1191 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{1166 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try w.print(" {f}", .{
1192 ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip),1167 ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip),
1193 }),1168 }),
1194 .pseudo_dbg_arg_i_s, .pseudo_dbg_var_i_s => try writer.print(" {d}", .{1169 .pseudo_dbg_arg_i_s, .pseudo_dbg_var_i_s => try w.print(" {d}", .{
1195 @as(i32, @bitCast(mir_inst.data.i.i)),1170 @as(i32, @bitCast(mir_inst.data.i.i)),
1196 }),1171 }),
1197 .pseudo_dbg_arg_i_u, .pseudo_dbg_var_i_u => try writer.print(" {d}", .{1172 .pseudo_dbg_arg_i_u, .pseudo_dbg_var_i_u => try w.print(" {d}", .{
1198 mir_inst.data.i.i,1173 mir_inst.data.i.i,
1199 }),1174 }),
1200 .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => try writer.print(" {d}", .{1175 .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => try w.print(" {d}", .{
1201 mir_inst.data.i64,1176 mir_inst.data.i64,
1202 }),1177 }),
1203 .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => {1178 .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => {
...@@ -1205,44 +1180,39 @@ fn formatWipMir(...@@ -1205,44 +1180,39 @@ fn formatWipMir(
1205 .base = .{ .reg = mir_inst.data.ro.reg },1180 .base = .{ .reg = mir_inst.data.ro.reg },
1206 .disp = mir_inst.data.ro.off,1181 .disp = mir_inst.data.ro.off,
1207 }) };1182 }) };
1208 try writer.print(" {}", .{mem_op.fmt(.m)});1183 try w.print(" {f}", .{mem_op.fmt(.m)});
1209 },1184 },
1210 .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {1185 .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {
1211 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{1186 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
1212 .base = .{ .frame = mir_inst.data.fa.index },1187 .base = .{ .frame = mir_inst.data.fa.index },
1213 .disp = mir_inst.data.fa.off,1188 .disp = mir_inst.data.fa.off,
1214 }) };1189 }) };
1215 try writer.print(" {}", .{mem_op.fmt(.m)});1190 try w.print(" {f}", .{mem_op.fmt(.m)});
1216 },1191 },
1217 .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {1192 .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
1218 const mem_op: encoder.Instruction.Operand = .{1193 const mem_op: encoder.Instruction.Operand = .{
1219 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.x.payload).data.decode(),1194 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.x.payload).data.decode(),
1220 };1195 };
1221 try writer.print(" {}", .{mem_op.fmt(.m)});1196 try w.print(" {f}", .{mem_op.fmt(.m)});
1222 },1197 },
1223 .pseudo_dbg_arg_val, .pseudo_dbg_var_val => try writer.print(" {}", .{1198 .pseudo_dbg_arg_val, .pseudo_dbg_var_val => try w.print(" {f}", .{
1224 Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),1199 Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),
1225 }),1200 }),
1226 }1201 }
1227 }1202 }
1228}1203}
1229fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) {1204fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(FormatWipMirData, formatWipMir) {
1230 return .{ .data = .{ .self = self, .inst = inst } };1205 return .{ .data = .{ .self = self, .inst = inst } };
1231}1206}
12321207
1233const FormatTrackingData = struct {1208const FormatTrackingData = struct {
1234 self: *CodeGen,1209 self: *CodeGen,
1235};1210};
1236fn formatTracking(1211fn formatTracking(data: FormatTrackingData, w: *Writer) Writer.Error!void {
1237 data: FormatTrackingData,
1238 comptime _: []const u8,
1239 _: std.fmt.FormatOptions,
1240 writer: anytype,
1241) @TypeOf(writer).Error!void {
1242 var it = data.self.inst_tracking.iterator();1212 var it = data.self.inst_tracking.iterator();
1243 while (it.next()) |entry| try writer.print("\n{} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });1213 while (it.next()) |entry| try w.print("\n{f} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });
1244}1214}
1245fn fmtTracking(self: *CodeGen) std.fmt.Formatter(formatTracking) {1215fn fmtTracking(self: *CodeGen) std.fmt.Formatter(FormatTrackingData, formatTracking) {
1246 return .{ .data = .{ .self = self } };1216 return .{ .data = .{ .self = self } };
1247}1217}
12481218
...@@ -1251,7 +1221,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -1251,7 +1221,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1251 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);1221 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
1252 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);1222 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);
1253 self.mir_instructions.appendAssumeCapacity(inst);1223 self.mir_instructions.appendAssumeCapacity(inst);
1254 if (inst.ops != .pseudo_dead_none) wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});1224 if (inst.ops != .pseudo_dead_none) wip_mir_log.debug("{f}", .{self.fmtWipMir(result_index)});
1255 return result_index;1225 return result_index;
1256}1226}
12571227
...@@ -2056,7 +2026,7 @@ fn gen(...@@ -2056,7 +2026,7 @@ fn gen(
2056 .{},2026 .{},
2057 );2027 );
2058 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };2028 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
2059 tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index });2029 tracking_log.debug("spill {f} to {}", .{ self.ret_mcv.long, frame_index });
2060 },2030 },
2061 else => unreachable,2031 else => unreachable,
2062 }2032 }
...@@ -2334,8 +2304,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2334,8 +2304,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
23342304
2335 for (body) |inst| {2305 for (body) |inst| {
2336 if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue;2306 if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue;
2337 wip_mir_log.debug("{}", .{cg.fmtAir(inst)});2307 wip_mir_log.debug("{f}", .{cg.fmtAir(inst)});
2338 verbose_tracking_log.debug("{}", .{cg.fmtTracking()});2308 verbose_tracking_log.debug("{f}", .{cg.fmtTracking()});
23392309
2340 cg.reused_operands = .initEmpty();2310 cg.reused_operands = .initEmpty();
2341 try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);2311 try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);
...@@ -4339,7 +4309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -4339,7 +4309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4339 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },4309 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
4340 } },4310 } },
4341 } }) catch |err| switch (err) {4311 } }) catch |err| switch (err) {
4342 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{4312 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
4343 @tagName(air_tag),4313 @tagName(air_tag),
4344 cg.typeOf(bin_op.lhs).fmt(pt),4314 cg.typeOf(bin_op.lhs).fmt(pt),
4345 ops[0].tracking(cg),4315 ops[0].tracking(cg),
...@@ -4351,7 +4321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -4351,7 +4321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4351 else => unreachable,4321 else => unreachable,
4352 .add, .add_optimized => {},4322 .add, .add_optimized => {},
4353 .add_wrap => res[0].wrapInt(cg) catch |err| switch (err) {4323 .add_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
4354 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{4324 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
4355 @tagName(air_tag),4325 @tagName(air_tag),
4356 cg.typeOf(bin_op.lhs).fmt(pt),4326 cg.typeOf(bin_op.lhs).fmt(pt),
4357 res[0].tracking(cg),4327 res[0].tracking(cg),
...@@ -12917,7 +12887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -12917,7 +12887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
12917 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },12887 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
12918 } },12888 } },
12919 } }) catch |err| switch (err) {12889 } }) catch |err| switch (err) {
12920 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{12890 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
12921 @tagName(air_tag),12891 @tagName(air_tag),
12922 cg.typeOf(bin_op.lhs).fmt(pt),12892 cg.typeOf(bin_op.lhs).fmt(pt),
12923 ops[0].tracking(cg),12893 ops[0].tracking(cg),
...@@ -14947,7 +14917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -14947,7 +14917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
14947 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },14917 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
14948 } },14918 } },
14949 } }) catch |err| switch (err) {14919 } }) catch |err| switch (err) {
14950 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{14920 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
14951 @tagName(air_tag),14921 @tagName(air_tag),
14952 cg.typeOf(bin_op.lhs).fmt(pt),14922 cg.typeOf(bin_op.lhs).fmt(pt),
14953 ops[0].tracking(cg),14923 ops[0].tracking(cg),
...@@ -14959,7 +14929,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -14959,7 +14929,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
14959 else => unreachable,14929 else => unreachable,
14960 .sub, .sub_optimized => {},14930 .sub, .sub_optimized => {},
14961 .sub_wrap => res[0].wrapInt(cg) catch |err| switch (err) {14931 .sub_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
14962 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{14932 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
14963 @tagName(air_tag),14933 @tagName(air_tag),
14964 cg.typeOf(bin_op.lhs).fmt(pt),14934 cg.typeOf(bin_op.lhs).fmt(pt),
14965 res[0].tracking(cg),14935 res[0].tracking(cg),
...@@ -21794,7 +21764,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -21794,7 +21764,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
21794 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },21764 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
21795 } },21765 } },
21796 } }) catch |err| switch (err) {21766 } }) catch |err| switch (err) {
21797 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{21767 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
21798 @tagName(air_tag),21768 @tagName(air_tag),
21799 cg.typeOf(bin_op.lhs).fmt(pt),21769 cg.typeOf(bin_op.lhs).fmt(pt),
21800 ops[0].tracking(cg),21770 ops[0].tracking(cg),
...@@ -24587,7 +24557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -24587,7 +24557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24587 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },24557 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
24588 } },24558 } },
24589 } }) catch |err| switch (err) {24559 } }) catch |err| switch (err) {
24590 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{24560 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
24591 @tagName(air_tag),24561 @tagName(air_tag),
24592 ty.fmt(pt),24562 ty.fmt(pt),
24593 ops[0].tracking(cg),24563 ops[0].tracking(cg),
...@@ -27287,7 +27257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -27287,7 +27257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27287 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },27257 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
27288 } },27258 } },
27289 } }) catch |err| switch (err) {27259 } }) catch |err| switch (err) {
27290 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{27260 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
27291 @tagName(air_tag),27261 @tagName(air_tag),
27292 ty.fmt(pt),27262 ty.fmt(pt),
27293 ops[0].tracking(cg),27263 ops[0].tracking(cg),
...@@ -27296,7 +27266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -27296,7 +27266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27296 else => |e| return e,27266 else => |e| return e,
27297 };27267 };
27298 res[0].wrapInt(cg) catch |err| switch (err) {27268 res[0].wrapInt(cg) catch |err| switch (err) {
27299 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{27269 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
27300 @tagName(air_tag),27270 @tagName(air_tag),
27301 cg.typeOf(bin_op.lhs).fmt(pt),27271 cg.typeOf(bin_op.lhs).fmt(pt),
27302 res[0].tracking(cg),27272 res[0].tracking(cg),
...@@ -32512,7 +32482,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -32512,7 +32482,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
32512 .{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp3q, ._, ._ },32482 .{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp3q, ._, ._ },
32513 } },32483 } },
32514 } }) catch |err| switch (err) {32484 } }) catch |err| switch (err) {
32515 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{32485 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
32516 @tagName(air_tag),32486 @tagName(air_tag),
32517 cg.typeOf(bin_op.lhs).fmt(pt),32487 cg.typeOf(bin_op.lhs).fmt(pt),
32518 ops[0].tracking(cg),32488 ops[0].tracking(cg),
...@@ -33606,7 +33576,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -33606,7 +33576,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
33606 assert(air_tag == .div_exact);33576 assert(air_tag == .div_exact);
33607 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;33577 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
33608 }) catch |err| switch (err) {33578 }) catch |err| switch (err) {
33609 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{33579 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
33610 @tagName(air_tag),33580 @tagName(air_tag),
33611 ty.fmt(pt),33581 ty.fmt(pt),
33612 ops[0].tracking(cg),33582 ops[0].tracking(cg),
...@@ -34837,7 +34807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34837,7 +34807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34837 } }) else err: {34807 } }) else err: {
34838 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;34808 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
34839 }) catch |err| switch (err) {34809 }) catch |err| switch (err) {
34840 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{34810 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
34841 @tagName(air_tag),34811 @tagName(air_tag),
34842 ty.fmt(pt),34812 ty.fmt(pt),
34843 ops[0].tracking(cg),34813 ops[0].tracking(cg),
...@@ -36148,7 +36118,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36148,7 +36118,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36148 } },36118 } },
36149 } },36119 } },
36150 }) catch |err| switch (err) {36120 }) catch |err| switch (err) {
36151 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{36121 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
36152 @tagName(air_tag),36122 @tagName(air_tag),
36153 cg.typeOf(bin_op.lhs).fmt(pt),36123 cg.typeOf(bin_op.lhs).fmt(pt),
36154 ops[0].tracking(cg),36124 ops[0].tracking(cg),
...@@ -37614,7 +37584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37614,7 +37584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37614 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },37584 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
37615 } },37585 } },
37616 } })) catch |err| switch (err) {37586 } })) catch |err| switch (err) {
37617 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{37587 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
37618 @tagName(air_tag),37588 @tagName(air_tag),
37619 ty.fmt(pt),37589 ty.fmt(pt),
37620 ops[0].tracking(cg),37590 ops[0].tracking(cg),
...@@ -39248,7 +39218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39248,7 +39218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39248 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },39218 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
39249 } },39219 } },
39250 } }) catch |err| switch (err) {39220 } }) catch |err| switch (err) {
39251 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{39221 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
39252 @tagName(air_tag),39222 @tagName(air_tag),
39253 cg.typeOf(bin_op.lhs).fmt(pt),39223 cg.typeOf(bin_op.lhs).fmt(pt),
39254 ops[0].tracking(cg),39224 ops[0].tracking(cg),
...@@ -42077,7 +42047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42077,7 +42047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42077 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },42047 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
42078 } },42048 } },
42079 } }) catch |err| switch (err) {42049 } }) catch |err| switch (err) {
42080 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{42050 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
42081 @tagName(air_tag),42051 @tagName(air_tag),
42082 cg.typeOf(bin_op.lhs).fmt(pt),42052 cg.typeOf(bin_op.lhs).fmt(pt),
42083 ops[0].tracking(cg),42053 ops[0].tracking(cg),
...@@ -42191,7 +42161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42191,7 +42161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42191 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },42161 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
42192 } },42162 } },
42193 } }) catch |err| switch (err) {42163 } }) catch |err| switch (err) {
42194 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{42164 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
42195 @tagName(air_tag),42165 @tagName(air_tag),
42196 cg.typeOf(bin_op.lhs).fmt(pt),42166 cg.typeOf(bin_op.lhs).fmt(pt),
42197 ops[0].tracking(cg),42167 ops[0].tracking(cg),
...@@ -42320,7 +42290,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42320,7 +42290,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42320 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },42290 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
42321 } },42291 } },
42322 } }) catch |err| switch (err) {42292 } }) catch |err| switch (err) {
42323 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{42293 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
42324 @tagName(air_tag),42294 @tagName(air_tag),
42325 cg.typeOf(bin_op.lhs).fmt(pt),42295 cg.typeOf(bin_op.lhs).fmt(pt),
42326 ops[0].tracking(cg),42296 ops[0].tracking(cg),
...@@ -46485,7 +46455,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -46485,7 +46455,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
46485 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },46455 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
46486 } },46456 } },
46487 } }) catch |err| switch (err) {46457 } }) catch |err| switch (err) {
46488 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{46458 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
46489 @tagName(air_tag),46459 @tagName(air_tag),
46490 cg.typeOf(bin_op.lhs).fmt(pt),46460 cg.typeOf(bin_op.lhs).fmt(pt),
46491 ops[0].tracking(cg),46461 ops[0].tracking(cg),
...@@ -50644,7 +50614,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -50644,7 +50614,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
50644 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },50614 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
50645 } },50615 } },
50646 } }) catch |err| switch (err) {50616 } }) catch |err| switch (err) {
50647 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{50617 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
50648 @tagName(air_tag),50618 @tagName(air_tag),
50649 cg.typeOf(bin_op.lhs).fmt(pt),50619 cg.typeOf(bin_op.lhs).fmt(pt),
50650 ops[0].tracking(cg),50620 ops[0].tracking(cg),
...@@ -51493,7 +51463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -51493,7 +51463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
51493 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },51463 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
51494 } },51464 } },
51495 } }) catch |err| switch (err) {51465 } }) catch |err| switch (err) {
51496 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{51466 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
51497 @tagName(air_tag),51467 @tagName(air_tag),
51498 ty_pl.ty.toType().fmt(pt),51468 ty_pl.ty.toType().fmt(pt),
51499 ops[0].tracking(cg),51469 ops[0].tracking(cg),
...@@ -52398,7 +52368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52398,7 +52368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52398 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },52368 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
52399 } },52369 } },
52400 } }) catch |err| switch (err) {52370 } }) catch |err| switch (err) {
52401 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{52371 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
52402 @tagName(air_tag),52372 @tagName(air_tag),
52403 ty_pl.ty.toType().fmt(pt),52373 ty_pl.ty.toType().fmt(pt),
52404 ops[0].tracking(cg),52374 ops[0].tracking(cg),
...@@ -55995,7 +55965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -55995,7 +55965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
55995 .{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ },55965 .{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ },
55996 } },55966 } },
55997 } }) catch |err| switch (err) {55967 } }) catch |err| switch (err) {
55998 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{55968 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
55999 @tagName(air_tag),55969 @tagName(air_tag),
56000 ty_pl.ty.toType().fmt(pt),55970 ty_pl.ty.toType().fmt(pt),
56001 ops[0].tracking(cg),55971 ops[0].tracking(cg),
...@@ -59340,7 +59310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -59340,7 +59310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
59340 .{ ._, ._, .@"or", .tmp4q, .tmp5q, ._, ._ },59310 .{ ._, ._, .@"or", .tmp4q, .tmp5q, ._, ._ },
59341 } },59311 } },
59342 } }) catch |err| switch (err) {59312 } }) catch |err| switch (err) {
59343 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{59313 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
59344 @tagName(air_tag),59314 @tagName(air_tag),
59345 ty_pl.ty.toType().fmt(pt),59315 ty_pl.ty.toType().fmt(pt),
59346 ops[0].tracking(cg),59316 ops[0].tracking(cg),
...@@ -59735,7 +59705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -59735,7 +59705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
59735 } },59705 } },
59736 } },59706 } },
59737 }) catch |err| switch (err) {59707 }) catch |err| switch (err) {
59738 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{59708 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
59739 @tagName(air_tag),59709 @tagName(air_tag),
59740 cg.typeOf(bin_op.lhs).fmt(pt),59710 cg.typeOf(bin_op.lhs).fmt(pt),
59741 ops[0].tracking(cg),59711 ops[0].tracking(cg),
...@@ -60298,7 +60268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60298,7 +60268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60298 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },60268 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
60299 } },60269 } },
60300 } }) catch |err| switch (err) {60270 } }) catch |err| switch (err) {
60301 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{60271 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
60302 @tagName(air_tag),60272 @tagName(air_tag),
60303 cg.typeOf(bin_op.lhs).fmt(pt),60273 cg.typeOf(bin_op.lhs).fmt(pt),
60304 cg.typeOf(bin_op.rhs).fmt(pt),60274 cg.typeOf(bin_op.rhs).fmt(pt),
...@@ -60660,7 +60630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60660,7 +60630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60660 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },60630 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
60661 } },60631 } },
60662 } }) catch |err| switch (err) {60632 } }) catch |err| switch (err) {
60663 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{60633 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
60664 @tagName(air_tag),60634 @tagName(air_tag),
60665 cg.typeOf(bin_op.lhs).fmt(pt),60635 cg.typeOf(bin_op.lhs).fmt(pt),
60666 cg.typeOf(bin_op.rhs).fmt(pt),60636 cg.typeOf(bin_op.rhs).fmt(pt),
...@@ -60672,7 +60642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60672,7 +60642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60672 switch (air_tag) {60642 switch (air_tag) {
60673 else => unreachable,60643 else => unreachable,
60674 .shl => res[0].wrapInt(cg) catch |err| switch (err) {60644 .shl => res[0].wrapInt(cg) catch |err| switch (err) {
60675 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{60645 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
60676 @tagName(air_tag),60646 @tagName(air_tag),
60677 cg.typeOf(bin_op.lhs).fmt(pt),60647 cg.typeOf(bin_op.lhs).fmt(pt),
60678 res[0].tracking(cg),60648 res[0].tracking(cg),
...@@ -60839,7 +60809,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60839,7 +60809,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60839 .{ ._, ._, .@"or", .dst0d, .tmp0d, ._, ._ },60809 .{ ._, ._, .@"or", .dst0d, .tmp0d, ._, ._ },
60840 } },60810 } },
60841 } }) catch |err| switch (err) {60811 } }) catch |err| switch (err) {
60842 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{60812 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
60843 @tagName(air_tag),60813 @tagName(air_tag),
60844 cg.typeOf(bin_op.rhs).fmt(pt),60814 cg.typeOf(bin_op.rhs).fmt(pt),
60845 ops[1].tracking(cg),60815 ops[1].tracking(cg),
...@@ -64096,7 +64066,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -64096,7 +64066,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
64096 .{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp1q, ._, ._ },64066 .{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp1q, ._, ._ },
64097 } },64067 } },
64098 } }) catch |err| switch (err) {64068 } }) catch |err| switch (err) {
64099 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{64069 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
64100 @tagName(air_tag),64070 @tagName(air_tag),
64101 lhs_ty.fmt(pt),64071 lhs_ty.fmt(pt),
64102 ops[0].tracking(cg),64072 ops[0].tracking(cg),
...@@ -65329,7 +65299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -65329,7 +65299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
65329 .{ ._, ._b, .j, .@"0b", ._, ._, ._ },65299 .{ ._, ._b, .j, .@"0b", ._, ._, ._ },
65330 } },65300 } },
65331 } }) catch |err| switch (err) {65301 } }) catch |err| switch (err) {
65332 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{65302 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
65333 @tagName(air_tag),65303 @tagName(air_tag),
65334 ty_op.ty.toType().fmt(pt),65304 ty_op.ty.toType().fmt(pt),
65335 ops[0].tracking(cg),65305 ops[0].tracking(cg),
...@@ -68483,7 +68453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -68483,7 +68453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
68483 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },68453 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
68484 } },68454 } },
68485 } }) catch |err| switch (err) {68455 } }) catch |err| switch (err) {
68486 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{68456 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
68487 @tagName(air_tag),68457 @tagName(air_tag),
68488 cg.typeOf(ty_op.operand).fmt(pt),68458 cg.typeOf(ty_op.operand).fmt(pt),
68489 ops[0].tracking(cg),68459 ops[0].tracking(cg),
...@@ -68880,7 +68850,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -68880,7 +68850,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
68880 .{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ },68850 .{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ },
68881 } },68851 } },
68882 } }) catch |err| switch (err) {68852 } }) catch |err| switch (err) {
68883 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{68853 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
68884 @tagName(air_tag),68854 @tagName(air_tag),
68885 cg.typeOf(ty_op.operand).fmt(pt),68855 cg.typeOf(ty_op.operand).fmt(pt),
68886 ops[0].tracking(cg),68856 ops[0].tracking(cg),
...@@ -69768,7 +69738,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -69768,7 +69738,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
69768 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },69738 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
69769 } },69739 } },
69770 } }) catch |err| switch (err) {69740 } }) catch |err| switch (err) {
69771 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{69741 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
69772 @tagName(air_tag),69742 @tagName(air_tag),
69773 cg.typeOf(ty_op.operand).fmt(pt),69743 cg.typeOf(ty_op.operand).fmt(pt),
69774 ops[0].tracking(cg),69744 ops[0].tracking(cg),
...@@ -70417,7 +70387,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -70417,7 +70387,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
70417 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },70387 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
70418 } },70388 } },
70419 } }) catch |err| switch (err) {70389 } }) catch |err| switch (err) {
70420 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{70390 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
70421 @tagName(air_tag),70391 @tagName(air_tag),
70422 ty_op.ty.toType().fmt(pt),70392 ty_op.ty.toType().fmt(pt),
70423 ops[0].tracking(cg),70393 ops[0].tracking(cg),
...@@ -73519,7 +73489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -73519,7 +73489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
73519 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },73489 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
73520 } },73490 } },
73521 } }) catch |err| switch (err) {73491 } }) catch |err| switch (err) {
73522 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{73492 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
73523 @tagName(air_tag),73493 @tagName(air_tag),
73524 ty_op.ty.toType().fmt(pt),73494 ty_op.ty.toType().fmt(pt),
73525 ops[0].tracking(cg),73495 ops[0].tracking(cg),
...@@ -74457,7 +74427,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -74457,7 +74427,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
74457 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },74427 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
74458 } },74428 } },
74459 } }) catch |err| switch (err) {74429 } }) catch |err| switch (err) {
74460 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{74430 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
74461 @tagName(air_tag),74431 @tagName(air_tag),
74462 cg.typeOf(un_op).fmt(pt),74432 cg.typeOf(un_op).fmt(pt),
74463 ops[0].tracking(cg),74433 ops[0].tracking(cg),
...@@ -75183,7 +75153,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -75183,7 +75153,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
75183 } },75153 } },
75184 } },75154 } },
75185 }) catch |err| switch (err) {75155 }) catch |err| switch (err) {
75186 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{75156 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
75187 @tagName(air_tag),75157 @tagName(air_tag),
75188 cg.typeOf(un_op).fmt(pt),75158 cg.typeOf(un_op).fmt(pt),
75189 ops[0].tracking(cg),75159 ops[0].tracking(cg),
...@@ -76734,7 +76704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76734,7 +76704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76734 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },76704 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
76735 } },76705 } },
76736 } }) catch |err| switch (err) {76706 } }) catch |err| switch (err) {
76737 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{76707 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
76738 @tagName(air_tag),76708 @tagName(air_tag),
76739 cg.typeOf(ty_op.operand).fmt(pt),76709 cg.typeOf(ty_op.operand).fmt(pt),
76740 ops[0].tracking(cg),76710 ops[0].tracking(cg),
...@@ -77926,7 +77896,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77926,7 +77896,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77926 } },77896 } },
77927 } },77897 } },
77928 }) catch |err| switch (err) {77898 }) catch |err| switch (err) {
77929 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{77899 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
77930 @tagName(air_tag),77900 @tagName(air_tag),
77931 cg.typeOf(un_op).fmt(pt),77901 cg.typeOf(un_op).fmt(pt),
77932 ops[0].tracking(cg),77902 ops[0].tracking(cg),
...@@ -78466,7 +78436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -78466,7 +78436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
78466 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },78436 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
78467 } },78437 } },
78468 } }) catch |err| switch (err) {78438 } }) catch |err| switch (err) {
78469 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{78439 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
78470 @tagName(air_tag),78440 @tagName(air_tag),
78471 cg.typeOf(un_op).fmt(pt),78441 cg.typeOf(un_op).fmt(pt),
78472 ops[0].tracking(cg),78442 ops[0].tracking(cg),
...@@ -78913,7 +78883,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -78913,7 +78883,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
78913 } else err: {78883 } else err: {
78914 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;78884 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
78915 }) catch |err| switch (err) {78885 }) catch |err| switch (err) {
78916 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{78886 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
78917 @tagName(air_tag),78887 @tagName(air_tag),
78918 cg.typeOf(bin_op.lhs).fmt(pt),78888 cg.typeOf(bin_op.lhs).fmt(pt),
78919 ops[0].tracking(cg),78889 ops[0].tracking(cg),
...@@ -79458,7 +79428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -79458,7 +79428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
79458 .@"struct", .@"union" => {79428 .@"struct", .@"union" => {
79459 assert(ty.containerLayout(zcu) == .@"packed");79429 assert(ty.containerLayout(zcu) == .@"packed");
79460 for (&ops) |*op| op.wrapInt(cg) catch |err| switch (err) {79430 for (&ops) |*op| op.wrapInt(cg) catch |err| switch (err) {
79461 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{79431 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
79462 @tagName(air_tag),79432 @tagName(air_tag),
79463 ty.fmt(pt),79433 ty.fmt(pt),
79464 op.tracking(cg),79434 op.tracking(cg),
...@@ -79470,7 +79440,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -79470,7 +79440,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
79470 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;79440 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
79471 },79441 },
79472 }) catch |err| switch (err) {79442 }) catch |err| switch (err) {
79473 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{79443 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
79474 @tagName(air_tag),79444 @tagName(air_tag),
79475 ty.fmt(pt),79445 ty.fmt(pt),
79476 ops[0].tracking(cg),79446 ops[0].tracking(cg),
...@@ -86551,7 +86521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -86551,7 +86521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
86551 } },86521 } },
86552 }),86522 }),
86553 }) catch |err| switch (err) {86523 }) catch |err| switch (err) {
86554 error.SelectFailed => return cg.fail("failed to select {s} {s} {} {} {}", .{86524 error.SelectFailed => return cg.fail("failed to select {s} {s} {f} {f} {f}", .{
86555 @tagName(air_tag),86525 @tagName(air_tag),
86556 @tagName(vector_cmp.compareOperator()),86526 @tagName(vector_cmp.compareOperator()),
86557 cg.typeOf(vector_cmp.lhs).fmt(pt),86527 cg.typeOf(vector_cmp.lhs).fmt(pt),
...@@ -88546,7 +88516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -88546,7 +88516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
88546 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },88516 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
88547 } },88517 } },
88548 } }) catch |err| switch (err) {88518 } }) catch |err| switch (err) {
88549 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{88519 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
88550 @tagName(air_tag),88520 @tagName(air_tag),
88551 ty_op.ty.toType().fmt(pt),88521 ty_op.ty.toType().fmt(pt),
88552 cg.typeOf(ty_op.operand).fmt(pt),88522 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -90221,7 +90191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -90221,7 +90191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
90221 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },90191 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
90222 } },90192 } },
90223 } }) catch |err| switch (err) {90193 } }) catch |err| switch (err) {
90224 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{90194 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
90225 @tagName(air_tag),90195 @tagName(air_tag),
90226 ty_op.ty.toType().fmt(pt),90196 ty_op.ty.toType().fmt(pt),
90227 cg.typeOf(ty_op.operand).fmt(pt),90197 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -94899,7 +94869,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -94899,7 +94869,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
94899 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },94869 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
94900 } },94870 } },
94901 } }) catch |err| switch (err) {94871 } }) catch |err| switch (err) {
94902 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{94872 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
94903 @tagName(air_tag),94873 @tagName(air_tag),
94904 dst_ty.fmt(pt),94874 dst_ty.fmt(pt),
94905 src_ty.fmt(pt),94875 src_ty.fmt(pt),
...@@ -100565,7 +100535,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -100565,7 +100535,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100565 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },100535 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
100566 } },100536 } },
100567 } }) catch |err| switch (err) {100537 } }) catch |err| switch (err) {
100568 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{100538 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
100569 @tagName(air_tag),100539 @tagName(air_tag),
100570 ty_op.ty.toType().fmt(pt),100540 ty_op.ty.toType().fmt(pt),
100571 cg.typeOf(ty_op.operand).fmt(pt),100541 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -111427,7 +111397,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -111427,7 +111397,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111427 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },111397 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
111428 } },111398 } },
111429 } }) catch |err| switch (err) {111399 } }) catch |err| switch (err) {
111430 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{111400 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
111431 @tagName(air_tag),111401 @tagName(air_tag),
111432 ty_op.ty.toType().fmt(pt),111402 ty_op.ty.toType().fmt(pt),
111433 cg.typeOf(ty_op.operand).fmt(pt),111403 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -123446,7 +123416,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -123446,7 +123416,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
123446 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },123416 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
123447 } },123417 } },
123448 } }) catch |err| switch (err) {123418 } }) catch |err| switch (err) {
123449 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{123419 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
123450 @tagName(air_tag),123420 @tagName(air_tag),
123451 ty_op.ty.toType().fmt(pt),123421 ty_op.ty.toType().fmt(pt),
123452 cg.typeOf(ty_op.operand).fmt(pt),123422 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -157216,7 +157186,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -157216,7 +157186,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157216 } },157186 } },
157217 } },157187 } },
157218 }) catch |err| switch (err) {157188 }) catch |err| switch (err) {
157219 error.SelectFailed => return cg.fail("failed to select {s}.{s} {} {}", .{157189 error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
157220 @tagName(air_tag),157190 @tagName(air_tag),
157221 @tagName(reduce.operation),157191 @tagName(reduce.operation),
157222 cg.typeOf(reduce.operand).fmt(pt),157192 cg.typeOf(reduce.operand).fmt(pt),
...@@ -157227,7 +157197,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -157227,7 +157197,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157227 switch (reduce.operation) {157197 switch (reduce.operation) {
157228 .And, .Or, .Xor, .Min, .Max => {},157198 .And, .Or, .Xor, .Min, .Max => {},
157229 .Add, .Mul => if (cg.intInfo(res_ty)) |_| res[0].wrapInt(cg) catch |err| switch (err) {157199 .Add, .Mul => if (cg.intInfo(res_ty)) |_| res[0].wrapInt(cg) catch |err| switch (err) {
157230 error.SelectFailed => return cg.fail("failed to select {s}.{s} wrap {} {}", .{157200 error.SelectFailed => return cg.fail("failed to select {s}.{s} wrap {f} {f}", .{
157231 @tagName(air_tag),157201 @tagName(air_tag),
157232 @tagName(reduce.operation),157202 @tagName(reduce.operation),
157233 res_ty.fmt(pt),157203 res_ty.fmt(pt),
...@@ -164510,7 +164480,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -164510,7 +164480,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164510 } },164480 } },
164511 } },164481 } },
164512 }) catch |err| switch (err) {164482 }) catch |err| switch (err) {
164513 error.SelectFailed => return cg.fail("failed to select {s}.{s} {} {}", .{164483 error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
164514 @tagName(air_tag),164484 @tagName(air_tag),
164515 @tagName(reduce.operation),164485 @tagName(reduce.operation),
164516 cg.typeOf(reduce.operand).fmt(pt),164486 cg.typeOf(reduce.operand).fmt(pt),
...@@ -166307,7 +166277,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166307,7 +166277,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166307 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },166277 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
166308 } },166278 } },
166309 } }) catch |err| switch (err) {166279 } }) catch |err| switch (err) {
166310 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166280 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166311 @tagName(air_tag),166281 @tagName(air_tag),
166312 ty_op.ty.toType().fmt(pt),166282 ty_op.ty.toType().fmt(pt),
166313 ops[0].tracking(cg),166283 ops[0].tracking(cg),
...@@ -166323,7 +166293,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166323,7 +166293,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166323 const bin_op = air_datas[@intFromEnum(inst)].bin_op;166293 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
166324 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }) ++ .{undefined};166294 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }) ++ .{undefined};
166325 ops[2] = ops[0].getByteLen(cg) catch |err| switch (err) {166295 ops[2] = ops[0].getByteLen(cg) catch |err| switch (err) {
166326 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{166296 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
166327 @tagName(air_tag),166297 @tagName(air_tag),
166328 cg.typeOf(bin_op.lhs).fmt(pt),166298 cg.typeOf(bin_op.lhs).fmt(pt),
166329 cg.typeOf(bin_op.rhs).fmt(pt),166299 cg.typeOf(bin_op.rhs).fmt(pt),
...@@ -166363,7 +166333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166363,7 +166333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166363 } },166333 } },
166364 }},166334 }},
166365 }) catch |err| switch (err) {166335 }) catch |err| switch (err) {
166366 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {} {}", .{166336 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f} {f}", .{
166367 @tagName(air_tag),166337 @tagName(air_tag),
166368 cg.typeOf(bin_op.lhs).fmt(pt),166338 cg.typeOf(bin_op.lhs).fmt(pt),
166369 cg.typeOf(bin_op.rhs).fmt(pt),166339 cg.typeOf(bin_op.rhs).fmt(pt),
...@@ -166464,7 +166434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166464,7 +166434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166464 .{ ._, ._, .@"test", .src0p, .src0p, ._, ._ },166434 .{ ._, ._, .@"test", .src0p, .src0p, ._, ._ },
166465 } },166435 } },
166466 } }) catch |err| switch (err) {166436 } }) catch |err| switch (err) {
166467 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166437 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166468 @tagName(air_tag),166438 @tagName(air_tag),
166469 cg.typeOf(un_op).fmt(pt),166439 cg.typeOf(un_op).fmt(pt),
166470 ops[0].tracking(cg),166440 ops[0].tracking(cg),
...@@ -166552,7 +166522,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166552,7 +166522,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166552 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },166522 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },
166553 } },166523 } },
166554 } }) catch |err| switch (err) {166524 } }) catch |err| switch (err) {
166555 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166525 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166556 @tagName(air_tag),166526 @tagName(air_tag),
166557 cg.typeOf(un_op).fmt(pt),166527 cg.typeOf(un_op).fmt(pt),
166558 ops[0].tracking(cg),166528 ops[0].tracking(cg),
...@@ -166654,7 +166624,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166654,7 +166624,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166654 .{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ },166624 .{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ },
166655 } },166625 } },
166656 } }) catch |err| switch (err) {166626 } }) catch |err| switch (err) {
166657 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166627 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166658 @tagName(air_tag),166628 @tagName(air_tag),
166659 cg.typeOf(un_op).fmt(pt),166629 cg.typeOf(un_op).fmt(pt),
166660 ops[0].tracking(cg),166630 ops[0].tracking(cg),
...@@ -166752,7 +166722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166752,7 +166722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166752 .{ ._, ._, .@"test", .src0d, .src0d, ._, ._ },166722 .{ ._, ._, .@"test", .src0d, .src0d, ._, ._ },
166753 } },166723 } },
166754 } }) catch |err| switch (err) {166724 } }) catch |err| switch (err) {
166755 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166725 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166756 @tagName(air_tag),166726 @tagName(air_tag),
166757 ty_op.ty.toType().fmt(pt),166727 ty_op.ty.toType().fmt(pt),
166758 ops[0].tracking(cg),166728 ops[0].tracking(cg),
...@@ -166804,7 +166774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166804,7 +166774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166804 }166774 }
166805 }166775 }
166806 },166776 },
166807 .@"packed" => return cg.fail("failed to select {s} {}", .{166777 .@"packed" => return cg.fail("failed to select {s} {f}", .{
166808 @tagName(air_tag),166778 @tagName(air_tag),
166809 agg_ty.fmt(pt),166779 agg_ty.fmt(pt),
166810 }),166780 }),
...@@ -166825,7 +166795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166825,7 +166795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166825 elem_disp += @intCast(field_type.abiSize(zcu));166795 elem_disp += @intCast(field_type.abiSize(zcu));
166826 }166796 }
166827 },166797 },
166828 else => return cg.fail("failed to select {s} {}", .{166798 else => return cg.fail("failed to select {s} {f}", .{
166829 @tagName(air_tag),166799 @tagName(air_tag),
166830 agg_ty.fmt(pt),166800 agg_ty.fmt(pt),
166831 }),166801 }),
...@@ -168123,7 +168093,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168123,7 +168093,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168123 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },168093 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
168124 } },168094 } },
168125 } }) catch |err| switch (err) {168095 } }) catch |err| switch (err) {
168126 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{168096 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
168127 @tagName(air_tag),168097 @tagName(air_tag),
168128 cg.typeOf(bin_op.lhs).fmt(pt),168098 cg.typeOf(bin_op.lhs).fmt(pt),
168129 ops[0].tracking(cg),168099 ops[0].tracking(cg),
...@@ -168223,7 +168193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168223,7 +168193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168223 .{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ },168193 .{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ },
168224 } },168194 } },
168225 } }) catch |err| switch (err) {168195 } }) catch |err| switch (err) {
168226 error.SelectFailed => return cg.fail("failed to select {s} {}", .{168196 error.SelectFailed => return cg.fail("failed to select {s} {f}", .{
168227 @tagName(air_tag),168197 @tagName(air_tag),
168228 ops[0].tracking(cg),168198 ops[0].tracking(cg),
168229 }),168199 }),
...@@ -168242,12 +168212,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168242,12 +168212,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168242 .ref => {168212 .ref => {
168243 const result = try cg.allocRegOrMem(err_ret_trace_index, true);168213 const result = try cg.allocRegOrMem(err_ret_trace_index, true);
168244 try cg.genCopy(.usize, result, ops[0].tracking(cg).short, .{});168214 try cg.genCopy(.usize, result, ops[0].tracking(cg).short, .{});
168245 tracking_log.debug("{} => {} (birth)", .{ err_ret_trace_index, result });168215 tracking_log.debug("{f} => {f} (birth)", .{ err_ret_trace_index, result });
168246 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, .init(result));168216 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, .init(result));
168247 },168217 },
168248 .temp => |temp_index| {168218 .temp => |temp_index| {
168249 const temp_tracking = temp_index.tracking(cg);168219 const temp_tracking = temp_index.tracking(cg);
168250 tracking_log.debug("{} => {} (birth)", .{ err_ret_trace_index, temp_tracking.short });168220 tracking_log.debug("{f} => {f} (birth)", .{ err_ret_trace_index, temp_tracking.short });
168251 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, temp_tracking.*);168221 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, temp_tracking.*);
168252 assert(cg.reuseTemp(err_ret_trace_index, temp_index.toIndex(), temp_tracking));168222 assert(cg.reuseTemp(err_ret_trace_index, temp_index.toIndex(), temp_tracking));
168253 },168223 },
...@@ -168917,7 +168887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168917,7 +168887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168917 try cg.resetTemps(@enumFromInt(0));168887 try cg.resetTemps(@enumFromInt(0));
168918 cg.checkInvariantsAfterAirInst();168888 cg.checkInvariantsAfterAirInst();
168919 }168889 }
168920 verbose_tracking_log.debug("{}", .{cg.fmtTracking()});168890 verbose_tracking_log.debug("{f}", .{cg.fmtTracking()});
168921}168891}
168922168892
168923fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {168893fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
...@@ -168927,7 +168897,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -168927,7 +168897,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
168927 switch (ip.indexToKey(lazy_sym.ty)) {168897 switch (ip.indexToKey(lazy_sym.ty)) {
168928 .enum_type => {168898 .enum_type => {
168929 const enum_ty: Type = .fromInterned(lazy_sym.ty);168899 const enum_ty: Type = .fromInterned(lazy_sym.ty);
168930 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});168900 wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
168931168901
168932 const param_regs = abi.getCAbiIntParamRegs(.auto);168902 const param_regs = abi.getCAbiIntParamRegs(.auto);
168933 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);168903 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
...@@ -168976,7 +168946,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -168976,7 +168946,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
168976 },168946 },
168977 .error_set_type => |error_set_type| {168947 .error_set_type => |error_set_type| {
168978 const err_ty: Type = .fromInterned(lazy_sym.ty);168948 const err_ty: Type = .fromInterned(lazy_sym.ty);
168979 wip_mir_log.debug("{}.@errorCast:", .{err_ty.fmt(pt)});168949 wip_mir_log.debug("{f}.@errorCast:", .{err_ty.fmt(pt)});
168980168950
168981 const param_regs = abi.getCAbiIntParamRegs(.auto);168951 const param_regs = abi.getCAbiIntParamRegs(.auto);
168982 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);168952 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
...@@ -169016,7 +168986,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -169016,7 +168986,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
169016 try cg.asmOpOnly(.{ ._, .ret });168986 try cg.asmOpOnly(.{ ._, .ret });
169017 },168987 },
169018 else => return cg.fail(168988 else => return cg.fail(
169019 "TODO implement {s} for {}",168989 "TODO implement {s} for {f}",
169020 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },168990 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
169021 ),168991 ),
169022 }168992 }
...@@ -169076,7 +169046,7 @@ fn finishAirResult(self: *CodeGen, inst: Air.Inst.Index, result: MCValue) void {...@@ -169076,7 +169046,7 @@ fn finishAirResult(self: *CodeGen, inst: Air.Inst.Index, result: MCValue) void {
169076 .none, .dead, .unreach => {},169046 .none, .dead, .unreach => {},
169077 else => unreachable, // Why didn't the result die?169047 else => unreachable, // Why didn't the result die?
169078 } else {169048 } else {
169079 tracking_log.debug("{} => {} (birth)", .{ inst, result });169049 tracking_log.debug("{f} => {f} (birth)", .{ inst, result });
169080 self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));169050 self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));
169081 // In some cases, an operand may be reused as the result.169051 // In some cases, an operand may be reused as the result.
169082 // If that operand died and was a register, it was freed by169052 // If that operand died and was a register, it was freed by
...@@ -169226,7 +169196,7 @@ fn allocMemPtr(self: *CodeGen, inst: Air.Inst.Index) !FrameIndex {...@@ -169226,7 +169196,7 @@ fn allocMemPtr(self: *CodeGen, inst: Air.Inst.Index) !FrameIndex {
169226 const val_ty = ptr_ty.childType(zcu);169196 const val_ty = ptr_ty.childType(zcu);
169227 return self.allocFrameIndex(.init(.{169197 return self.allocFrameIndex(.init(.{
169228 .size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {169198 .size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {
169229 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(pt)});169199 return self.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(pt)});
169230 },169200 },
169231 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),169201 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
169232 }));169202 }));
...@@ -169244,7 +169214,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok...@@ -169244,7 +169214,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok
169244 const pt = self.pt;169214 const pt = self.pt;
169245 const zcu = pt.zcu;169215 const zcu = pt.zcu;
169246 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {169216 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
169247 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});169217 return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(pt)});
169248 };169218 };
169249169219
169250 if (reg_ok) need_mem: {169220 if (reg_ok) need_mem: {
...@@ -169749,7 +169719,7 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -169749,7 +169719,7 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void {
169749 );169719 );
169750 }169720 }
169751 break :result dst_mcv;169721 break :result dst_mcv;
169752 } orelse return self.fail("TODO implement airFpext from {} to {}", .{169722 } orelse return self.fail("TODO implement airFpext from {f} to {f}", .{
169753 src_ty.fmt(pt), dst_ty.fmt(pt),169723 src_ty.fmt(pt), dst_ty.fmt(pt),
169754 });169724 });
169755 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });169725 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -170004,7 +169974,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170004,7 +169974,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
170004 );169974 );
170005169975
170006 break :result dst_mcv;169976 break :result dst_mcv;
170007 }) orelse return self.fail("TODO implement airIntCast from {} to {}", .{169977 }) orelse return self.fail("TODO implement airIntCast from {f} to {f}", .{
170008 src_ty.fmt(pt), dst_ty.fmt(pt),169978 src_ty.fmt(pt), dst_ty.fmt(pt),
170009 });169979 });
170010 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });169980 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -170076,7 +170046,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170076,7 +170046,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
170076 else => null,170046 else => null,
170077 },170047 },
170078 else => null,170048 else => null,
170079 }) orelse return self.fail("TODO implement airTrunc for {}", .{dst_ty.fmt(pt)});170049 }) orelse return self.fail("TODO implement airTrunc for {f}", .{dst_ty.fmt(pt)});
170080170050
170081 const dst_info = dst_elem_ty.intInfo(zcu);170051 const dst_info = dst_elem_ty.intInfo(zcu);
170082 const src_info = src_elem_ty.intInfo(zcu);170052 const src_info = src_elem_ty.intInfo(zcu);
...@@ -170497,7 +170467,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170497,7 +170467,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {
170497 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;170467 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
170498 const ty = self.typeOf(bin_op.lhs);170468 const ty = self.typeOf(bin_op.lhs);
170499 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(170469 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(
170500 "TODO implement airAddSat for {}",170470 "TODO implement airAddSat for {f}",
170501 .{ty.fmt(pt)},170471 .{ty.fmt(pt)},
170502 );170472 );
170503170473
...@@ -170575,7 +170545,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170575,7 +170545,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {
170575 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;170545 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
170576 const ty = self.typeOf(bin_op.lhs);170546 const ty = self.typeOf(bin_op.lhs);
170577 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(170547 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(
170578 "TODO implement airSubSat for {}",170548 "TODO implement airSubSat for {f}",
170579 .{ty.fmt(pt)},170549 .{ty.fmt(pt)},
170580 );170550 );
170581170551
...@@ -170726,7 +170696,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170726,7 +170696,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
170726 }170696 }
170727170697
170728 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(170698 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(
170729 "TODO implement airMulSat for {}",170699 "TODO implement airMulSat for {f}",
170730 .{ty.fmt(pt)},170700 .{ty.fmt(pt)},
170731 );170701 );
170732170702
...@@ -171020,7 +170990,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -171020,7 +170990,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
171020 const tuple_ty = self.typeOfIndex(inst);170990 const tuple_ty = self.typeOfIndex(inst);
171021 const dst_ty = self.typeOf(bin_op.lhs);170991 const dst_ty = self.typeOf(bin_op.lhs);
171022 const result: MCValue = switch (dst_ty.zigTypeTag(zcu)) {170992 const result: MCValue = switch (dst_ty.zigTypeTag(zcu)) {
171023 .vector => return self.fail("TODO implement airMulWithOverflow for {}", .{dst_ty.fmt(pt)}),170993 .vector => return self.fail("TODO implement airMulWithOverflow for {f}", .{dst_ty.fmt(pt)}),
171024 .int => result: {170994 .int => result: {
171025 const dst_info = dst_ty.intInfo(zcu);170995 const dst_info = dst_ty.intInfo(zcu);
171026 if (dst_info.bits > 128 and dst_info.signedness == .unsigned) {170996 if (dst_info.bits > 128 and dst_info.signedness == .unsigned) {
...@@ -171373,7 +171343,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -171373,7 +171343,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
171373 else => {171343 else => {
171374 // For now, this is the only supported multiply that doesn't fit in a register.171344 // For now, this is the only supported multiply that doesn't fit in a register.
171375 if (dst_info.bits > 128 or src_bits != 64)171345 if (dst_info.bits > 128 or src_bits != 64)
171376 return self.fail("TODO implement airWithOverflow from {} to {}", .{171346 return self.fail("TODO implement airWithOverflow from {f} to {f}", .{
171377 src_ty.fmt(pt), dst_ty.fmt(pt),171347 src_ty.fmt(pt), dst_ty.fmt(pt),
171378 });171348 });
171379171349
...@@ -171774,7 +171744,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -171774,7 +171744,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
171774 },171744 },
171775 else => {},171745 else => {},
171776 }171746 }
171777 return self.fail("TODO implement airShlShrBinOp for {}", .{lhs_ty.fmt(pt)});171747 return self.fail("TODO implement airShlShrBinOp for {f}", .{lhs_ty.fmt(pt)});
171778 };171748 };
171779 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });171749 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
171780}171750}
...@@ -172034,7 +172004,7 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172034,7 +172004,7 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void {
172034 .index = frame_addr.index,172004 .index = frame_addr.index,
172035 .off = frame_addr.off + @as(i32, @intCast(err_off)),172005 .off = frame_addr.off + @as(i32, @intCast(err_off)),
172036 } },172006 } },
172037 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),172007 else => return self.fail("TODO implement unwrap_err_err for {f}", .{operand}),
172038 }172008 }
172039 };172009 };
172040 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });172010 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -172196,7 +172166,7 @@ fn genUnwrapErrUnionPayloadMir(...@@ -172196,7 +172166,7 @@ fn genUnwrapErrUnionPayloadMir(
172196 else172166 else
172197 .{ .register = try self.copyToTmpRegister(payload_ty, result_mcv) };172167 .{ .register = try self.copyToTmpRegister(payload_ty, result_mcv) };
172198 },172168 },
172199 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),172169 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {f}", .{err_union}),
172200 }172170 }
172201 };172171 };
172202172172
...@@ -172362,7 +172332,7 @@ fn airSliceLen(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172362,7 +172332,7 @@ fn airSliceLen(self: *CodeGen, inst: Air.Inst.Index) !void {
172362 .index = frame_addr.index,172332 .index = frame_addr.index,
172363 .off = frame_addr.off + 8,172333 .off = frame_addr.off + 8,
172364 } },172334 } },
172365 else => return self.fail("TODO implement slice_len for {}", .{src_mcv}),172335 else => return self.fail("TODO implement slice_len for {f}", .{src_mcv}),
172366 };172336 };
172367 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {172337 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
172368 switch (src_mcv) {172338 switch (src_mcv) {
...@@ -172645,7 +172615,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172645,7 +172615,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
172645 }.to64(),172615 }.to64(),
172646 ),172616 ),
172647 },172617 },
172648 else => return self.fail("TODO airArrayElemVal for {s} of {}", .{172618 else => return self.fail("TODO airArrayElemVal for {s} of {f}", .{
172649 @tagName(array_mat_mcv), array_ty.fmt(pt),172619 @tagName(array_mat_mcv), array_ty.fmt(pt),
172650 }),172620 }),
172651 }172621 }
...@@ -172688,7 +172658,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172688,7 +172658,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
172688 .load_extern_func,172658 .load_extern_func,
172689 .lea_extern_func,172659 .lea_extern_func,
172690 => try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),172660 => try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),
172691 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{172661 else => return self.fail("TODO airArrayElemVal_val for {s} of {f}", .{
172692 @tagName(array_mcv), array_ty.fmt(pt),172662 @tagName(array_mcv), array_ty.fmt(pt),
172693 }),172663 }),
172694 }172664 }
...@@ -172881,7 +172851,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172881,7 +172851,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {
172881 }172851 }
172882172852
172883 return self.fail(172853 return self.fail(
172884 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {}",172854 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {f}",
172885 .{operand},172855 .{operand},
172886 );172856 );
172887 },172857 },
...@@ -172893,7 +172863,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172893,7 +172863,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {
172893 .register = registerAlias(result.register, @intCast(layout.tag_size)),172863 .register = registerAlias(result.register, @intCast(layout.tag_size)),
172894 };172864 };
172895 },172865 },
172896 else => return self.fail("TODO implement get_union_tag for {}", .{operand}),172866 else => return self.fail("TODO implement get_union_tag for {f}", .{operand}),
172897 }172867 }
172898 };172868 };
172899172869
...@@ -172909,7 +172879,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172909,7 +172879,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {
172909172879
172910 const dst_ty = self.typeOfIndex(inst);172880 const dst_ty = self.typeOfIndex(inst);
172911 const src_ty = self.typeOf(ty_op.operand);172881 const src_ty = self.typeOf(ty_op.operand);
172912 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airClz for {}", .{172882 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airClz for {f}", .{
172913 src_ty.fmt(pt),172883 src_ty.fmt(pt),
172914 });172884 });
172915172885
...@@ -173105,7 +173075,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -173105,7 +173075,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {
173105173075
173106 const dst_ty = self.typeOfIndex(inst);173076 const dst_ty = self.typeOfIndex(inst);
173107 const src_ty = self.typeOf(ty_op.operand);173077 const src_ty = self.typeOf(ty_op.operand);
173108 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airCtz for {}", .{173078 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airCtz for {f}", .{
173109 src_ty.fmt(pt),173079 src_ty.fmt(pt),
173110 });173080 });
173111173081
...@@ -173277,7 +173247,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -173277,7 +173247,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void {
173277 const src_ty = self.typeOf(ty_op.operand);173247 const src_ty = self.typeOf(ty_op.operand);
173278 const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu));173248 const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu));
173279 if (src_ty.zigTypeTag(zcu) == .vector or src_abi_size > 16)173249 if (src_ty.zigTypeTag(zcu) == .vector or src_abi_size > 16)
173280 return self.fail("TODO implement airPopCount for {}", .{src_ty.fmt(pt)});173250 return self.fail("TODO implement airPopCount for {f}", .{src_ty.fmt(pt)});
173281 const src_mcv = try self.resolveInst(ty_op.operand);173251 const src_mcv = try self.resolveInst(ty_op.operand);
173282173252
173283 const mat_src_mcv = switch (src_mcv) {173253 const mat_src_mcv = switch (src_mcv) {
...@@ -173430,7 +173400,7 @@ fn genByteSwap(...@@ -173430,7 +173400,7 @@ fn genByteSwap(
173430 const has_movbe = self.hasFeature(.movbe);173400 const has_movbe = self.hasFeature(.movbe);
173431173401
173432 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail(173402 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail(
173433 "TODO implement genByteSwap for {}",173403 "TODO implement genByteSwap for {f}",
173434 .{src_ty.fmt(pt)},173404 .{src_ty.fmt(pt)},
173435 );173405 );
173436173406
...@@ -173739,7 +173709,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173739,7 +173709,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173739 const result = result: {173709 const result = result: {
173740 const scalar_bits = ty.scalarType(zcu).floatBits(self.target);173710 const scalar_bits = ty.scalarType(zcu).floatBits(self.target);
173741 if (scalar_bits == 80) {173711 if (scalar_bits == 80) {
173742 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement floatSign for {}", .{173712 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement floatSign for {f}", .{
173743 ty.fmt(pt),173713 ty.fmt(pt),
173744 });173714 });
173745173715
...@@ -173763,7 +173733,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173763,7 +173733,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173763 const abi_size: u32 = switch (ty.abiSize(zcu)) {173733 const abi_size: u32 = switch (ty.abiSize(zcu)) {
173764 1...16 => 16,173734 1...16 => 16,
173765 17...32 => 32,173735 17...32 => 32,
173766 else => return self.fail("TODO implement floatSign for {}", .{173736 else => return self.fail("TODO implement floatSign for {f}", .{
173767 ty.fmt(pt),173737 ty.fmt(pt),
173768 }),173738 }),
173769 };173739 };
...@@ -173822,7 +173792,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173822,7 +173792,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173822 .abs => .{ .v_pd, .@"and" },173792 .abs => .{ .v_pd, .@"and" },
173823 else => unreachable,173793 else => unreachable,
173824 },173794 },
173825 80 => return self.fail("TODO implement floatSign for {}", .{ty.fmt(pt)}),173795 80 => return self.fail("TODO implement floatSign for {f}", .{ty.fmt(pt)}),
173826 else => unreachable,173796 else => unreachable,
173827 },173797 },
173828 registerAlias(dst_reg, abi_size),173798 registerAlias(dst_reg, abi_size),
...@@ -173848,7 +173818,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173848,7 +173818,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173848 .abs => .{ ._pd, .@"and" },173818 .abs => .{ ._pd, .@"and" },
173849 else => unreachable,173819 else => unreachable,
173850 },173820 },
173851 80 => return self.fail("TODO implement floatSign for {}", .{ty.fmt(pt)}),173821 80 => return self.fail("TODO implement floatSign for {f}", .{ty.fmt(pt)}),
173852 else => unreachable,173822 else => unreachable,
173853 },173823 },
173854 registerAlias(dst_reg, abi_size),173824 registerAlias(dst_reg, abi_size),
...@@ -173928,7 +173898,7 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM...@@ -173928,7 +173898,7 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM
173928 if (self.getRoundTag(ty)) |_| return .none;173898 if (self.getRoundTag(ty)) |_| return .none;
173929173899
173930 if (ty.zigTypeTag(zcu) != .float)173900 if (ty.zigTypeTag(zcu) != .float)
173931 return self.fail("TODO implement genRound for {}", .{ty.fmt(pt)});173901 return self.fail("TODO implement genRound for {f}", .{ty.fmt(pt)});
173932173902
173933 var sym_buf: ["__trunc?".len]u8 = undefined;173903 var sym_buf: ["__trunc?".len]u8 = undefined;
173934 return try self.genCall(.{ .extern_func = .{173904 return try self.genCall(.{ .extern_func = .{
...@@ -174164,7 +174134,7 @@ fn airAbs(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -174164,7 +174134,7 @@ fn airAbs(self: *CodeGen, inst: Air.Inst.Index) !void {
174164 },174134 },
174165 .float => return self.floatSign(inst, .abs, ty_op.operand, ty),174135 .float => return self.floatSign(inst, .abs, ty_op.operand, ty),
174166 },174136 },
174167 }) orelse return self.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});174137 }) orelse return self.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
174168174138
174169 const abi_size: u32 = @intCast(ty.abiSize(zcu));174139 const abi_size: u32 = @intCast(ty.abiSize(zcu));
174170 const src_mcv = try self.resolveInst(ty_op.operand);174140 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -174323,7 +174293,7 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -174323,7 +174293,7 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {
174323 else => unreachable,174293 else => unreachable,
174324 },174294 },
174325 else => unreachable,174295 else => unreachable,
174326 }) orelse return self.fail("TODO implement airSqrt for {}", .{ty.fmt(pt)});174296 }) orelse return self.fail("TODO implement airSqrt for {f}", .{ty.fmt(pt)});
174327 switch (mir_tag[0]) {174297 switch (mir_tag[0]) {
174328 .v_ss, .v_sd => if (src_mcv.isBase()) try self.asmRegisterRegisterMemory(174298 .v_ss, .v_sd => if (src_mcv.isBase()) try self.asmRegisterRegisterMemory(
174329 mir_tag,174299 mir_tag,
...@@ -174481,7 +174451,7 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue)...@@ -174481,7 +174451,7 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue)
174481 return;174451 return;
174482 }174452 }
174483174453
174484 if (val_abi_size > 8) return self.fail("TODO implement packed load of {}", .{val_ty.fmt(pt)});174454 if (val_abi_size > 8) return self.fail("TODO implement packed load of {f}", .{val_ty.fmt(pt)});
174485174455
174486 const limb_abi_size: u31 = @min(val_abi_size, 8);174456 const limb_abi_size: u31 = @min(val_abi_size, 8);
174487 const limb_abi_bits = limb_abi_size * 8;174457 const limb_abi_bits = limb_abi_size * 8;
...@@ -174753,7 +174723,7 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)...@@ -174753,7 +174723,7 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
174753 limb_mem,174723 limb_mem,
174754 registerAlias(tmp_reg, limb_abi_size),174724 registerAlias(tmp_reg, limb_abi_size),
174755 );174725 );
174756 } else return self.fail("TODO: implement packed store of {}", .{src_ty.fmt(pt)});174726 } else return self.fail("TODO: implement packed store of {f}", .{src_ty.fmt(pt)});
174757 }174727 }
174758}174728}
174759174729
...@@ -174856,7 +174826,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a...@@ -174856,7 +174826,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a
174856 const zcu = pt.zcu;174826 const zcu = pt.zcu;
174857 const src_ty = self.typeOf(src_air);174827 const src_ty = self.typeOf(src_air);
174858 if (src_ty.zigTypeTag(zcu) == .vector)174828 if (src_ty.zigTypeTag(zcu) == .vector)
174859 return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(pt)});174829 return self.fail("TODO implement genUnOp for {f}", .{src_ty.fmt(pt)});
174860174830
174861 var src_mcv = try self.resolveInst(src_air);174831 var src_mcv = try self.resolveInst(src_air);
174862 switch (src_mcv) {174832 switch (src_mcv) {
...@@ -174943,7 +174913,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a...@@ -174943,7 +174913,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a
174943fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {174913fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {
174944 const pt = self.pt;174914 const pt = self.pt;
174945 const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu));174915 const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu));
174946 if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ mir_tag, dst_ty.fmt(pt) });174916 if (abi_size > 8) return self.fail("TODO implement {} for {f}", .{ mir_tag, dst_ty.fmt(pt) });
174947 switch (dst_mcv) {174917 switch (dst_mcv) {
174948 .none,174918 .none,
174949 .unreach,174919 .unreach,
...@@ -175672,7 +175642,7 @@ fn genBinOp(...@@ -175672,7 +175642,7 @@ fn genBinOp(
175672 },175642 },
175673 floatLibcAbiSuffix(lhs_ty),175643 floatLibcAbiSuffix(lhs_ty),
175674 }),175644 }),
175675 else => return self.fail("TODO implement genBinOp for {s} {}", .{175645 else => return self.fail("TODO implement genBinOp for {s} {f}", .{
175676 @tagName(air_tag), lhs_ty.fmt(pt),175646 @tagName(air_tag), lhs_ty.fmt(pt),
175677 }),175647 }),
175678 } catch unreachable;175648 } catch unreachable;
...@@ -175785,7 +175755,7 @@ fn genBinOp(...@@ -175785,7 +175755,7 @@ fn genBinOp(
175785 );175755 );
175786 break :adjusted .{ .register = dst_reg };175756 break :adjusted .{ .register = dst_reg };
175787 },175757 },
175788 80, 128 => return self.fail("TODO implement genBinOp for {s} of {}", .{175758 80, 128 => return self.fail("TODO implement genBinOp for {s} of {f}", .{
175789 @tagName(air_tag), lhs_ty.fmt(pt),175759 @tagName(air_tag), lhs_ty.fmt(pt),
175790 }),175760 }),
175791 else => unreachable,175761 else => unreachable,
...@@ -175819,7 +175789,7 @@ fn genBinOp(...@@ -175819,7 +175789,7 @@ fn genBinOp(
175819 if (sse_op and ((lhs_ty.scalarType(zcu).isRuntimeFloat() and175789 if (sse_op and ((lhs_ty.scalarType(zcu).isRuntimeFloat() and
175820 lhs_ty.scalarType(zcu).floatBits(self.target) == 80) or175790 lhs_ty.scalarType(zcu).floatBits(self.target) == 80) or
175821 lhs_ty.abiSize(zcu) > self.vectorSize(.float)))175791 lhs_ty.abiSize(zcu) > self.vectorSize(.float)))
175822 return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(air_tag), lhs_ty.fmt(pt) });175792 return self.fail("TODO implement genBinOp for {s} {f}", .{ @tagName(air_tag), lhs_ty.fmt(pt) });
175823175793
175824 const maybe_mask_reg = switch (air_tag) {175794 const maybe_mask_reg = switch (air_tag) {
175825 else => null,175795 else => null,
...@@ -176199,7 +176169,7 @@ fn genBinOp(...@@ -176199,7 +176169,7 @@ fn genBinOp(
176199 }176169 }
176200 },176170 },
176201176171
176202 else => return self.fail("TODO implement genBinOp for {s} {}", .{176172 else => return self.fail("TODO implement genBinOp for {s} {f}", .{
176203 @tagName(air_tag), lhs_ty.fmt(pt),176173 @tagName(air_tag), lhs_ty.fmt(pt),
176204 }),176174 }),
176205 }176175 }
...@@ -176953,7 +176923,7 @@ fn genBinOp(...@@ -176953,7 +176923,7 @@ fn genBinOp(
176953 else => unreachable,176923 else => unreachable,
176954 },176924 },
176955 },176925 },
176956 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{176926 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
176957 @tagName(air_tag), lhs_ty.fmt(pt),176927 @tagName(air_tag), lhs_ty.fmt(pt),
176958 });176928 });
176959176929
...@@ -177086,7 +177056,7 @@ fn genBinOp(...@@ -177086,7 +177056,7 @@ fn genBinOp(
177086 else => unreachable,177056 else => unreachable,
177087 },177057 },
177088 else => unreachable,177058 else => unreachable,
177089 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177059 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177090 @tagName(air_tag), lhs_ty.fmt(pt),177060 @tagName(air_tag), lhs_ty.fmt(pt),
177091 }),177061 }),
177092 mask_reg,177062 mask_reg,
...@@ -177118,7 +177088,7 @@ fn genBinOp(...@@ -177118,7 +177088,7 @@ fn genBinOp(
177118 else => unreachable,177088 else => unreachable,
177119 },177089 },
177120 else => unreachable,177090 else => unreachable,
177121 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177091 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177122 @tagName(air_tag), lhs_ty.fmt(pt),177092 @tagName(air_tag), lhs_ty.fmt(pt),
177123 }),177093 }),
177124 dst_reg,177094 dst_reg,
...@@ -177154,7 +177124,7 @@ fn genBinOp(...@@ -177154,7 +177124,7 @@ fn genBinOp(
177154 else => unreachable,177124 else => unreachable,
177155 },177125 },
177156 else => unreachable,177126 else => unreachable,
177157 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177127 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177158 @tagName(air_tag), lhs_ty.fmt(pt),177128 @tagName(air_tag), lhs_ty.fmt(pt),
177159 }),177129 }),
177160 mask_reg,177130 mask_reg,
...@@ -177185,7 +177155,7 @@ fn genBinOp(...@@ -177185,7 +177155,7 @@ fn genBinOp(
177185 else => unreachable,177155 else => unreachable,
177186 },177156 },
177187 else => unreachable,177157 else => unreachable,
177188 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177158 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177189 @tagName(air_tag), lhs_ty.fmt(pt),177159 @tagName(air_tag), lhs_ty.fmt(pt),
177190 }),177160 }),
177191 dst_reg,177161 dst_reg,
...@@ -177215,7 +177185,7 @@ fn genBinOp(...@@ -177215,7 +177185,7 @@ fn genBinOp(
177215 else => unreachable,177185 else => unreachable,
177216 },177186 },
177217 else => unreachable,177187 else => unreachable,
177218 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177188 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177219 @tagName(air_tag), lhs_ty.fmt(pt),177189 @tagName(air_tag), lhs_ty.fmt(pt),
177220 });177190 });
177221 try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_reg, mask_reg);177191 try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_reg, mask_reg);
...@@ -178022,7 +177992,7 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178022,7 +177992,7 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
178022177992
178023 break :result dst_mcv;177993 break :result dst_mcv;
178024 },177994 },
178025 else => return self.fail("TODO implement arg for {}", .{src_mcv}),177995 else => return self.fail("TODO implement arg for {f}", .{src_mcv}),
178026 }177996 }
178027 };177997 };
178028 return self.finishAir(inst, result, .{ .none, .none, .none });177998 return self.finishAir(inst, result, .{ .none, .none, .none });
...@@ -179079,7 +179049,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {...@@ -179079,7 +179049,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {
179079 const reg = try self.copyToTmpRegister(ty, mcv);179049 const reg = try self.copyToTmpRegister(ty, mcv);
179080 return self.genCondBrMir(ty, .{ .register = reg });179050 return self.genCondBrMir(ty, .{ .register = reg });
179081 }179051 }
179082 return self.fail("TODO implement condbr when condition is {} with abi larger than 8 bytes", .{mcv});179052 return self.fail("TODO implement condbr when condition is {f} with abi larger than 8 bytes", .{mcv});
179083 },179053 },
179084 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),179054 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),
179085 }179055 }
...@@ -179166,7 +179136,7 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal...@@ -179166,7 +179136,7 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal
179166 } },179136 } },
179167 .{ .immediate = 0 },179137 .{ .immediate = 0 },
179168 ),179138 ),
179169 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),179139 else => return self.fail("TODO implement isErr for {f}", .{eu_mcv}),
179170 }179140 }
179171179141
179172 if (maybe_inst) |inst| self.eflags_inst = inst;179142 if (maybe_inst) |inst| self.eflags_inst = inst;
...@@ -180916,7 +180886,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M...@@ -180916,7 +180886,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
180916 },180886 },
180917 .ip, .cr, .dr => {},180887 .ip, .cr, .dr => {},
180918 }180888 }
180919 return cg.fail("TODO moveStrategy for {}", .{ty.fmt(pt)});180889 return cg.fail("TODO moveStrategy for {f}", .{ty.fmt(pt)});
180920}180890}
180921180891
180922const CopyOptions = struct {180892const CopyOptions = struct {
...@@ -181048,7 +181018,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C...@@ -181048,7 +181018,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
181048 break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };181018 break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
181049 },181019 },
181050 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref), opts),181020 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref), opts),
181051 else => return self.fail("TODO implement genCopy for {s} of {}", .{181021 else => return self.fail("TODO implement genCopy for {s} of {f}", .{
181052 @tagName(src_mcv), ty.fmt(pt),181022 @tagName(src_mcv), ty.fmt(pt),
181053 }),181023 }),
181054 };181024 };
...@@ -181424,7 +181394,7 @@ fn genSetReg(...@@ -181424,7 +181394,7 @@ fn genSetReg(
181424 80 => null,181394 80 => null,
181425 else => unreachable,181395 else => unreachable,
181426 },181396 },
181427 }) orelse return self.fail("TODO implement genSetReg for {}", .{ty.fmt(pt)}),181397 }) orelse return self.fail("TODO implement genSetReg for {f}", .{ty.fmt(pt)}),
181428 dst_alias,181398 dst_alias,
181429 registerAlias(src_reg, abi_size),181399 registerAlias(src_reg, abi_size),
181430 ),181400 ),
...@@ -181532,7 +181502,7 @@ fn genSetReg(...@@ -181532,7 +181502,7 @@ fn genSetReg(
181532 assert(!ty.optionalReprIsPayload(zcu));181502 assert(!ty.optionalReprIsPayload(zcu));
181533 break :first_ty opt_child;181503 break :first_ty opt_child;
181534 },181504 },
181535 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, ty.fmt(pt) }),181505 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, ty.fmt(pt) }),
181536 });181506 });
181537 const first_size: u31 = @intCast(first_ty.abiSize(zcu));181507 const first_size: u31 = @intCast(first_ty.abiSize(zcu));
181538 const frame_size = std.math.ceilPowerOfTwoAssert(u32, abi_size);181508 const frame_size = std.math.ceilPowerOfTwoAssert(u32, abi_size);
...@@ -181854,7 +181824,7 @@ fn genSetMem(...@@ -181854,7 +181824,7 @@ fn genSetMem(
181854 opts,181824 opts,
181855 );181825 );
181856 },181826 },
181857 else => return self.fail("TODO implement genSetMem for {s} of {}", .{181827 else => return self.fail("TODO implement genSetMem for {s} of {f}", .{
181858 @tagName(src_mcv), ty.fmt(pt),181828 @tagName(src_mcv), ty.fmt(pt),
181859 }),181829 }),
181860 },181830 },
...@@ -182167,7 +182137,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -182167,7 +182137,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {
182167 32, 64 => src_size > 8,182137 32, 64 => src_size > 8,
182168 else => unreachable,182138 else => unreachable,
182169 }) {182139 }) {
182170 if (src_bits > 128) return self.fail("TODO implement airFloatFromInt from {} to {}", .{182140 if (src_bits > 128) return self.fail("TODO implement airFloatFromInt from {f} to {f}", .{
182171 src_ty.fmt(pt), dst_ty.fmt(pt),182141 src_ty.fmt(pt), dst_ty.fmt(pt),
182172 });182142 });
182173182143
...@@ -182209,7 +182179,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -182209,7 +182179,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {
182209 else => unreachable,182179 else => unreachable,
182210 },182180 },
182211 else => null,182181 else => null,
182212 }) orelse return self.fail("TODO implement airFloatFromInt from {} to {}", .{182182 }) orelse return self.fail("TODO implement airFloatFromInt from {f} to {f}", .{
182213 src_ty.fmt(pt), dst_ty.fmt(pt),182183 src_ty.fmt(pt), dst_ty.fmt(pt),
182214 });182184 });
182215 const dst_alias = dst_reg.to128();182185 const dst_alias = dst_reg.to128();
...@@ -182247,7 +182217,7 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -182247,7 +182217,7 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void {
182247 32, 64 => dst_size > 8,182217 32, 64 => dst_size > 8,
182248 else => unreachable,182218 else => unreachable,
182249 }) {182219 }) {
182250 if (dst_bits > 128) return self.fail("TODO implement airIntFromFloat from {} to {}", .{182220 if (dst_bits > 128) return self.fail("TODO implement airIntFromFloat from {f} to {f}", .{
182251 src_ty.fmt(pt), dst_ty.fmt(pt),182221 src_ty.fmt(pt), dst_ty.fmt(pt),
182252 });182222 });
182253182223
...@@ -182531,7 +182501,7 @@ fn atomicOp(...@@ -182531,7 +182501,7 @@ fn atomicOp(
182531 else => null,182501 else => null,
182532 },182502 },
182533 else => unreachable,182503 else => unreachable,
182534 }) orelse return self.fail("TODO implement atomicOp of {s} for {}", .{182504 }) orelse return self.fail("TODO implement atomicOp of {s} for {f}", .{
182535 @tagName(op), val_ty.fmt(pt),182505 @tagName(op), val_ty.fmt(pt),
182536 });182506 });
182537 try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});182507 try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});
...@@ -183286,7 +183256,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183286,7 +183256,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {
183286 else => unreachable,183256 else => unreachable,
183287 },183257 },
183288 }183258 }
183289 return self.fail("TODO implement airSplat for {}", .{vector_ty.fmt(pt)});183259 return self.fail("TODO implement airSplat for {f}", .{vector_ty.fmt(pt)});
183290 };183260 };
183291 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });183261 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
183292}183262}
...@@ -183322,12 +183292,12 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183322,12 +183292,12 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183322 else183292 else
183323 try self.copyToTmpRegister(pred_ty, pred_mcv)183293 try self.copyToTmpRegister(pred_ty, pred_mcv)
183324 else183294 else
183325 return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}),183295 return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)}),
183326 else => unreachable,183296 else => unreachable,
183327 },183297 },
183328 .register_mask => |pred_reg_mask| {183298 .register_mask => |pred_reg_mask| {
183329 if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)183299 if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
183330 return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183300 return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183331183301
183332 const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {183302 const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
183333 try self.register_manager.getKnownReg(.xmm0, null);183303 try self.register_manager.getKnownReg(.xmm0, null);
...@@ -183401,7 +183371,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183401,7 +183371,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183401 else183371 else
183402 null183372 null
183403 else183373 else
183404 null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183374 null) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183405 if (has_avx) {183375 if (has_avx) {
183406 const rhs_alias = if (reuse_mcv.isRegister())183376 const rhs_alias = if (reuse_mcv.isRegister())
183407 registerAlias(reuse_mcv.getReg().?, abi_size)183377 registerAlias(reuse_mcv.getReg().?, abi_size)
...@@ -183554,7 +183524,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183554,7 +183524,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183554 else => unreachable,183524 else => unreachable,
183555 }),183525 }),
183556 );183526 );
183557 } else return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183527 } else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183558 const elem_bits: u16 = @intCast(elem_abi_size * 8);183528 const elem_bits: u16 = @intCast(elem_abi_size * 8);
183559 if (!pred_fits_in_elem) if (self.hasFeature(.ssse3)) {183529 if (!pred_fits_in_elem) if (self.hasFeature(.ssse3)) {
183560 const mask_len = elem_abi_size * vec_len;183530 const mask_len = elem_abi_size * vec_len;
...@@ -183583,7 +183553,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183583,7 +183553,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183583 mask_alias,183553 mask_alias,
183584 mask_mem,183554 mask_mem,
183585 );183555 );
183586 } else return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183556 } else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183587 {183557 {
183588 const mask_elem_ty = try pt.intType(.unsigned, elem_bits);183558 const mask_elem_ty = try pt.intType(.unsigned, elem_bits);
183589 const mask_ty = try pt.vectorType(.{ .len = vec_len, .child = mask_elem_ty.toIntern() });183559 const mask_ty = try pt.vectorType(.{ .len = vec_len, .child = mask_elem_ty.toIntern() });
...@@ -183706,7 +183676,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183706,7 +183676,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183706 else => null,183676 else => null,
183707 },183677 },
183708 },183678 },
183709 }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183679 }) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183710 if (has_avx) {183680 if (has_avx) {
183711 const rhs_alias = if (rhs_mcv.isRegister())183681 const rhs_alias = if (rhs_mcv.isRegister())
183712 registerAlias(rhs_mcv.getReg().?, abi_size)183682 registerAlias(rhs_mcv.getReg().?, abi_size)
...@@ -184551,7 +184521,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184551,7 +184521,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
184551 }184521 }
184552184522
184553 break :result null;184523 break :result null;
184554 }) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{184524 }) orelse return self.fail("TODO implement airShuffle from {f} and {f} to {f} with {f}", .{
184555 lhs_ty.fmt(pt),184525 lhs_ty.fmt(pt),
184556 rhs_ty.fmt(pt),184526 rhs_ty.fmt(pt),
184557 dst_ty.fmt(pt),184527 dst_ty.fmt(pt),
...@@ -184800,7 +184770,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184800,7 +184770,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {
184800 32, 64 => !self.hasFeature(.fma),184770 32, 64 => !self.hasFeature(.fma),
184801 else => unreachable,184771 else => unreachable,
184802 }) {184772 }) {
184803 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement airMulAdd for {}", .{184773 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement airMulAdd for {f}", .{
184804 ty.fmt(pt),184774 ty.fmt(pt),
184805 });184775 });
184806184776
...@@ -184930,7 +184900,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184930,7 +184900,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {
184930 else => unreachable,184900 else => unreachable,
184931 }184901 }
184932 else184902 else
184933 unreachable) orelse return self.fail("TODO implement airMulAdd for {}", .{ty.fmt(pt)});184903 unreachable) orelse return self.fail("TODO implement airMulAdd for {f}", .{ty.fmt(pt)});
184934184904
184935 var mops: [3]MCValue = undefined;184905 var mops: [3]MCValue = undefined;
184936 for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv;184906 for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv;
...@@ -185130,7 +185100,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -185130,7 +185100,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
185130 assert(classes.len == 1);185100 assert(classes.len == 1);
185131 unreachable;185101 unreachable;
185132 },185102 },
185133 else => return self.fail("TODO implement c_va_arg for {} on SysV", .{promote_ty.fmt(pt)}),185103 else => return self.fail("TODO implement c_va_arg for {f} on SysV", .{promote_ty.fmt(pt)}),
185134 }185104 }
185135185105
185136 if (unused) break :result .unreach;185106 if (unused) break :result .unreach;
...@@ -185779,7 +185749,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty...@@ -185779,7 +185749,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
185779 for (parts) |part| part_sizes += part.abiSize(zcu);185749 for (parts) |part| part_sizes += part.abiSize(zcu);
185780 if (part_sizes == ty.abiSize(zcu)) return parts;185750 if (part_sizes == ty.abiSize(zcu)) return parts;
185781 };185751 };
185782 return self.fail("TODO implement splitType({d}, {})", .{ parts_len, ty.fmt(pt) });185752 return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) });
185783}185753}
185784185754
185785/// Truncates the value in the register in place.185755/// Truncates the value in the register in place.
...@@ -186153,7 +186123,7 @@ const Temp = struct {...@@ -186153,7 +186123,7 @@ const Temp = struct {
186153 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);186123 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
186154 const mcv = temp.tracking(cg).short;186124 const mcv = temp.tracking(cg).short;
186155 switch (mcv) {186125 switch (mcv) {
186156 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186126 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186157 .register => |reg| {186127 .register => |reg| {
186158 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);186128 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
186159 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });186129 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
...@@ -186227,7 +186197,7 @@ const Temp = struct {...@@ -186227,7 +186197,7 @@ const Temp = struct {
186227 const new_temp_index = cg.next_temp_index;186197 const new_temp_index = cg.next_temp_index;
186228 cg.temp_type[@intFromEnum(new_temp_index)] = limb_ty;186198 cg.temp_type[@intFromEnum(new_temp_index)] = limb_ty;
186229 switch (temp.tracking(cg).short) {186199 switch (temp.tracking(cg).short) {
186230 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186200 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186231 .immediate => |imm| {186201 .immediate => |imm| {
186232 assert(limb_index == 0);186202 assert(limb_index == 0);
186233 new_temp_index.tracking(cg).* = .init(.{ .immediate = imm });186203 new_temp_index.tracking(cg).* = .init(.{ .immediate = imm });
...@@ -186568,7 +186538,7 @@ const Temp = struct {...@@ -186568,7 +186538,7 @@ const Temp = struct {
186568 },186538 },
186569 else => {},186539 else => {},
186570 }186540 }
186571 std.debug.panic("{s}: {} {}\n", .{ @src().fn_name, temp_tracking, overflow_temp_tracking });186541 std.debug.panic("{s}: {f} {f}\n", .{ @src().fn_name, temp_tracking, overflow_temp_tracking });
186572 }186542 }
186573186543
186574 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {186544 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {
...@@ -186658,7 +186628,7 @@ const Temp = struct {...@@ -186658,7 +186628,7 @@ const Temp = struct {
186658 while (try ptr.toLea(cg)) {}186628 while (try ptr.toLea(cg)) {}
186659 const val_mcv = val.tracking(cg).short;186629 const val_mcv = val.tracking(cg).short;
186660 switch (val_mcv) {186630 switch (val_mcv) {
186661 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186631 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186662 .register => |val_reg| try ptr.loadReg(val_ty, registerAlias(186632 .register => |val_reg| try ptr.loadReg(val_ty, registerAlias(
186663 val_reg,186633 val_reg,
186664 @intCast(val_ty.abiSize(cg.pt.zcu)),186634 @intCast(val_ty.abiSize(cg.pt.zcu)),
...@@ -186698,7 +186668,7 @@ const Temp = struct {...@@ -186698,7 +186668,7 @@ const Temp = struct {
186698 {}) {186668 {}) {
186699 const val_mcv = val.tracking(cg).short;186669 const val_mcv = val.tracking(cg).short;
186700 switch (val_mcv) {186670 switch (val_mcv) {
186701 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186671 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186702 .undef => if (opts.safe) {186672 .undef => if (opts.safe) {
186703 var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });186673 var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });
186704 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });186674 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
...@@ -186772,7 +186742,7 @@ const Temp = struct {...@@ -186772,7 +186742,7 @@ const Temp = struct {
186772 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));186742 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));
186773 break :first_ty opt_child;186743 break :first_ty opt_child;
186774 },186744 },
186775 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),186745 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
186776 });186746 });
186777 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));186747 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
186778 try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg);186748 try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg);
...@@ -186804,7 +186774,7 @@ const Temp = struct {...@@ -186804,7 +186774,7 @@ const Temp = struct {
186804186774
186805 fn readTo(src: *Temp, val_ty: Type, val_mcv: MCValue, opts: AccessOptions, cg: *CodeGen) InnerError!void {186775 fn readTo(src: *Temp, val_ty: Type, val_mcv: MCValue, opts: AccessOptions, cg: *CodeGen) InnerError!void {
186806 switch (val_mcv) {186776 switch (val_mcv) {
186807 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186777 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186808 .register => |val_reg| try src.readReg(opts.disp, val_ty, registerAlias(186778 .register => |val_reg| try src.readReg(opts.disp, val_ty, registerAlias(
186809 val_reg,186779 val_reg,
186810 @intCast(cg.unalignedSize(val_ty)),186780 @intCast(cg.unalignedSize(val_ty)),
...@@ -186844,7 +186814,7 @@ const Temp = struct {...@@ -186844,7 +186814,7 @@ const Temp = struct {
186844 {}) {186814 {}) {
186845 const val_mcv = val.tracking(cg).short;186815 const val_mcv = val.tracking(cg).short;
186846 switch (val_mcv) {186816 switch (val_mcv) {
186847 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186817 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186848 .none => {},186818 .none => {},
186849 .undef => if (opts.safe) {186819 .undef => if (opts.safe) {
186850 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));186820 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
...@@ -186905,7 +186875,7 @@ const Temp = struct {...@@ -186905,7 +186875,7 @@ const Temp = struct {
186905 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));186875 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));
186906 break :first_ty opt_child;186876 break :first_ty opt_child;
186907 },186877 },
186908 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),186878 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
186909 });186879 });
186910 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));186880 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
186911 try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg);186881 try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg);
...@@ -186960,7 +186930,7 @@ const Temp = struct {...@@ -186960,7 +186930,7 @@ const Temp = struct {
186960 assert(src_regs.len == std.math.divCeil(u16, int_info.bits, 64) catch unreachable);186930 assert(src_regs.len == std.math.divCeil(u16, int_info.bits, 64) catch unreachable);
186961 break :part_ty .u64;186931 break :part_ty .u64;
186962 } else part_ty: switch (ip.indexToKey(src_ty.toIntern())) {186932 } else part_ty: switch (ip.indexToKey(src_ty.toIntern())) {
186963 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),186933 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),
186964 .ptr_type => |ptr_info| {186934 .ptr_type => |ptr_info| {
186965 assert(ptr_info.flags.size == .slice);186935 assert(ptr_info.flags.size == .slice);
186966 assert(src_regs.len == 2);186936 assert(src_regs.len == 2);
...@@ -186971,7 +186941,7 @@ const Temp = struct {...@@ -186971,7 +186941,7 @@ const Temp = struct {
186971 break :part_ty try cg.pt.intType(.unsigned, @as(u16, 8) * @min(src_abi_size, 8));186941 break :part_ty try cg.pt.intType(.unsigned, @as(u16, 8) * @min(src_abi_size, 8));
186972 },186942 },
186973 .opt_type => |opt_child| switch (ip.indexToKey(opt_child)) {186943 .opt_type => |opt_child| switch (ip.indexToKey(opt_child)) {
186974 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),186944 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),
186975 .ptr_type => |ptr_info| {186945 .ptr_type => |ptr_info| {
186976 assert(ptr_info.flags.size == .slice);186946 assert(ptr_info.flags.size == .slice);
186977 assert(src_regs.len == 2);186947 assert(src_regs.len == 2);
...@@ -191677,12 +191647,12 @@ const Temp = struct {...@@ -191677,12 +191647,12 @@ const Temp = struct {
191677 break :result result;191647 break :result result;
191678 },191648 },
191679 };191649 };
191680 tracking_log.debug("{} => {} (birth)", .{ inst, result });191650 tracking_log.debug("{f} => {f} (birth)", .{ inst, result });
191681 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));191651 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));
191682 },191652 },
191683 .temp => |temp_index| {191653 .temp => |temp_index| {
191684 const temp_tracking = temp_index.tracking(cg);191654 const temp_tracking = temp_index.tracking(cg);
191685 tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short });191655 tracking_log.debug("{f} => {f} (birth)", .{ inst, temp_tracking.short });
191686 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short));191656 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short));
191687 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));191657 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
191688 },191658 },
...@@ -191757,7 +191727,7 @@ fn resetTemps(cg: *CodeGen, from_index: Temp.Index) InnerError!void {...@@ -191757,7 +191727,7 @@ fn resetTemps(cg: *CodeGen, from_index: Temp.Index) InnerError!void {
191757 const temp: Temp.Index = @enumFromInt(temp_index);191727 const temp: Temp.Index = @enumFromInt(temp_index);
191758 if (temp.isValid(cg)) {191728 if (temp.isValid(cg)) {
191759 any_valid = true;191729 any_valid = true;
191760 tracking_log.err("failed to kill {}: {}", .{191730 tracking_log.err("failed to kill {f}: {f}", .{
191761 temp.toIndex(),191731 temp.toIndex(),
191762 cg.temp_type[temp_index].fmt(cg.pt),191732 cg.temp_type[temp_index].fmt(cg.pt),
191763 });191733 });
src/arch/x86_64/Emit.zig+8-1
...@@ -707,7 +707,14 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI...@@ -707,7 +707,14 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
707 const comp = emit.bin_file.comp;707 const comp = emit.bin_file.comp;
708 const gpa = comp.gpa;708 const gpa = comp.gpa;
709 const start_offset: u32 = @intCast(emit.code.items.len);709 const start_offset: u32 = @intCast(emit.code.items.len);
710 try lowered_inst.encode(emit.code.writer(gpa), .{});710 {
711 var aw: std.io.Writer.Allocating = .fromArrayList(gpa, emit.code);
712 defer emit.code.* = aw.toArrayList();
713 lowered_inst.encode(&aw.writer, .{}) catch |err| switch (err) {
714 error.WriteFailed => return error.OutOfMemory,
715 else => |e| return e,
716 };
717 }
711 const end_offset: u32 = @intCast(emit.code.items.len);718 const end_offset: u32 = @intCast(emit.code.items.len);
712 for (reloc_info) |reloc| switch (reloc.target.type) {719 for (reloc_info) |reloc| switch (reloc.target.type) {
713 .inst => {720 .inst => {
src/arch/x86_64/Encoding.zig+16-15
...@@ -158,15 +158,7 @@ pub fn modRmExt(encoding: Encoding) u3 {...@@ -158,15 +158,7 @@ pub fn modRmExt(encoding: Encoding) u3 {
158 };158 };
159}159}
160160
161pub fn format(161pub fn format(encoding: Encoding, writer: *std.io.Writer) std.io.Writer.Error!void {
162 encoding: Encoding,
163 comptime fmt: []const u8,
164 options: std.fmt.FormatOptions,
165 writer: anytype,
166) !void {
167 _ = options;
168 _ = fmt;
169
170 var opc = encoding.opcode();162 var opc = encoding.opcode();
171 if (encoding.data.mode.isVex()) {163 if (encoding.data.mode.isVex()) {
172 try writer.writeAll("VEX.");164 try writer.writeAll("VEX.");
...@@ -187,7 +179,7 @@ pub fn format(...@@ -187,7 +179,7 @@ pub fn format(
187 },179 },
188 }180 }
189181
190 try writer.print(".{}", .{std.fmt.fmtSliceHexUpper(opc[0 .. opc.len - 1])});182 try writer.print(".{X}", .{opc[0 .. opc.len - 1]});
191 opc = opc[opc.len - 1 ..];183 opc = opc[opc.len - 1 ..];
192184
193 try writer.writeAll(".W");185 try writer.writeAll(".W");
...@@ -1014,19 +1006,28 @@ pub const Feature = enum {...@@ -1014,19 +1006,28 @@ pub const Feature = enum {
1014};1006};
10151007
1016fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize {1008fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize {
1017 var inst = Instruction{1009 var inst: Instruction = .{
1018 .prefix = prefix,1010 .prefix = prefix,
1019 .encoding = encoding,1011 .encoding = encoding,
1020 .ops = @splat(.none),1012 .ops = @splat(.none),
1021 };1013 };
1022 @memcpy(inst.ops[0..ops.len], ops);1014 @memcpy(inst.ops[0..ops.len], ops);
10231015
1024 var cwriter = std.io.countingWriter(std.io.null_writer);1016 // By using a buffer with maximum length of encoded instruction, we can use
1025 inst.encode(cwriter.writer(), .{1017 // the `end` field of the Writer for the count.
1018 var buf: [16]u8 = undefined;
1019 var trash: std.io.Writer.Discarding = .init(&buf);
1020 inst.encode(&trash.writer, .{
1026 .allow_frame_locs = true,1021 .allow_frame_locs = true,
1027 .allow_symbols = true,1022 .allow_symbols = true,
1028 }) catch unreachable; // Not allowed to fail here unless OOM.1023 }) catch {
1029 return @as(usize, @intCast(cwriter.bytes_written));1024 // Since the function signature for encode() does not mention under what
1025 // conditions it can fail, I have changed `unreachable` to `@panic` here.
1026 // This is a TODO item since it indicates this function
1027 // (`estimateInstructionLength`) has the wrong function signature.
1028 @panic("unexpected failure to encode");
1029 };
1030 return trash.writer.end;
1030}1031}
10311032
1032const mnemonic_to_encodings_map = init: {1033const mnemonic_to_encodings_map = init: {
src/arch/x86_64/bits.zig+2-29
...@@ -727,23 +727,6 @@ pub const FrameIndex = enum(u32) {...@@ -727,23 +727,6 @@ pub const FrameIndex = enum(u32) {
727 pub fn isNamed(fi: FrameIndex) bool {727 pub fn isNamed(fi: FrameIndex) bool {
728 return @intFromEnum(fi) < named_count;728 return @intFromEnum(fi) < named_count;
729 }729 }
730
731 pub fn format(
732 fi: FrameIndex,
733 comptime fmt: []const u8,
734 options: std.fmt.FormatOptions,
735 writer: anytype,
736 ) @TypeOf(writer).Error!void {
737 try writer.writeAll("FrameIndex");
738 if (fi.isNamed()) {
739 try writer.writeByte('.');
740 try writer.writeAll(@tagName(fi));
741 } else {
742 try writer.writeByte('(');
743 try std.fmt.formatType(@intFromEnum(fi), fmt, options, writer, 0);
744 try writer.writeByte(')');
745 }
746 }
747};730};
748731
749pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };732pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
...@@ -844,12 +827,7 @@ pub const Memory = struct {...@@ -844,12 +827,7 @@ pub const Memory = struct {
844 };827 };
845 }828 }
846829
847 pub fn format(830 pub fn format(s: Size, writer: *std.io.Writer) std.io.Writer.Error!void {
848 s: Size,
849 comptime _: []const u8,
850 _: std.fmt.FormatOptions,
851 writer: anytype,
852 ) @TypeOf(writer).Error!void {
853 if (s == .none) return;831 if (s == .none) return;
854 try writer.writeAll(@tagName(s));832 try writer.writeAll(@tagName(s));
855 switch (s) {833 switch (s) {
...@@ -914,12 +892,7 @@ pub const Immediate = union(enum) {...@@ -914,12 +892,7 @@ pub const Immediate = union(enum) {
914 return .{ .signed = x };892 return .{ .signed = x };
915 }893 }
916894
917 pub fn format(895 pub fn format(imm: Immediate, writer: *std.io.Writer) std.io.Writer.Error!void {
918 imm: Immediate,
919 comptime _: []const u8,
920 _: std.fmt.FormatOptions,
921 writer: anytype,
922 ) @TypeOf(writer).Error!void {
923 switch (imm) {896 switch (imm) {
924 inline else => |int| try writer.print("{d}", .{int}),897 inline else => |int| try writer.print("{d}", .{int}),
925 .nav => |nav_off| try writer.print("Nav({d}) + {d}", .{ @intFromEnum(nav_off.nav), nav_off.off }),898 .nav => |nav_off| try writer.print("Nav({d}) + {d}", .{ @intFromEnum(nav_off.nav), nav_off.off }),
src/arch/x86_64/encoder.zig+111-138
...@@ -3,6 +3,7 @@ const assert = std.debug.assert;...@@ -3,6 +3,7 @@ const assert = std.debug.assert;
3const log = std.log.scoped(.x86_64_encoder);3const log = std.log.scoped(.x86_64_encoder);
4const math = std.math;4const math = std.math;
5const testing = std.testing;5const testing = std.testing;
6const Writer = std.io.Writer;
67
7const bits = @import("bits.zig");8const bits = @import("bits.zig");
8const Encoding = @import("Encoding.zig");9const Encoding = @import("Encoding.zig");
...@@ -226,101 +227,81 @@ pub const Instruction = struct {...@@ -226,101 +227,81 @@ pub const Instruction = struct {
226 };227 };
227 }228 }
228229
229 fn format(230 const Format = struct {
230 op: Operand,
231 comptime unused_format_string: []const u8,
232 options: std.fmt.FormatOptions,
233 writer: anytype,
234 ) !void {
235 _ = op;
236 _ = unused_format_string;
237 _ = options;
238 _ = writer;
239 @compileError("do not format Operand directly; use fmt() instead");
240 }
241
242 const FormatContext = struct {
243 op: Operand,231 op: Operand,
244 enc_op: Encoding.Op,232 enc_op: Encoding.Op,
245 };
246233
247 fn fmtContext(234 fn default(f: Format, w: *Writer) Writer.Error!void {
248 ctx: FormatContext,235 const op = f.op;
249 comptime unused_format_string: []const u8,236 const enc_op = f.enc_op;
250 options: std.fmt.FormatOptions,237 switch (op) {
251 writer: anytype,238 .none => {},
252 ) @TypeOf(writer).Error!void {239 .reg => |reg| try w.writeAll(@tagName(reg)),
253 _ = unused_format_string;240 .mem => |mem| switch (mem) {
254 _ = options;241 .rip => |rip| {
255 const op = ctx.op;242 try w.print("{f} [rip", .{rip.ptr_size});
256 const enc_op = ctx.enc_op;243 if (rip.disp != 0) try w.print(" {c} 0x{x}", .{
257 switch (op) {244 @as(u8, if (rip.disp < 0) '-' else '+'),
258 .none => {},245 @abs(rip.disp),
259 .reg => |reg| try writer.writeAll(@tagName(reg)),246 });
260 .mem => |mem| switch (mem) {247 try w.writeByte(']');
261 .rip => |rip| {248 },
262 try writer.print("{} [rip", .{rip.ptr_size});249 .sib => |sib| {
263 if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{250 try w.print("{f} ", .{sib.ptr_size});
264 @as(u8, if (rip.disp < 0) '-' else '+'),
265 @abs(rip.disp),
266 });
267 try writer.writeByte(']');
268 },
269 .sib => |sib| {
270 try writer.print("{} ", .{sib.ptr_size});
271251
272 if (mem.isSegmentRegister()) {252 if (mem.isSegmentRegister()) {
273 return writer.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });253 return w.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });
274 }254 }
275255
276 try writer.writeByte('[');256 try w.writeByte('[');
277257
278 var any = true;258 var any = true;
279 switch (sib.base) {259 switch (sib.base) {
280 .none => any = false,260 .none => any = false,
281 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),261 .reg => |reg| try w.print("{s}", .{@tagName(reg)}),
282 .frame => |frame_index| try writer.print("{}", .{frame_index}),262 .frame => |frame_index| try w.print("{}", .{frame_index}),
283 .table => try writer.print("Table", .{}),263 .table => try w.print("Table", .{}),
284 .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}),264 .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}),
285 .nav => |nav| try writer.print("Nav({d})", .{@intFromEnum(nav)}),265 .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}),
286 .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}),266 .uav => |uav| try w.print("Uav({d})", .{@intFromEnum(uav.val)}),
287 .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{267 .lazy_sym => |lazy_sym| try w.print("LazySym({s}, {d})", .{
288 @tagName(lazy_sym.kind),268 @tagName(lazy_sym.kind),
289 @intFromEnum(lazy_sym.ty),269 @intFromEnum(lazy_sym.ty),
290 }),270 }),
291 .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),271 .extern_func => |extern_func| try w.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
292 }272 }
293 if (mem.scaleIndex()) |si| {273 if (mem.scaleIndex()) |si| {
294 if (any) try writer.writeAll(" + ");274 if (any) try w.writeAll(" + ");
295 try writer.print("{s} * {d}", .{ @tagName(si.index), si.scale });275 try w.print("{s} * {d}", .{ @tagName(si.index), si.scale });
296 any = true;276 any = true;
297 }277 }
298 if (sib.disp != 0 or !any) {278 if (sib.disp != 0 or !any) {
299 if (any)279 if (any)
300 try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')})280 try w.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')})
301 else if (sib.disp < 0)281 else if (sib.disp < 0)
302 try writer.writeByte('-');282 try w.writeByte('-');
303 try writer.print("0x{x}", .{@abs(sib.disp)});283 try w.print("0x{x}", .{@abs(sib.disp)});
304 any = true;284 any = true;
305 }285 }
306286
307 try writer.writeByte(']');287 try w.writeByte(']');
288 },
289 .moffs => |moffs| try w.print("{s}:0x{x}", .{
290 @tagName(moffs.seg),
291 moffs.offset,
292 }),
308 },293 },
309 .moffs => |moffs| try writer.print("{s}:0x{x}", .{294 .imm => |imm| if (enc_op.isSigned()) {
310 @tagName(moffs.seg),295 const imms = imm.asSigned(enc_op.immBitSize());
311 moffs.offset,296 if (imms < 0) try w.writeByte('-');
312 }),297 try w.print("0x{x}", .{@abs(imms)});
313 },298 } else try w.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}),
314 .imm => |imm| if (enc_op.isSigned()) {299 .bytes => unreachable,
315 const imms = imm.asSigned(enc_op.immBitSize());300 }
316 if (imms < 0) try writer.writeByte('-');
317 try writer.print("0x{x}", .{@abs(imms)});
318 } else try writer.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}),
319 .bytes => unreachable,
320 }301 }
321 }302 };
322303
323 pub fn fmt(op: Operand, enc_op: Encoding.Op) std.fmt.Formatter(fmtContext) {304 pub fn fmt(op: Operand, enc_op: Encoding.Op) std.fmt.Formatter(Format, Format.default) {
324 return .{ .data = .{ .op = op, .enc_op = enc_op } };305 return .{ .data = .{ .op = op, .enc_op = enc_op } };
325 }306 }
326 };307 };
...@@ -361,7 +342,7 @@ pub const Instruction = struct {...@@ -361,7 +342,7 @@ pub const Instruction = struct {
361 },342 },
362 },343 },
363 };344 };
364 log.debug("selected encoding: {}", .{encoding});345 log.debug("selected encoding: {f}", .{encoding});
365346
366 var inst: Instruction = .{347 var inst: Instruction = .{
367 .prefix = prefix,348 .prefix = prefix,
...@@ -372,30 +353,22 @@ pub const Instruction = struct {...@@ -372,30 +353,22 @@ pub const Instruction = struct {
372 return inst;353 return inst;
373 }354 }
374355
375 pub fn format(356 pub fn format(inst: Instruction, w: *Writer) Writer.Error!void {
376 inst: Instruction,
377 comptime unused_format_string: []const u8,
378 options: std.fmt.FormatOptions,
379 writer: anytype,
380 ) @TypeOf(writer).Error!void {
381 _ = unused_format_string;
382 _ = options;
383 switch (inst.prefix) {357 switch (inst.prefix) {
384 .none, .directive => {},358 .none, .directive => {},
385 else => try writer.print("{s} ", .{@tagName(inst.prefix)}),359 else => try w.print("{s} ", .{@tagName(inst.prefix)}),
386 }360 }
387 try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)});361 try w.print("{s}", .{@tagName(inst.encoding.mnemonic)});
388 for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| {362 for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| {
389 if (op == .none) break;363 if (op == .none) break;
390 if (i > 0) try writer.writeByte(',');364 if (i > 0) try w.writeByte(',');
391 try writer.writeByte(' ');365 try w.print(" {f}", .{op.fmt(enc)});
392 try writer.print("{}", .{op.fmt(enc)});
393 }366 }
394 }367 }
395368
396 pub fn encode(inst: Instruction, writer: anytype, comptime opts: Options) !void {369 pub fn encode(inst: Instruction, w: *Writer, comptime opts: Options) !void {
397 assert(inst.prefix != .directive);370 assert(inst.prefix != .directive);
398 const encoder = Encoder(@TypeOf(writer), opts){ .writer = writer };371 const encoder: Encoder(opts) = .{ .w = w };
399 const enc = inst.encoding;372 const enc = inst.encoding;
400 const data = enc.data;373 const data = enc.data;
401374
...@@ -801,9 +774,9 @@ pub const LegacyPrefixes = packed struct {...@@ -801,9 +774,9 @@ pub const LegacyPrefixes = packed struct {
801774
802pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool = false };775pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool = false };
803776
804fn Encoder(comptime T: type, comptime opts: Options) type {777fn Encoder(comptime opts: Options) type {
805 return struct {778 return struct {
806 writer: T,779 w: *Writer,
807780
808 const Self = @This();781 const Self = @This();
809 pub const options = opts;782 pub const options = opts;
...@@ -818,31 +791,31 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -818,31 +791,31 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
818 // Hopefully this path isn't taken very often, so we'll do it the slow way for now791 // Hopefully this path isn't taken very often, so we'll do it the slow way for now
819792
820 // LOCK793 // LOCK
821 if (prefixes.prefix_f0) try self.writer.writeByte(0xf0);794 if (prefixes.prefix_f0) try self.w.writeByte(0xf0);
822 // REPNZ, REPNE, REP, Scalar Double-precision795 // REPNZ, REPNE, REP, Scalar Double-precision
823 if (prefixes.prefix_f2) try self.writer.writeByte(0xf2);796 if (prefixes.prefix_f2) try self.w.writeByte(0xf2);
824 // REPZ, REPE, REP, Scalar Single-precision797 // REPZ, REPE, REP, Scalar Single-precision
825 if (prefixes.prefix_f3) try self.writer.writeByte(0xf3);798 if (prefixes.prefix_f3) try self.w.writeByte(0xf3);
826799
827 // CS segment override or Branch not taken800 // CS segment override or Branch not taken
828 if (prefixes.prefix_2e) try self.writer.writeByte(0x2e);801 if (prefixes.prefix_2e) try self.w.writeByte(0x2e);
829 // DS segment override802 // DS segment override
830 if (prefixes.prefix_36) try self.writer.writeByte(0x36);803 if (prefixes.prefix_36) try self.w.writeByte(0x36);
831 // ES segment override804 // ES segment override
832 if (prefixes.prefix_26) try self.writer.writeByte(0x26);805 if (prefixes.prefix_26) try self.w.writeByte(0x26);
833 // FS segment override806 // FS segment override
834 if (prefixes.prefix_64) try self.writer.writeByte(0x64);807 if (prefixes.prefix_64) try self.w.writeByte(0x64);
835 // GS segment override808 // GS segment override
836 if (prefixes.prefix_65) try self.writer.writeByte(0x65);809 if (prefixes.prefix_65) try self.w.writeByte(0x65);
837810
838 // Branch taken811 // Branch taken
839 if (prefixes.prefix_3e) try self.writer.writeByte(0x3e);812 if (prefixes.prefix_3e) try self.w.writeByte(0x3e);
840813
841 // Operand size override814 // Operand size override
842 if (prefixes.prefix_66) try self.writer.writeByte(0x66);815 if (prefixes.prefix_66) try self.w.writeByte(0x66);
843816
844 // Address size override817 // Address size override
845 if (prefixes.prefix_67) try self.writer.writeByte(0x67);818 if (prefixes.prefix_67) try self.w.writeByte(0x67);
846 }819 }
847 }820 }
848821
...@@ -850,7 +823,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -850,7 +823,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
850 ///823 ///
851 /// Note that this flag is overridden by REX.W, if both are present.824 /// Note that this flag is overridden by REX.W, if both are present.
852 pub fn prefix16BitMode(self: Self) !void {825 pub fn prefix16BitMode(self: Self) !void {
853 try self.writer.writeByte(0x66);826 try self.w.writeByte(0x66);
854 }827 }
855828
856 /// Encodes a REX prefix byte given all the fields829 /// Encodes a REX prefix byte given all the fields
...@@ -869,7 +842,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -869,7 +842,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
869 if (fields.x) byte |= 0b0010;842 if (fields.x) byte |= 0b0010;
870 if (fields.b) byte |= 0b0001;843 if (fields.b) byte |= 0b0001;
871844
872 try self.writer.writeByte(byte);845 try self.w.writeByte(byte);
873 }846 }
874847
875 /// Encodes a VEX prefix given all the fields848 /// Encodes a VEX prefix given all the fields
...@@ -877,24 +850,24 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -877,24 +850,24 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
877 /// See struct `Vex` for a description of each field.850 /// See struct `Vex` for a description of each field.
878 pub fn vex(self: Self, fields: Vex) !void {851 pub fn vex(self: Self, fields: Vex) !void {
879 if (fields.is3Byte()) {852 if (fields.is3Byte()) {
880 try self.writer.writeByte(0b1100_0100);853 try self.w.writeByte(0b1100_0100);
881854
882 try self.writer.writeByte(855 try self.w.writeByte(
883 @as(u8, ~@intFromBool(fields.r)) << 7 |856 @as(u8, ~@intFromBool(fields.r)) << 7 |
884 @as(u8, ~@intFromBool(fields.x)) << 6 |857 @as(u8, ~@intFromBool(fields.x)) << 6 |
885 @as(u8, ~@intFromBool(fields.b)) << 5 |858 @as(u8, ~@intFromBool(fields.b)) << 5 |
886 @as(u8, @intFromEnum(fields.m)) << 0,859 @as(u8, @intFromEnum(fields.m)) << 0,
887 );860 );
888861
889 try self.writer.writeByte(862 try self.w.writeByte(
890 @as(u8, @intFromBool(fields.w)) << 7 |863 @as(u8, @intFromBool(fields.w)) << 7 |
891 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |864 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |
892 @as(u8, @intFromBool(fields.l)) << 2 |865 @as(u8, @intFromBool(fields.l)) << 2 |
893 @as(u8, @intFromEnum(fields.p)) << 0,866 @as(u8, @intFromEnum(fields.p)) << 0,
894 );867 );
895 } else {868 } else {
896 try self.writer.writeByte(0b1100_0101);869 try self.w.writeByte(0b1100_0101);
897 try self.writer.writeByte(870 try self.w.writeByte(
898 @as(u8, ~@intFromBool(fields.r)) << 7 |871 @as(u8, ~@intFromBool(fields.r)) << 7 |
899 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |872 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |
900 @as(u8, @intFromBool(fields.l)) << 2 |873 @as(u8, @intFromBool(fields.l)) << 2 |
...@@ -909,7 +882,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -909,7 +882,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
909882
910 /// Encodes a 1 byte opcode883 /// Encodes a 1 byte opcode
911 pub fn opcode_1byte(self: Self, opcode: u8) !void {884 pub fn opcode_1byte(self: Self, opcode: u8) !void {
912 try self.writer.writeByte(opcode);885 try self.w.writeByte(opcode);
913 }886 }
914887
915 /// Encodes a 2 byte opcode888 /// Encodes a 2 byte opcode
...@@ -918,7 +891,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -918,7 +891,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
918 ///891 ///
919 /// encoder.opcode_2byte(0x0f, 0xaf);892 /// encoder.opcode_2byte(0x0f, 0xaf);
920 pub fn opcode_2byte(self: Self, prefix: u8, opcode: u8) !void {893 pub fn opcode_2byte(self: Self, prefix: u8, opcode: u8) !void {
921 try self.writer.writeAll(&.{ prefix, opcode });894 try self.w.writeAll(&.{ prefix, opcode });
922 }895 }
923896
924 /// Encodes a 3 byte opcode897 /// Encodes a 3 byte opcode
...@@ -927,7 +900,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -927,7 +900,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
927 ///900 ///
928 /// encoder.opcode_3byte(0xf2, 0x0f, 0x10);901 /// encoder.opcode_3byte(0xf2, 0x0f, 0x10);
929 pub fn opcode_3byte(self: Self, prefix_1: u8, prefix_2: u8, opcode: u8) !void {902 pub fn opcode_3byte(self: Self, prefix_1: u8, prefix_2: u8, opcode: u8) !void {
930 try self.writer.writeAll(&.{ prefix_1, prefix_2, opcode });903 try self.w.writeAll(&.{ prefix_1, prefix_2, opcode });
931 }904 }
932905
933 /// Encodes a 1 byte opcode with a reg field906 /// Encodes a 1 byte opcode with a reg field
...@@ -935,7 +908,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -935,7 +908,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
935 /// Remember to add a REX prefix byte if reg is extended!908 /// Remember to add a REX prefix byte if reg is extended!
936 pub fn opcode_withReg(self: Self, opcode: u8, reg: u3) !void {909 pub fn opcode_withReg(self: Self, opcode: u8, reg: u3) !void {
937 assert(opcode & 0b111 == 0);910 assert(opcode & 0b111 == 0);
938 try self.writer.writeByte(opcode | reg);911 try self.w.writeByte(opcode | reg);
939 }912 }
940913
941 // ------914 // ------
...@@ -946,7 +919,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -946,7 +919,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
946 ///919 ///
947 /// Remember to add a REX prefix byte if reg or rm are extended!920 /// Remember to add a REX prefix byte if reg or rm are extended!
948 pub fn modRm(self: Self, mod: u2, reg_or_opx: u3, rm: u3) !void {921 pub fn modRm(self: Self, mod: u2, reg_or_opx: u3, rm: u3) !void {
949 try self.writer.writeByte(@as(u8, mod) << 6 | @as(u8, reg_or_opx) << 3 | rm);922 try self.w.writeByte(@as(u8, mod) << 6 | @as(u8, reg_or_opx) << 3 | rm);
950 }923 }
951924
952 /// Construct a ModR/M byte using direct r/m addressing925 /// Construct a ModR/M byte using direct r/m addressing
...@@ -1032,7 +1005,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1032,7 +1005,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1032 ///1005 ///
1033 /// Remember to add a REX prefix byte if index or base are extended!1006 /// Remember to add a REX prefix byte if index or base are extended!
1034 pub fn sib(self: Self, scale: u2, index: u3, base: u3) !void {1007 pub fn sib(self: Self, scale: u2, index: u3, base: u3) !void {
1035 try self.writer.writeByte(@as(u8, scale) << 6 | @as(u8, index) << 3 | base);1008 try self.w.writeByte(@as(u8, scale) << 6 | @as(u8, index) << 3 | base);
1036 }1009 }
10371010
1038 /// Construct a SIB byte with scale * index + base, no frills.1011 /// Construct a SIB byte with scale * index + base, no frills.
...@@ -1124,42 +1097,42 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1124,42 +1097,42 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1124 ///1097 ///
1125 /// It is sign-extended to 64 bits by the cpu.1098 /// It is sign-extended to 64 bits by the cpu.
1126 pub fn disp8(self: Self, disp: i8) !void {1099 pub fn disp8(self: Self, disp: i8) !void {
1127 try self.writer.writeByte(@as(u8, @bitCast(disp)));1100 try self.w.writeByte(@as(u8, @bitCast(disp)));
1128 }1101 }
11291102
1130 /// Encode an 32 bit displacement1103 /// Encode an 32 bit displacement
1131 ///1104 ///
1132 /// It is sign-extended to 64 bits by the cpu.1105 /// It is sign-extended to 64 bits by the cpu.
1133 pub fn disp32(self: Self, disp: i32) !void {1106 pub fn disp32(self: Self, disp: i32) !void {
1134 try self.writer.writeInt(i32, disp, .little);1107 try self.w.writeInt(i32, disp, .little);
1135 }1108 }
11361109
1137 /// Encode an 8 bit immediate1110 /// Encode an 8 bit immediate
1138 ///1111 ///
1139 /// It is sign-extended to 64 bits by the cpu.1112 /// It is sign-extended to 64 bits by the cpu.
1140 pub fn imm8(self: Self, imm: u8) !void {1113 pub fn imm8(self: Self, imm: u8) !void {
1141 try self.writer.writeByte(imm);1114 try self.w.writeByte(imm);
1142 }1115 }
11431116
1144 /// Encode an 16 bit immediate1117 /// Encode an 16 bit immediate
1145 ///1118 ///
1146 /// It is sign-extended to 64 bits by the cpu.1119 /// It is sign-extended to 64 bits by the cpu.
1147 pub fn imm16(self: Self, imm: u16) !void {1120 pub fn imm16(self: Self, imm: u16) !void {
1148 try self.writer.writeInt(u16, imm, .little);1121 try self.w.writeInt(u16, imm, .little);
1149 }1122 }
11501123
1151 /// Encode an 32 bit immediate1124 /// Encode an 32 bit immediate
1152 ///1125 ///
1153 /// It is sign-extended to 64 bits by the cpu.1126 /// It is sign-extended to 64 bits by the cpu.
1154 pub fn imm32(self: Self, imm: u32) !void {1127 pub fn imm32(self: Self, imm: u32) !void {
1155 try self.writer.writeInt(u32, imm, .little);1128 try self.w.writeInt(u32, imm, .little);
1156 }1129 }
11571130
1158 /// Encode an 64 bit immediate1131 /// Encode an 64 bit immediate
1159 ///1132 ///
1160 /// It is sign-extended to 64 bits by the cpu.1133 /// It is sign-extended to 64 bits by the cpu.
1161 pub fn imm64(self: Self, imm: u64) !void {1134 pub fn imm64(self: Self, imm: u64) !void {
1162 try self.writer.writeInt(u64, imm, .little);1135 try self.w.writeInt(u64, imm, .little);
1163 }1136 }
1164 };1137 };
1165}1138}
...@@ -1205,9 +1178,9 @@ pub const Vex = struct {...@@ -1205,9 +1178,9 @@ pub const Vex = struct {
1205fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {1178fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {
1206 assert(expected.len > 0);1179 assert(expected.len > 0);
1207 if (std.mem.eql(u8, expected, given)) return;1180 if (std.mem.eql(u8, expected, given)) return;
1208 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(expected)});1181 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{expected});
1209 defer testing.allocator.free(expected_fmt);1182 defer testing.allocator.free(expected_fmt);
1210 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(given)});1183 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
1211 defer testing.allocator.free(given_fmt);1184 defer testing.allocator.free(given_fmt);
1212 const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;1185 const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
1213 const padding = try testing.allocator.alloc(u8, idx + 5);1186 const padding = try testing.allocator.alloc(u8, idx + 5);
...@@ -2217,10 +2190,10 @@ const Assembler = struct {...@@ -2217,10 +2190,10 @@ const Assembler = struct {
2217 };2190 };
2218 }2191 }
22192192
2220 pub fn assemble(as: *Assembler, writer: anytype) !void {2193 pub fn assemble(as: *Assembler, w: *Writer) !void {
2221 while (try as.next()) |parsed_inst| {2194 while (try as.next()) |parsed_inst| {
2222 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);2195 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);
2223 try inst.encode(writer, .{});2196 try inst.encode(w, .{});
2224 }2197 }
2225 }2198 }
22262199
src/codegen.zig+6-6
...@@ -237,7 +237,7 @@ pub fn generateLazySymbol(...@@ -237,7 +237,7 @@ pub fn generateLazySymbol(
237 const target = &comp.root_mod.resolved_target.result;237 const target = &comp.root_mod.resolved_target.result;
238 const endian = target.cpu.arch.endian();238 const endian = target.cpu.arch.endian();
239239
240 log.debug("generateLazySymbol: kind = {s}, ty = {}", .{240 log.debug("generateLazySymbol: kind = {s}, ty = {f}", .{
241 @tagName(lazy_sym.kind),241 @tagName(lazy_sym.kind),
242 Type.fromInterned(lazy_sym.ty).fmt(pt),242 Type.fromInterned(lazy_sym.ty).fmt(pt),
243 });243 });
...@@ -277,7 +277,7 @@ pub fn generateLazySymbol(...@@ -277,7 +277,7 @@ pub fn generateLazySymbol(
277 code.appendAssumeCapacity(0);277 code.appendAssumeCapacity(0);
278 }278 }
279 } else {279 } else {
280 return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {}", .{280 return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{
281 @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),281 @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),
282 });282 });
283 }283 }
...@@ -310,7 +310,7 @@ pub fn generateSymbol(...@@ -310,7 +310,7 @@ pub fn generateSymbol(
310 const target = zcu.getTarget();310 const target = zcu.getTarget();
311 const endian = target.cpu.arch.endian();311 const endian = target.cpu.arch.endian();
312312
313 log.debug("generateSymbol: val = {}", .{val.fmtValue(pt)});313 log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)});
314314
315 if (val.isUndefDeep(zcu)) {315 if (val.isUndefDeep(zcu)) {
316 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;316 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
...@@ -767,7 +767,7 @@ fn lowerUavRef(...@@ -767,7 +767,7 @@ fn lowerUavRef(
767 const uav_ty = Type.fromInterned(ip.typeOf(uav_val));767 const uav_ty = Type.fromInterned(ip.typeOf(uav_val));
768 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";768 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
769769
770 log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)});770 log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(pt)});
771 try code.ensureUnusedCapacity(gpa, ptr_width_bytes);771 try code.ensureUnusedCapacity(gpa, ptr_width_bytes);
772772
773 if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) {773 if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) {
...@@ -913,7 +913,7 @@ pub fn genNavRef(...@@ -913,7 +913,7 @@ pub fn genNavRef(
913 const zcu = pt.zcu;913 const zcu = pt.zcu;
914 const ip = &zcu.intern_pool;914 const ip = &zcu.intern_pool;
915 const nav = ip.getNav(nav_index);915 const nav = ip.getNav(nav_index);
916 log.debug("genNavRef({})", .{nav.fqn.fmt(ip)});916 log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)});
917917
918 const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|918 const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|
919 .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }919 .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }
...@@ -1065,7 +1065,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo...@@ -1065,7 +1065,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
1065 const ip = &zcu.intern_pool;1065 const ip = &zcu.intern_pool;
1066 const ty = val.typeOf(zcu);1066 const ty = val.typeOf(zcu);
10671067
1068 log.debug("lowerValue(@as({}, {}))", .{ ty.fmt(pt), val.fmtValue(pt) });1068 log.debug("lowerValue(@as({f}, {f}))", .{ ty.fmt(pt), val.fmtValue(pt) });
10691069
1070 if (val.isUndef(zcu)) return .undef;1070 if (val.isUndef(zcu)) return .undef;
10711071
src/codegen/c.zig+2215-2164
...@@ -4,6 +4,7 @@ const assert = std.debug.assert;...@@ -4,6 +4,7 @@ const assert = std.debug.assert;
4const mem = std.mem;4const mem = std.mem;
5const log = std.log.scoped(.c);5const log = std.log.scoped(.c);
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
7const Writer = std.io.Writer;
78
8const dev = @import("../dev.zig");9const dev = @import("../dev.zig");
9const link = @import("../link.zig");10const link = @import("../link.zig");
...@@ -55,6 +56,7 @@ pub const Mir = struct {...@@ -55,6 +56,7 @@ pub const Mir = struct {
55 /// less than the natural alignment.56 /// less than the natural alignment.
56 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),57 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
57 // These remaining fields are essentially just an owned version of `link.C.AvBlock`.58 // These remaining fields are essentially just an owned version of `link.C.AvBlock`.
59 code_header: []u8,
58 code: []u8,60 code: []u8,
59 fwd_decl: []u8,61 fwd_decl: []u8,
60 ctype_pool: CType.Pool,62 ctype_pool: CType.Pool,
...@@ -62,6 +64,7 @@ pub const Mir = struct {...@@ -62,6 +64,7 @@ pub const Mir = struct {
6264
63 pub fn deinit(mir: *Mir, gpa: Allocator) void {65 pub fn deinit(mir: *Mir, gpa: Allocator) void {
64 mir.uavs.deinit(gpa);66 mir.uavs.deinit(gpa);
67 gpa.free(mir.code_header);
65 gpa.free(mir.code);68 gpa.free(mir.code);
66 gpa.free(mir.fwd_decl);69 gpa.free(mir.fwd_decl);
67 mir.ctype_pool.deinit(gpa);70 mir.ctype_pool.deinit(gpa);
...@@ -69,6 +72,8 @@ pub const Mir = struct {...@@ -69,6 +72,8 @@ pub const Mir = struct {
69 }72 }
70};73};
7174
75pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail};
76
72pub const CType = @import("c/Type.zig");77pub const CType = @import("c/Type.zig");
7378
74pub const CValue = union(enum) {79pub const CValue = union(enum) {
...@@ -340,53 +345,61 @@ fn isReservedIdent(ident: []const u8) bool {...@@ -340,53 +345,61 @@ fn isReservedIdent(ident: []const u8) bool {
340 } else return reserved_idents.has(ident);345 } else return reserved_idents.has(ident);
341}346}
342347
343fn formatIdent(348fn formatIdentSolo(ident: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
344 ident: []const u8,349 return formatIdentOptions(ident, w, true);
345 comptime fmt_str: []const u8,350}
346 _: std.fmt.FormatOptions,351
347 writer: anytype,352fn formatIdentUnsolo(ident: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
348) @TypeOf(writer).Error!void {353 return formatIdentOptions(ident, w, false);
349 const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident.354}
355
356fn formatIdentOptions(ident: []const u8, w: *std.io.Writer, solo: bool) std.io.Writer.Error!void {
350 if (solo and isReservedIdent(ident)) {357 if (solo and isReservedIdent(ident)) {
351 try writer.writeAll("zig_e_");358 try w.writeAll("zig_e_");
352 }359 }
353 for (ident, 0..) |c, i| {360 for (ident, 0..) |c, i| {
354 switch (c) {361 switch (c) {
355 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c),362 'a'...'z', 'A'...'Z', '_' => try w.writeByte(c),
356 '.' => try writer.writeByte('_'),363 '.' => try w.writeByte('_'),
357 '0'...'9' => if (i == 0) {364 '0'...'9' => if (i == 0) {
358 try writer.print("_{x:2}", .{c});365 try w.print("_{x:2}", .{c});
359 } else {366 } else {
360 try writer.writeByte(c);367 try w.writeByte(c);
361 },368 },
362 else => try writer.print("_{x:2}", .{c}),369 else => try w.print("_{x:2}", .{c}),
363 }370 }
364 }371 }
365}372}
366pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {373
374pub fn fmtIdentSolo(ident: []const u8) std.fmt.Formatter([]const u8, formatIdentSolo) {
375 return .{ .data = ident };
376}
377
378pub fn fmtIdentUnsolo(ident: []const u8) std.fmt.Formatter([]const u8, formatIdentUnsolo) {
367 return .{ .data = ident };379 return .{ .data = ident };
368}380}
369381
370const CTypePoolStringFormatData = struct {382const CTypePoolStringFormatData = struct {
371 ctype_pool_string: CType.Pool.String,383 ctype_pool_string: CType.Pool.String,
372 ctype_pool: *const CType.Pool,384 ctype_pool: *const CType.Pool,
385 solo: bool,
373};386};
374fn formatCTypePoolString(387fn formatCTypePoolString(data: CTypePoolStringFormatData, w: *std.io.Writer) std.io.Writer.Error!void {
375 data: CTypePoolStringFormatData,
376 comptime fmt_str: []const u8,
377 fmt_opts: std.fmt.FormatOptions,
378 writer: anytype,
379) @TypeOf(writer).Error!void {
380 if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice|388 if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice|
381 try formatIdent(slice, fmt_str, fmt_opts, writer)389 try formatIdentOptions(slice, w, data.solo)
382 else390 else
383 try writer.print("{}", .{data.ctype_pool_string.fmt(data.ctype_pool)});391 try w.print("{f}", .{data.ctype_pool_string.fmt(data.ctype_pool)});
384}392}
385pub fn fmtCTypePoolString(393pub fn fmtCTypePoolString(
386 ctype_pool_string: CType.Pool.String,394 ctype_pool_string: CType.Pool.String,
387 ctype_pool: *const CType.Pool,395 ctype_pool: *const CType.Pool,
388) std.fmt.Formatter(formatCTypePoolString) {396 solo: bool,
389 return .{ .data = .{ .ctype_pool_string = ctype_pool_string, .ctype_pool = ctype_pool } };397) std.fmt.Formatter(CTypePoolStringFormatData, formatCTypePoolString) {
398 return .{ .data = .{
399 .ctype_pool_string = ctype_pool_string,
400 .ctype_pool = ctype_pool,
401 .solo = solo,
402 } };
390}403}
391404
392// Returns true if `formatIdent` would make any edits to ident.405// Returns true if `formatIdent` would make any edits to ident.
...@@ -440,18 +453,18 @@ pub const Function = struct {...@@ -440,18 +453,18 @@ pub const Function = struct {
440 const ty = f.typeOf(ref);453 const ty = f.typeOf(ref);
441454
442 const result: CValue = if (lowersToArray(ty, pt)) result: {455 const result: CValue = if (lowersToArray(ty, pt)) result: {
443 const writer = f.object.codeHeaderWriter();456 const ch = &f.object.code_header.writer;
444 const decl_c_value = try f.allocLocalValue(.{457 const decl_c_value = try f.allocLocalValue(.{
445 .ctype = try f.ctypeFromType(ty, .complete),458 .ctype = try f.ctypeFromType(ty, .complete),
446 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),459 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),
447 });460 });
448 const gpa = f.object.dg.gpa;461 const gpa = f.object.dg.gpa;
449 try f.allocs.put(gpa, decl_c_value.new_local, false);462 try f.allocs.put(gpa, decl_c_value.new_local, false);
450 try writer.writeAll("static ");463 try ch.writeAll("static ");
451 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, .none, .complete);464 try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete);
452 try writer.writeAll(" = ");465 try ch.writeAll(" = ");
453 try f.object.dg.renderValue(writer, val, .StaticInitializer);466 try f.object.dg.renderValue(ch, val, .StaticInitializer);
454 try writer.writeAll(";\n ");467 try ch.writeAll(";\n ");
455 break :result .{ .local = decl_c_value.new_local };468 break :result .{ .local = decl_c_value.new_local };
456 } else .{ .constant = val };469 } else .{ .constant = val };
457470
...@@ -504,7 +517,7 @@ pub const Function = struct {...@@ -504,7 +517,7 @@ pub const Function = struct {
504 return result;517 return result;
505 }518 }
506519
507 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {520 fn writeCValue(f: *Function, w: *Writer, c_value: CValue, location: ValueRenderLocation) !void {
508 switch (c_value) {521 switch (c_value) {
509 .none => unreachable,522 .none => unreachable,
510 .new_local, .local => |i| try w.print("t{d}", .{i}),523 .new_local, .local => |i| try w.print("t{d}", .{i}),
...@@ -517,7 +530,7 @@ pub const Function = struct {...@@ -517,7 +530,7 @@ pub const Function = struct {
517 }530 }
518 }531 }
519532
520 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {533 fn writeCValueDeref(f: *Function, w: *Writer, c_value: CValue) !void {
521 switch (c_value) {534 switch (c_value) {
522 .none => unreachable,535 .none => unreachable,
523 .new_local, .local, .constant => {536 .new_local, .local, .constant => {
...@@ -538,41 +551,41 @@ pub const Function = struct {...@@ -538,41 +551,41 @@ pub const Function = struct {
538551
539 fn writeCValueMember(552 fn writeCValueMember(
540 f: *Function,553 f: *Function,
541 writer: anytype,554 w: *Writer,
542 c_value: CValue,555 c_value: CValue,
543 member: CValue,556 member: CValue,
544 ) error{ OutOfMemory, AnalysisFail }!void {557 ) Error!void {
545 switch (c_value) {558 switch (c_value) {
546 .new_local, .local, .local_ref, .constant, .arg, .arg_array => {559 .new_local, .local, .local_ref, .constant, .arg, .arg_array => {
547 try f.writeCValue(writer, c_value, .Other);560 try f.writeCValue(w, c_value, .Other);
548 try writer.writeByte('.');561 try w.writeByte('.');
549 try f.writeCValue(writer, member, .Other);562 try f.writeCValue(w, member, .Other);
550 },563 },
551 else => return f.object.dg.writeCValueMember(writer, c_value, member),564 else => return f.object.dg.writeCValueMember(w, c_value, member),
552 }565 }
553 }566 }
554567
555 fn writeCValueDerefMember(f: *Function, writer: anytype, c_value: CValue, member: CValue) !void {568 fn writeCValueDerefMember(f: *Function, w: *Writer, c_value: CValue, member: CValue) !void {
556 switch (c_value) {569 switch (c_value) {
557 .new_local, .local, .arg, .arg_array => {570 .new_local, .local, .arg, .arg_array => {
558 try f.writeCValue(writer, c_value, .Other);571 try f.writeCValue(w, c_value, .Other);
559 try writer.writeAll("->");572 try w.writeAll("->");
560 },573 },
561 .constant => {574 .constant => {
562 try writer.writeByte('(');575 try w.writeByte('(');
563 try f.writeCValue(writer, c_value, .Other);576 try f.writeCValue(w, c_value, .Other);
564 try writer.writeAll(")->");577 try w.writeAll(")->");
565 },578 },
566 .local_ref => {579 .local_ref => {
567 try f.writeCValueDeref(writer, c_value);580 try f.writeCValueDeref(w, c_value);
568 try writer.writeByte('.');581 try w.writeByte('.');
569 },582 },
570 else => return f.object.dg.writeCValueDerefMember(writer, c_value, member),583 else => return f.object.dg.writeCValueDerefMember(w, c_value, member),
571 }584 }
572 try f.writeCValue(writer, member, .Other);585 try f.writeCValue(w, member, .Other);
573 }586 }
574587
575 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {588 fn fail(f: *Function, comptime format: []const u8, args: anytype) Error {
576 return f.object.dg.fail(format, args);589 return f.object.dg.fail(format, args);
577 }590 }
578591
...@@ -584,20 +597,24 @@ pub const Function = struct {...@@ -584,20 +597,24 @@ pub const Function = struct {
584 return f.object.dg.byteSize(ctype);597 return f.object.dg.byteSize(ctype);
585 }598 }
586599
587 fn renderType(f: *Function, w: anytype, ctype: Type) !void {600 fn renderType(f: *Function, w: *Writer, ctype: Type) !void {
588 return f.object.dg.renderType(w, ctype);601 return f.object.dg.renderType(w, ctype);
589 }602 }
590603
591 fn renderCType(f: *Function, w: anytype, ctype: CType) !void {604 fn renderCType(f: *Function, w: *Writer, ctype: CType) !void {
592 return f.object.dg.renderCType(w, ctype);605 return f.object.dg.renderCType(w, ctype);
593 }606 }
594607
595 fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {608 fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
596 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);609 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
597 }610 }
598611
599 fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) {612 fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
600 return f.object.dg.fmtIntLiteral(val, .Other);613 return f.object.dg.fmtIntLiteralDec(val, .Other);
614 }
615
616 fn fmtIntLiteralHex(f: *Function, val: Value) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
617 return f.object.dg.fmtIntLiteralHex(val, .Other);
601 }618 }
602619
603 fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 {620 fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 {
...@@ -614,16 +631,16 @@ pub const Function = struct {...@@ -614,16 +631,16 @@ pub const Function = struct {
614 gop.value_ptr.* = .{631 gop.value_ptr.* = .{
615 .fn_name = switch (key) {632 .fn_name = switch (key) {
616 .tag_name,633 .tag_name,
617 => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{634 => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{
618 @tagName(key),635 @tagName(key),
619 fmtIdent(ip.loadEnumType(enum_ty).name.toSlice(ip)),636 fmtIdentUnsolo(ip.loadEnumType(enum_ty).name.toSlice(ip)),
620 @intFromEnum(enum_ty),637 @intFromEnum(enum_ty),
621 }),638 }),
622 .never_tail,639 .never_tail,
623 .never_inline,640 .never_inline,
624 => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{641 => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{
625 @tagName(key),642 @tagName(key),
626 fmtIdent(ip.getNav(owner_nav).name.toSlice(ip)),643 fmtIdentUnsolo(ip.getNav(owner_nav).name.toSlice(ip)),
627 @intFromEnum(owner_nav),644 @intFromEnum(owner_nav),
628 }),645 }),
629 },646 },
...@@ -659,12 +676,12 @@ pub const Function = struct {...@@ -659,12 +676,12 @@ pub const Function = struct {
659 },676 },
660 else => {},677 else => {},
661 }678 }
662 const writer = f.object.writer();679 const w = &f.object.code.writer;
663 const a = try Assignment.start(f, writer, ctype);680 const a = try Assignment.start(f, w, ctype);
664 try f.writeCValue(writer, dst, .Other);681 try f.writeCValue(w, dst, .Other);
665 try a.assign(f, writer);682 try a.assign(f, w);
666 try f.writeCValue(writer, src, .Other);683 try f.writeCValue(w, src, .Other);
667 try a.end(f, writer);684 try a.end(f, w);
668 }685 }
669686
670 fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue {687 fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue {
...@@ -693,18 +710,32 @@ pub const Function = struct {...@@ -693,18 +710,32 @@ pub const Function = struct {
693/// It is not available when generating .h file.710/// It is not available when generating .h file.
694pub const Object = struct {711pub const Object = struct {
695 dg: DeclGen,712 dg: DeclGen,
696 /// This is a borrowed reference from `link.C`.713 code_header: std.io.Writer.Allocating,
697 code: std.ArrayList(u8),714 code: std.io.Writer.Allocating,
698 /// Goes before code. Initialized and deinitialized in `genFunc`.715 indent_counter: usize,
699 code_header: std.ArrayList(u8) = undefined,716
700 indent_writer: IndentWriter(std.ArrayList(u8).Writer),717 const indent_width = 1;
701718 const indent_char = ' ';
702 fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {719
703 return o.indent_writer.writer();720 fn newline(o: *Object) !void {
704 }721 const w = &o.code.writer;
705722 try w.writeByte('\n');
706 fn codeHeaderWriter(o: *Object) ArrayListWriter {723 try w.splatByteAll(indent_char, o.indent_counter);
707 return arrayListWriter(&o.code_header);724 }
725 fn indent(o: *Object) void {
726 o.indent_counter += indent_width;
727 }
728 fn outdent(o: *Object) !void {
729 o.indent_counter -= indent_width;
730 const written = o.code.getWritten();
731 switch (written[written.len - 1]) {
732 indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width),
733 '\n' => try o.code.writer.splatByteAll(indent_char, o.indent_counter),
734 else => {
735 std.debug.print("\"{f}\"\n", .{std.zig.fmtString(written[written.len -| 100..])});
736 unreachable;
737 },
738 }
708 }739 }
709};740};
710741
...@@ -716,8 +747,7 @@ pub const DeclGen = struct {...@@ -716,8 +747,7 @@ pub const DeclGen = struct {
716 pass: Pass,747 pass: Pass,
717 is_naked_fn: bool,748 is_naked_fn: bool,
718 expected_block: ?u32,749 expected_block: ?u32,
719 /// This is a borrowed reference from `link.C`.750 fwd_decl: std.io.Writer.Allocating,
720 fwd_decl: std.ArrayList(u8),
721 error_msg: ?*Zcu.ErrorMsg,751 error_msg: ?*Zcu.ErrorMsg,
722 ctype_pool: CType.Pool,752 ctype_pool: CType.Pool,
723 scratch: std.ArrayListUnmanaged(u32),753 scratch: std.ArrayListUnmanaged(u32),
...@@ -734,11 +764,7 @@ pub const DeclGen = struct {...@@ -734,11 +764,7 @@ pub const DeclGen = struct {
734 flush,764 flush,
735 };765 };
736766
737 fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter {767 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
738 return arrayListWriter(&dg.fwd_decl);
739 }
740
741 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
742 @branchHint(.cold);768 @branchHint(.cold);
743 const zcu = dg.pt.zcu;769 const zcu = dg.pt.zcu;
744 const src_loc = zcu.navSrcLoc(dg.pass.nav);770 const src_loc = zcu.navSrcLoc(dg.pass.nav);
...@@ -748,10 +774,10 @@ pub const DeclGen = struct {...@@ -748,10 +774,10 @@ pub const DeclGen = struct {
748774
749 fn renderUav(775 fn renderUav(
750 dg: *DeclGen,776 dg: *DeclGen,
751 writer: anytype,777 w: *Writer,
752 uav: InternPool.Key.Ptr.BaseAddr.Uav,778 uav: InternPool.Key.Ptr.BaseAddr.Uav,
753 location: ValueRenderLocation,779 location: ValueRenderLocation,
754 ) error{ OutOfMemory, AnalysisFail }!void {780 ) Error!void {
755 const pt = dg.pt;781 const pt = dg.pt;
756 const zcu = pt.zcu;782 const zcu = pt.zcu;
757 const ip = &zcu.intern_pool;783 const ip = &zcu.intern_pool;
...@@ -762,14 +788,14 @@ pub const DeclGen = struct {...@@ -762,14 +788,14 @@ pub const DeclGen = struct {
762 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.788 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
763 const ptr_ty: Type = .fromInterned(uav.orig_ty);789 const ptr_ty: Type = .fromInterned(uav.orig_ty);
764 if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isFnOrHasRuntimeBits(zcu)) {790 if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isFnOrHasRuntimeBits(zcu)) {
765 return dg.writeCValue(writer, .{ .undef = ptr_ty });791 return dg.writeCValue(w, .{ .undef = ptr_ty });
766 }792 }
767793
768 // Chase function values in order to be able to reference the original function.794 // Chase function values in order to be able to reference the original function.
769 switch (ip.indexToKey(uav.val)) {795 switch (ip.indexToKey(uav.val)) {
770 .variable => unreachable,796 .variable => unreachable,
771 .func => |func| return dg.renderNav(writer, func.owner_nav, location),797 .func => |func| return dg.renderNav(w, func.owner_nav, location),
772 .@"extern" => |@"extern"| return dg.renderNav(writer, @"extern".owner_nav, location),798 .@"extern" => |@"extern"| return dg.renderNav(w, @"extern".owner_nav, location),
773 else => {},799 else => {},
774 }800 }
775801
...@@ -783,13 +809,13 @@ pub const DeclGen = struct {...@@ -783,13 +809,13 @@ pub const DeclGen = struct {
783 const need_cast = !elem_ctype.eql(uav_ctype) and809 const need_cast = !elem_ctype.eql(uav_ctype) and
784 (elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function);810 (elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function);
785 if (need_cast) {811 if (need_cast) {
786 try writer.writeAll("((");812 try w.writeAll("((");
787 try dg.renderCType(writer, ptr_ctype);813 try dg.renderCType(w, ptr_ctype);
788 try writer.writeByte(')');814 try w.writeByte(')');
789 }815 }
790 try writer.writeByte('&');816 try w.writeByte('&');
791 try renderUavName(writer, uav_val);817 try renderUavName(w, uav_val);
792 if (need_cast) try writer.writeByte(')');818 if (need_cast) try w.writeByte(')');
793819
794 // Indicate that the anon decl should be rendered to the output so that820 // Indicate that the anon decl should be rendered to the output so that
795 // our reference above is not undefined.821 // our reference above is not undefined.
...@@ -810,10 +836,10 @@ pub const DeclGen = struct {...@@ -810,10 +836,10 @@ pub const DeclGen = struct {
810836
811 fn renderNav(837 fn renderNav(
812 dg: *DeclGen,838 dg: *DeclGen,
813 writer: anytype,839 w: *Writer,
814 nav_index: InternPool.Nav.Index,840 nav_index: InternPool.Nav.Index,
815 location: ValueRenderLocation,841 location: ValueRenderLocation,
816 ) error{ OutOfMemory, AnalysisFail }!void {842 ) Error!void {
817 _ = location;843 _ = location;
818 const pt = dg.pt;844 const pt = dg.pt;
819 const zcu = pt.zcu;845 const zcu = pt.zcu;
...@@ -835,7 +861,7 @@ pub const DeclGen = struct {...@@ -835,7 +861,7 @@ pub const DeclGen = struct {
835 const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip));861 const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip));
836 const ptr_ty = try pt.navPtrType(owner_nav);862 const ptr_ty = try pt.navPtrType(owner_nav);
837 if (!nav_ty.isFnOrHasRuntimeBits(zcu)) {863 if (!nav_ty.isFnOrHasRuntimeBits(zcu)) {
838 return dg.writeCValue(writer, .{ .undef = ptr_ty });864 return dg.writeCValue(w, .{ .undef = ptr_ty });
839 }865 }
840866
841 // We shouldn't cast C function pointers as this is UB (when you call867 // We shouldn't cast C function pointers as this is UB (when you call
...@@ -848,21 +874,21 @@ pub const DeclGen = struct {...@@ -848,21 +874,21 @@ pub const DeclGen = struct {
848 const need_cast = !elem_ctype.eql(nav_ctype) and874 const need_cast = !elem_ctype.eql(nav_ctype) and
849 (elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function);875 (elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function);
850 if (need_cast) {876 if (need_cast) {
851 try writer.writeAll("((");877 try w.writeAll("((");
852 try dg.renderCType(writer, ctype);878 try dg.renderCType(w, ctype);
853 try writer.writeByte(')');879 try w.writeByte(')');
854 }880 }
855 try writer.writeByte('&');881 try w.writeByte('&');
856 try dg.renderNavName(writer, owner_nav);882 try dg.renderNavName(w, owner_nav);
857 if (need_cast) try writer.writeByte(')');883 if (need_cast) try w.writeByte(')');
858 }884 }
859885
860 fn renderPointer(886 fn renderPointer(
861 dg: *DeclGen,887 dg: *DeclGen,
862 writer: anytype,888 w: *Writer,
863 derivation: Value.PointerDeriveStep,889 derivation: Value.PointerDeriveStep,
864 location: ValueRenderLocation,890 location: ValueRenderLocation,
865 ) error{ OutOfMemory, AnalysisFail }!void {891 ) Error!void {
866 const pt = dg.pt;892 const pt = dg.pt;
867 const zcu = pt.zcu;893 const zcu = pt.zcu;
868 switch (derivation) {894 switch (derivation) {
...@@ -870,18 +896,18 @@ pub const DeclGen = struct {...@@ -870,18 +896,18 @@ pub const DeclGen = struct {
870 .int => |int| {896 .int => |int| {
871 const ptr_ctype = try dg.ctypeFromType(int.ptr_ty, .complete);897 const ptr_ctype = try dg.ctypeFromType(int.ptr_ty, .complete);
872 const addr_val = try pt.intValue(.usize, int.addr);898 const addr_val = try pt.intValue(.usize, int.addr);
873 try writer.writeByte('(');899 try w.writeByte('(');
874 try dg.renderCType(writer, ptr_ctype);900 try dg.renderCType(w, ptr_ctype);
875 try writer.print("){x}", .{try dg.fmtIntLiteral(addr_val, .Other)});901 try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .Other)});
876 },902 },
877903
878 .nav_ptr => |nav| try dg.renderNav(writer, nav, location),904 .nav_ptr => |nav| try dg.renderNav(w, nav, location),
879 .uav_ptr => |uav| try dg.renderUav(writer, uav, location),905 .uav_ptr => |uav| try dg.renderUav(w, uav, location),
880906
881 inline .eu_payload_ptr, .opt_payload_ptr => |info| {907 inline .eu_payload_ptr, .opt_payload_ptr => |info| {
882 try writer.writeAll("&(");908 try w.writeAll("&(");
883 try dg.renderPointer(writer, info.parent.*, location);909 try dg.renderPointer(w, info.parent.*, location);
884 try writer.writeAll(")->payload");910 try w.writeAll(")->payload");
885 },911 },
886912
887 .field_ptr => |field| {913 .field_ptr => |field| {
...@@ -893,26 +919,26 @@ pub const DeclGen = struct {...@@ -893,26 +919,26 @@ pub const DeclGen = struct {
893 switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, pt)) {919 switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, pt)) {
894 .begin => {920 .begin => {
895 const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);921 const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);
896 try writer.writeByte('(');922 try w.writeByte('(');
897 try dg.renderCType(writer, ptr_ctype);923 try dg.renderCType(w, ptr_ctype);
898 try writer.writeByte(')');924 try w.writeByte(')');
899 try dg.renderPointer(writer, field.parent.*, location);925 try dg.renderPointer(w, field.parent.*, location);
900 },926 },
901 .field => |name| {927 .field => |name| {
902 try writer.writeAll("&(");928 try w.writeAll("&(");
903 try dg.renderPointer(writer, field.parent.*, location);929 try dg.renderPointer(w, field.parent.*, location);
904 try writer.writeAll(")->");930 try w.writeAll(")->");
905 try dg.writeCValue(writer, name);931 try dg.writeCValue(w, name);
906 },932 },
907 .byte_offset => |byte_offset| {933 .byte_offset => |byte_offset| {
908 const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);934 const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);
909 try writer.writeByte('(');935 try w.writeByte('(');
910 try dg.renderCType(writer, ptr_ctype);936 try dg.renderCType(w, ptr_ctype);
911 try writer.writeByte(')');937 try w.writeByte(')');
912 const offset_val = try pt.intValue(.usize, byte_offset);938 const offset_val = try pt.intValue(.usize, byte_offset);
913 try writer.writeAll("((char *)");939 try w.writeAll("((char *)");
914 try dg.renderPointer(writer, field.parent.*, location);940 try dg.renderPointer(w, field.parent.*, location);
915 try writer.print(" + {})", .{try dg.fmtIntLiteral(offset_val, .Other)});941 try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)});
916 },942 },
917 }943 }
918 },944 },
...@@ -920,10 +946,10 @@ pub const DeclGen = struct {...@@ -920,10 +946,10 @@ pub const DeclGen = struct {
920 .elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) {946 .elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) {
921 // Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer.947 // Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer.
922 const ptr_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete);948 const ptr_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete);
923 try writer.writeByte('(');949 try w.writeByte('(');
924 try dg.renderCType(writer, ptr_ctype);950 try dg.renderCType(w, ptr_ctype);
925 try writer.writeByte(')');951 try w.writeByte(')');
926 try dg.renderPointer(writer, elem.parent.*, location);952 try dg.renderPointer(w, elem.parent.*, location);
927 } else {953 } else {
928 const index_val = try pt.intValue(.usize, elem.elem_idx);954 const index_val = try pt.intValue(.usize, elem.elem_idx);
929 // We want to do pointer arithmetic on a pointer to the element type.955 // We want to do pointer arithmetic on a pointer to the element type.
...@@ -932,48 +958,47 @@ pub const DeclGen = struct {...@@ -932,48 +958,47 @@ pub const DeclGen = struct {
932 const parent_ctype = try dg.ctypeFromType(try elem.parent.ptrType(pt), .complete);958 const parent_ctype = try dg.ctypeFromType(try elem.parent.ptrType(pt), .complete);
933 if (result_ctype.eql(parent_ctype)) {959 if (result_ctype.eql(parent_ctype)) {
934 // The pointer already has an appropriate type - just do the arithmetic.960 // The pointer already has an appropriate type - just do the arithmetic.
935 try writer.writeByte('(');961 try w.writeByte('(');
936 try dg.renderPointer(writer, elem.parent.*, location);962 try dg.renderPointer(w, elem.parent.*, location);
937 try writer.print(" + {})", .{try dg.fmtIntLiteral(index_val, .Other)});963 try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)});
938 } else {964 } else {
939 // We probably have an array pointer `T (*)[n]`. Cast to an element pointer,965 // We probably have an array pointer `T (*)[n]`. Cast to an element pointer,
940 // and *then* apply the index.966 // and *then* apply the index.
941 try writer.writeAll("((");967 try w.writeAll("((");
942 try dg.renderCType(writer, result_ctype);968 try dg.renderCType(w, result_ctype);
943 try writer.writeByte(')');969 try w.writeByte(')');
944 try dg.renderPointer(writer, elem.parent.*, location);970 try dg.renderPointer(w, elem.parent.*, location);
945 try writer.print(" + {})", .{try dg.fmtIntLiteral(index_val, .Other)});971 try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)});
946 }972 }
947 },973 },
948974
949 .offset_and_cast => |oac| {975 .offset_and_cast => |oac| {
950 const ptr_ctype = try dg.ctypeFromType(oac.new_ptr_ty, .complete);976 const ptr_ctype = try dg.ctypeFromType(oac.new_ptr_ty, .complete);
951 try writer.writeByte('(');977 try w.writeByte('(');
952 try dg.renderCType(writer, ptr_ctype);978 try dg.renderCType(w, ptr_ctype);
953 try writer.writeByte(')');979 try w.writeByte(')');
954 if (oac.byte_offset == 0) {980 if (oac.byte_offset == 0) {
955 try dg.renderPointer(writer, oac.parent.*, location);981 try dg.renderPointer(w, oac.parent.*, location);
956 } else {982 } else {
957 const offset_val = try pt.intValue(.usize, oac.byte_offset);983 const offset_val = try pt.intValue(.usize, oac.byte_offset);
958 try writer.writeAll("((char *)");984 try w.writeAll("((char *)");
959 try dg.renderPointer(writer, oac.parent.*, location);985 try dg.renderPointer(w, oac.parent.*, location);
960 try writer.print(" + {})", .{try dg.fmtIntLiteral(offset_val, .Other)});986 try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)});
961 }987 }
962 },988 },
963 }989 }
964 }990 }
965991
966 fn renderErrorName(dg: *DeclGen, writer: anytype, err_name: InternPool.NullTerminatedString) !void {992 fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void {
967 const ip = &dg.pt.zcu.intern_pool;993 try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))});
968 try writer.print("zig_error_{}", .{fmtIdent(err_name.toSlice(ip))});
969 }994 }
970995
971 fn renderValue(996 fn renderValue(
972 dg: *DeclGen,997 dg: *DeclGen,
973 writer: anytype,998 w: *Writer,
974 val: Value,999 val: Value,
975 location: ValueRenderLocation,1000 location: ValueRenderLocation,
976 ) error{ OutOfMemory, AnalysisFail }!void {1001 ) Error!void {
977 const pt = dg.pt;1002 const pt = dg.pt;
978 const zcu = pt.zcu;1003 const zcu = pt.zcu;
979 const ip = &zcu.intern_pool;1004 const ip = &zcu.intern_pool;
...@@ -986,7 +1011,7 @@ pub const DeclGen = struct {...@@ -986,7 +1011,7 @@ pub const DeclGen = struct {
986 };1011 };
9871012
988 const ty = val.typeOf(zcu);1013 const ty = val.typeOf(zcu);
989 if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location);1014 if (val.isUndefDeep(zcu)) return dg.renderUndefValue(w, ty, location);
990 const ctype = try dg.ctypeFromType(ty, location.toCTypeKind());1015 const ctype = try dg.ctypeFromType(ty, location.toCTypeKind());
991 switch (ip.indexToKey(val.toIntern())) {1016 switch (ip.indexToKey(val.toIntern())) {
992 // types, not values1017 // types, not values
...@@ -1019,8 +1044,8 @@ pub const DeclGen = struct {...@@ -1019,8 +1044,8 @@ pub const DeclGen = struct {
1019 .empty_tuple => unreachable,1044 .empty_tuple => unreachable,
1020 .@"unreachable" => unreachable,1045 .@"unreachable" => unreachable,
10211046
1022 .false => try writer.writeAll("false"),1047 .false => try w.writeAll("false"),
1023 .true => try writer.writeAll("true"),1048 .true => try w.writeAll("true"),
1024 },1049 },
1025 .variable,1050 .variable,
1026 .@"extern",1051 .@"extern",
...@@ -1029,45 +1054,45 @@ pub const DeclGen = struct {...@@ -1029,45 +1054,45 @@ pub const DeclGen = struct {
1029 .empty_enum_value,1054 .empty_enum_value,
1030 => unreachable, // non-runtime values1055 => unreachable, // non-runtime values
1031 .int => |int| switch (int.storage) {1056 .int => |int| switch (int.storage) {
1032 .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}),1057 .u64, .i64, .big_int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}),
1033 .lazy_align, .lazy_size => {1058 .lazy_align, .lazy_size => {
1034 try writer.writeAll("((");1059 try w.writeAll("((");
1035 try dg.renderCType(writer, ctype);1060 try dg.renderCType(w, ctype);
1036 try writer.print("){x})", .{try dg.fmtIntLiteral(1061 try w.print("){f})", .{try dg.fmtIntLiteralHex(
1037 try pt.intValue(.usize, val.toUnsignedInt(zcu)),1062 try pt.intValue(.usize, val.toUnsignedInt(zcu)),
1038 .Other,1063 .Other,
1039 )});1064 )});
1040 },1065 },
1041 },1066 },
1042 .err => |err| try dg.renderErrorName(writer, err.name),1067 .err => |err| try dg.renderErrorName(w, err.name),
1043 .error_union => |error_union| switch (ctype.info(ctype_pool)) {1068 .error_union => |error_union| switch (ctype.info(ctype_pool)) {
1044 .basic => switch (error_union.val) {1069 .basic => switch (error_union.val) {
1045 .err_name => |err_name| try dg.renderErrorName(writer, err_name),1070 .err_name => |err_name| try dg.renderErrorName(w, err_name),
1046 .payload => try writer.writeAll("0"),1071 .payload => try w.writeByte('0'),
1047 },1072 },
1048 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,1073 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1049 .aggregate => |aggregate| {1074 .aggregate => |aggregate| {
1050 if (!location.isInitializer()) {1075 if (!location.isInitializer()) {
1051 try writer.writeByte('(');1076 try w.writeByte('(');
1052 try dg.renderCType(writer, ctype);1077 try dg.renderCType(w, ctype);
1053 try writer.writeByte(')');1078 try w.writeByte(')');
1054 }1079 }
1055 try writer.writeByte('{');1080 try w.writeByte('{');
1056 for (0..aggregate.fields.len) |field_index| {1081 for (0..aggregate.fields.len) |field_index| {
1057 if (field_index > 0) try writer.writeByte(',');1082 if (field_index > 0) try w.writeByte(',');
1058 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {1083 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1059 .@"error" => switch (error_union.val) {1084 .@"error" => switch (error_union.val) {
1060 .err_name => |err_name| try dg.renderErrorName(writer, err_name),1085 .err_name => |err_name| try dg.renderErrorName(w, err_name),
1061 .payload => try writer.writeByte('0'),1086 .payload => try w.writeByte('0'),
1062 },1087 },
1063 .payload => switch (error_union.val) {1088 .payload => switch (error_union.val) {
1064 .err_name => try dg.renderUndefValue(1089 .err_name => try dg.renderUndefValue(
1065 writer,1090 w,
1066 ty.errorUnionPayload(zcu),1091 ty.errorUnionPayload(zcu),
1067 initializer_type,1092 initializer_type,
1068 ),1093 ),
1069 .payload => |payload| try dg.renderValue(1094 .payload => |payload| try dg.renderValue(
1070 writer,1095 w,
1071 Value.fromInterned(payload),1096 Value.fromInterned(payload),
1072 initializer_type,1097 initializer_type,
1073 ),1098 ),
...@@ -1075,10 +1100,10 @@ pub const DeclGen = struct {...@@ -1075,10 +1100,10 @@ pub const DeclGen = struct {
1075 else => unreachable,1100 else => unreachable,
1076 }1101 }
1077 }1102 }
1078 try writer.writeByte('}');1103 try w.writeByte('}');
1079 },1104 },
1080 },1105 },
1081 .enum_tag => |enum_tag| try dg.renderValue(writer, Value.fromInterned(enum_tag.int), location),1106 .enum_tag => |enum_tag| try dg.renderValue(w, Value.fromInterned(enum_tag.int), location),
1082 .float => {1107 .float => {
1083 const bits = ty.floatBits(target);1108 const bits = ty.floatBits(target);
1084 const f128_val = val.toFloat(f128, zcu);1109 const f128_val = val.toFloat(f128, zcu);
...@@ -1105,18 +1130,18 @@ pub const DeclGen = struct {...@@ -1105,18 +1130,18 @@ pub const DeclGen = struct {
11051130
1106 var empty = true;1131 var empty = true;
1107 if (std.math.isFinite(f128_val)) {1132 if (std.math.isFinite(f128_val)) {
1108 try writer.writeAll("zig_make_");1133 try w.writeAll("zig_make_");
1109 try dg.renderTypeForBuiltinFnName(writer, ty);1134 try dg.renderTypeForBuiltinFnName(w, ty);
1110 try writer.writeByte('(');1135 try w.writeByte('(');
1111 switch (bits) {1136 switch (bits) {
1112 16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}),1137 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}),
1113 32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}),1138 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}),
1114 64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}),1139 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}),
1115 80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}),1140 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}),
1116 128 => try writer.print("{x}", .{f128_val}),1141 128 => try w.print("{x}", .{f128_val}),
1117 else => unreachable,1142 else => unreachable,
1118 }1143 }
1119 try writer.writeAll(", ");1144 try w.writeAll(", ");
1120 empty = false;1145 empty = false;
1121 } else {1146 } else {
1122 // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan1147 // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan
...@@ -1140,45 +1165,45 @@ pub const DeclGen = struct {...@@ -1140,45 +1165,45 @@ pub const DeclGen = struct {
1140 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});1165 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});
1141 }1166 }
11421167
1143 try writer.writeAll("zig_");1168 try w.writeAll("zig_");
1144 try writer.writeAll(if (location == .StaticInitializer) "init" else "make");1169 try w.writeAll(if (location == .StaticInitializer) "init" else "make");
1145 try writer.writeAll("_special_");1170 try w.writeAll("_special_");
1146 try dg.renderTypeForBuiltinFnName(writer, ty);1171 try dg.renderTypeForBuiltinFnName(w, ty);
1147 try writer.writeByte('(');1172 try w.writeByte('(');
1148 if (std.math.signbit(f128_val)) try writer.writeByte('-');1173 if (std.math.signbit(f128_val)) try w.writeByte('-');
1149 try writer.writeAll(", ");1174 try w.writeAll(", ");
1150 try writer.writeAll(operation);1175 try w.writeAll(operation);
1151 try writer.writeAll(", ");1176 try w.writeAll(", ");
1152 if (std.math.isNan(f128_val)) switch (bits) {1177 if (std.math.isNan(f128_val)) switch (bits) {
1153 // We only actually need to pass the significand, but it will get1178 // We only actually need to pass the significand, but it will get
1154 // properly masked anyway, so just pass the whole value.1179 // properly masked anyway, so just pass the whole value.
1155 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),1180 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
1156 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}),1181 32 => try w.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}),
1157 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),1182 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
1158 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),1183 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
1159 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),1184 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
1160 else => unreachable,1185 else => unreachable,
1161 };1186 };
1162 try writer.writeAll(", ");1187 try w.writeAll(", ");
1163 empty = false;1188 empty = false;
1164 }1189 }
1165 try writer.print("{x}", .{try dg.fmtIntLiteral(1190 try w.print("{f}", .{try dg.fmtIntLiteralHex(
1166 try pt.intValue_big(repr_ty, repr_val_big.toConst()),1191 try pt.intValue_big(repr_ty, repr_val_big.toConst()),
1167 location,1192 location,
1168 )});1193 )});
1169 if (!empty) try writer.writeByte(')');1194 if (!empty) try w.writeByte(')');
1170 },1195 },
1171 .slice => |slice| {1196 .slice => |slice| {
1172 const aggregate = ctype.info(ctype_pool).aggregate;1197 const aggregate = ctype.info(ctype_pool).aggregate;
1173 if (!location.isInitializer()) {1198 if (!location.isInitializer()) {
1174 try writer.writeByte('(');1199 try w.writeByte('(');
1175 try dg.renderCType(writer, ctype);1200 try dg.renderCType(w, ctype);
1176 try writer.writeByte(')');1201 try w.writeByte(')');
1177 }1202 }
1178 try writer.writeByte('{');1203 try w.writeByte('{');
1179 for (0..aggregate.fields.len) |field_index| {1204 for (0..aggregate.fields.len) |field_index| {
1180 if (field_index > 0) try writer.writeByte(',');1205 if (field_index > 0) try w.writeByte(',');
1181 try dg.renderValue(writer, Value.fromInterned(1206 try dg.renderValue(w, Value.fromInterned(
1182 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {1207 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1183 .ptr => slice.ptr,1208 .ptr => slice.ptr,
1184 .len => slice.len,1209 .len => slice.len,
...@@ -1186,33 +1211,33 @@ pub const DeclGen = struct {...@@ -1186,33 +1211,33 @@ pub const DeclGen = struct {
1186 },1211 },
1187 ), initializer_type);1212 ), initializer_type);
1188 }1213 }
1189 try writer.writeByte('}');1214 try w.writeByte('}');
1190 },1215 },
1191 .ptr => {1216 .ptr => {
1192 var arena = std.heap.ArenaAllocator.init(zcu.gpa);1217 var arena = std.heap.ArenaAllocator.init(zcu.gpa);
1193 defer arena.deinit();1218 defer arena.deinit();
1194 const derivation = try val.pointerDerivation(arena.allocator(), pt);1219 const derivation = try val.pointerDerivation(arena.allocator(), pt);
1195 try dg.renderPointer(writer, derivation, location);1220 try dg.renderPointer(w, derivation, location);
1196 },1221 },
1197 .opt => |opt| switch (ctype.info(ctype_pool)) {1222 .opt => |opt| switch (ctype.info(ctype_pool)) {
1198 .basic => if (ctype.isBool()) try writer.writeAll(switch (opt.val) {1223 .basic => if (ctype.isBool()) try w.writeAll(switch (opt.val) {
1199 .none => "true",1224 .none => "true",
1200 else => "false",1225 else => "false",
1201 }) else switch (opt.val) {1226 }) else switch (opt.val) {
1202 .none => try writer.writeAll("0"),1227 .none => try w.writeByte('0'),
1203 else => |payload| switch (ip.indexToKey(payload)) {1228 else => |payload| switch (ip.indexToKey(payload)) {
1204 .undef => |err_ty| try dg.renderUndefValue(1229 .undef => |err_ty| try dg.renderUndefValue(
1205 writer,1230 w,
1206 .fromInterned(err_ty),1231 .fromInterned(err_ty),
1207 location,1232 location,
1208 ),1233 ),
1209 .err => |err| try dg.renderErrorName(writer, err.name),1234 .err => |err| try dg.renderErrorName(w, err.name),
1210 else => unreachable,1235 else => unreachable,
1211 },1236 },
1212 },1237 },
1213 .pointer => switch (opt.val) {1238 .pointer => switch (opt.val) {
1214 .none => try writer.writeAll("NULL"),1239 .none => try w.writeAll("NULL"),
1215 else => |payload| try dg.renderValue(writer, Value.fromInterned(payload), location),1240 else => |payload| try dg.renderValue(w, Value.fromInterned(payload), location),
1216 },1241 },
1217 .aligned, .array, .vector, .fwd_decl, .function => unreachable,1242 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1218 .aggregate => |aggregate| {1243 .aggregate => |aggregate| {
...@@ -1221,7 +1246,7 @@ pub const DeclGen = struct {...@@ -1221,7 +1246,7 @@ pub const DeclGen = struct {
1221 else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) {1246 else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) {
1222 .is_null, .payload => {},1247 .is_null, .payload => {},
1223 .ptr, .len => return dg.renderValue(1248 .ptr, .len => return dg.renderValue(
1224 writer,1249 w,
1225 Value.fromInterned(payload),1250 Value.fromInterned(payload),
1226 location,1251 location,
1227 ),1252 ),
...@@ -1229,48 +1254,48 @@ pub const DeclGen = struct {...@@ -1229,48 +1254,48 @@ pub const DeclGen = struct {
1229 },1254 },
1230 }1255 }
1231 if (!location.isInitializer()) {1256 if (!location.isInitializer()) {
1232 try writer.writeByte('(');1257 try w.writeByte('(');
1233 try dg.renderCType(writer, ctype);1258 try dg.renderCType(w, ctype);
1234 try writer.writeByte(')');1259 try w.writeByte(')');
1235 }1260 }
1236 try writer.writeByte('{');1261 try w.writeByte('{');
1237 for (0..aggregate.fields.len) |field_index| {1262 for (0..aggregate.fields.len) |field_index| {
1238 if (field_index > 0) try writer.writeByte(',');1263 if (field_index > 0) try w.writeByte(',');
1239 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {1264 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1240 .is_null => try writer.writeAll(switch (opt.val) {1265 .is_null => try w.writeAll(switch (opt.val) {
1241 .none => "true",1266 .none => "true",
1242 else => "false",1267 else => "false",
1243 }),1268 }),
1244 .payload => switch (opt.val) {1269 .payload => switch (opt.val) {
1245 .none => try dg.renderUndefValue(1270 .none => try dg.renderUndefValue(
1246 writer,1271 w,
1247 ty.optionalChild(zcu),1272 ty.optionalChild(zcu),
1248 initializer_type,1273 initializer_type,
1249 ),1274 ),
1250 else => |payload| try dg.renderValue(1275 else => |payload| try dg.renderValue(
1251 writer,1276 w,
1252 Value.fromInterned(payload),1277 Value.fromInterned(payload),
1253 initializer_type,1278 initializer_type,
1254 ),1279 ),
1255 },1280 },
1256 .ptr => try writer.writeAll("NULL"),1281 .ptr => try w.writeAll("NULL"),
1257 .len => try dg.renderUndefValue(writer, .usize, initializer_type),1282 .len => try dg.renderUndefValue(w, .usize, initializer_type),
1258 else => unreachable,1283 else => unreachable,
1259 }1284 }
1260 }1285 }
1261 try writer.writeByte('}');1286 try w.writeByte('}');
1262 },1287 },
1263 },1288 },
1264 .aggregate => switch (ip.indexToKey(ty.toIntern())) {1289 .aggregate => switch (ip.indexToKey(ty.toIntern())) {
1265 .array_type, .vector_type => {1290 .array_type, .vector_type => {
1266 if (location == .FunctionArgument) {1291 if (location == .FunctionArgument) {
1267 try writer.writeByte('(');1292 try w.writeByte('(');
1268 try dg.renderCType(writer, ctype);1293 try dg.renderCType(w, ctype);
1269 try writer.writeByte(')');1294 try w.writeByte(')');
1270 }1295 }
1271 const ai = ty.arrayInfo(zcu);1296 const ai = ty.arrayInfo(zcu);
1272 if (ai.elem_type.eql(.u8, zcu)) {1297 if (ai.elem_type.eql(.u8, zcu)) {
1273 var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu));1298 var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu)));
1274 try literal.start();1299 try literal.start();
1275 var index: usize = 0;1300 var index: usize = 0;
1276 while (index < ai.len) : (index += 1) {1301 while (index < ai.len) : (index += 1) {
...@@ -1287,28 +1312,28 @@ pub const DeclGen = struct {...@@ -1287,28 +1312,28 @@ pub const DeclGen = struct {
1287 }1312 }
1288 try literal.end();1313 try literal.end();
1289 } else {1314 } else {
1290 try writer.writeByte('{');1315 try w.writeByte('{');
1291 var index: usize = 0;1316 var index: usize = 0;
1292 while (index < ai.len) : (index += 1) {1317 while (index < ai.len) : (index += 1) {
1293 if (index != 0) try writer.writeByte(',');1318 if (index != 0) try w.writeByte(',');
1294 const elem_val = try val.elemValue(pt, index);1319 const elem_val = try val.elemValue(pt, index);
1295 try dg.renderValue(writer, elem_val, initializer_type);1320 try dg.renderValue(w, elem_val, initializer_type);
1296 }1321 }
1297 if (ai.sentinel) |s| {1322 if (ai.sentinel) |s| {
1298 if (index != 0) try writer.writeByte(',');1323 if (index != 0) try w.writeByte(',');
1299 try dg.renderValue(writer, s, initializer_type);1324 try dg.renderValue(w, s, initializer_type);
1300 }1325 }
1301 try writer.writeByte('}');1326 try w.writeByte('}');
1302 }1327 }
1303 },1328 },
1304 .tuple_type => |tuple| {1329 .tuple_type => |tuple| {
1305 if (!location.isInitializer()) {1330 if (!location.isInitializer()) {
1306 try writer.writeByte('(');1331 try w.writeByte('(');
1307 try dg.renderCType(writer, ctype);1332 try dg.renderCType(w, ctype);
1308 try writer.writeByte(')');1333 try w.writeByte(')');
1309 }1334 }
13101335
1311 try writer.writeByte('{');1336 try w.writeByte('{');
1312 var empty = true;1337 var empty = true;
1313 for (0..tuple.types.len) |field_index| {1338 for (0..tuple.types.len) |field_index| {
1314 const comptime_val = tuple.values.get(ip)[field_index];1339 const comptime_val = tuple.values.get(ip)[field_index];
...@@ -1316,7 +1341,7 @@ pub const DeclGen = struct {...@@ -1316,7 +1341,7 @@ pub const DeclGen = struct {
1316 const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]);1341 const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]);
1317 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;1342 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
13181343
1319 if (!empty) try writer.writeByte(',');1344 if (!empty) try w.writeByte(',');
13201345
1321 const field_val = Value.fromInterned(1346 const field_val = Value.fromInterned(
1322 switch (ip.indexToKey(val.toIntern()).aggregate.storage) {1347 switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
...@@ -1328,30 +1353,30 @@ pub const DeclGen = struct {...@@ -1328,30 +1353,30 @@ pub const DeclGen = struct {
1328 .repeated_elem => |elem| elem,1353 .repeated_elem => |elem| elem,
1329 },1354 },
1330 );1355 );
1331 try dg.renderValue(writer, field_val, initializer_type);1356 try dg.renderValue(w, field_val, initializer_type);
13321357
1333 empty = false;1358 empty = false;
1334 }1359 }
1335 try writer.writeByte('}');1360 try w.writeByte('}');
1336 },1361 },
1337 .struct_type => {1362 .struct_type => {
1338 const loaded_struct = ip.loadStructType(ty.toIntern());1363 const loaded_struct = ip.loadStructType(ty.toIntern());
1339 switch (loaded_struct.layout) {1364 switch (loaded_struct.layout) {
1340 .auto, .@"extern" => {1365 .auto, .@"extern" => {
1341 if (!location.isInitializer()) {1366 if (!location.isInitializer()) {
1342 try writer.writeByte('(');1367 try w.writeByte('(');
1343 try dg.renderCType(writer, ctype);1368 try dg.renderCType(w, ctype);
1344 try writer.writeByte(')');1369 try w.writeByte(')');
1345 }1370 }
13461371
1347 try writer.writeByte('{');1372 try w.writeByte('{');
1348 var field_it = loaded_struct.iterateRuntimeOrder(ip);1373 var field_it = loaded_struct.iterateRuntimeOrder(ip);
1349 var need_comma = false;1374 var need_comma = false;
1350 while (field_it.next()) |field_index| {1375 while (field_it.next()) |field_index| {
1351 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);1376 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1352 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;1377 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
13531378
1354 if (need_comma) try writer.writeByte(',');1379 if (need_comma) try w.writeByte(',');
1355 need_comma = true;1380 need_comma = true;
1356 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {1381 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1357 .bytes => |bytes| try pt.intern(.{ .int = .{1382 .bytes => |bytes| try pt.intern(.{ .int = .{
...@@ -1361,9 +1386,9 @@ pub const DeclGen = struct {...@@ -1361,9 +1386,9 @@ pub const DeclGen = struct {
1361 .elems => |elems| elems[field_index],1386 .elems => |elems| elems[field_index],
1362 .repeated_elem => |elem| elem,1387 .repeated_elem => |elem| elem,
1363 };1388 };
1364 try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type);1389 try dg.renderValue(w, Value.fromInterned(field_val), initializer_type);
1365 }1390 }
1366 try writer.writeByte('}');1391 try w.writeByte('}');
1367 },1392 },
1368 .@"packed" => {1393 .@"packed" => {
1369 const int_info = ty.intInfo(zcu);1394 const int_info = ty.intInfo(zcu);
...@@ -1381,16 +1406,16 @@ pub const DeclGen = struct {...@@ -1381,16 +1406,16 @@ pub const DeclGen = struct {
1381 }1406 }
13821407
1383 if (eff_num_fields == 0) {1408 if (eff_num_fields == 0) {
1384 try writer.writeByte('(');1409 try w.writeByte('(');
1385 try dg.renderUndefValue(writer, ty, location);1410 try dg.renderUndefValue(w, ty, location);
1386 try writer.writeByte(')');1411 try w.writeByte(')');
1387 } else if (ty.bitSize(zcu) > 64) {1412 } else if (ty.bitSize(zcu) > 64) {
1388 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))1413 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
1389 var num_or = eff_num_fields - 1;1414 var num_or = eff_num_fields - 1;
1390 while (num_or > 0) : (num_or -= 1) {1415 while (num_or > 0) : (num_or -= 1) {
1391 try writer.writeAll("zig_or_");1416 try w.writeAll("zig_or_");
1392 try dg.renderTypeForBuiltinFnName(writer, ty);1417 try dg.renderTypeForBuiltinFnName(w, ty);
1393 try writer.writeByte('(');1418 try w.writeByte('(');
1394 }1419 }
13951420
1396 var eff_index: usize = 0;1421 var eff_index: usize = 0;
...@@ -1409,36 +1434,36 @@ pub const DeclGen = struct {...@@ -1409,36 +1434,36 @@ pub const DeclGen = struct {
1409 };1434 };
1410 const cast_context = IntCastContext{ .value = .{ .value = Value.fromInterned(field_val) } };1435 const cast_context = IntCastContext{ .value = .{ .value = Value.fromInterned(field_val) } };
1411 if (bit_offset != 0) {1436 if (bit_offset != 0) {
1412 try writer.writeAll("zig_shl_");1437 try w.writeAll("zig_shl_");
1413 try dg.renderTypeForBuiltinFnName(writer, ty);1438 try dg.renderTypeForBuiltinFnName(w, ty);
1414 try writer.writeByte('(');1439 try w.writeByte('(');
1415 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);1440 try dg.renderIntCast(w, ty, cast_context, field_ty, .FunctionArgument);
1416 try writer.writeAll(", ");1441 try w.writeAll(", ");
1417 try dg.renderValue(writer, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);1442 try dg.renderValue(w, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
1418 try writer.writeByte(')');1443 try w.writeByte(')');
1419 } else {1444 } else {
1420 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);1445 try dg.renderIntCast(w, ty, cast_context, field_ty, .FunctionArgument);
1421 }1446 }
14221447
1423 if (needs_closing_paren) try writer.writeByte(')');1448 if (needs_closing_paren) try w.writeByte(')');
1424 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");1449 if (eff_index != eff_num_fields - 1) try w.writeAll(", ");
14251450
1426 bit_offset += field_ty.bitSize(zcu);1451 bit_offset += field_ty.bitSize(zcu);
1427 needs_closing_paren = true;1452 needs_closing_paren = true;
1428 eff_index += 1;1453 eff_index += 1;
1429 }1454 }
1430 } else {1455 } else {
1431 try writer.writeByte('(');1456 try w.writeByte('(');
1432 // a << a_off | b << b_off | c << c_off1457 // a << a_off | b << b_off | c << c_off
1433 var empty = true;1458 var empty = true;
1434 for (0..loaded_struct.field_types.len) |field_index| {1459 for (0..loaded_struct.field_types.len) |field_index| {
1435 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);1460 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1436 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;1461 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
14371462
1438 if (!empty) try writer.writeAll(" | ");1463 if (!empty) try w.writeAll(" | ");
1439 try writer.writeByte('(');1464 try w.writeByte('(');
1440 try dg.renderCType(writer, ctype);1465 try dg.renderCType(w, ctype);
1441 try writer.writeByte(')');1466 try w.writeByte(')');
14421467
1443 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {1468 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1444 .bytes => |bytes| try pt.intern(.{ .int = .{1469 .bytes => |bytes| try pt.intern(.{ .int = .{
...@@ -1455,24 +1480,24 @@ pub const DeclGen = struct {...@@ -1455,24 +1480,24 @@ pub const DeclGen = struct {
1455 .{ .signedness = .unsigned, .bits = undefined };1480 .{ .signedness = .unsigned, .bits = undefined };
1456 switch (field_int_info.signedness) {1481 switch (field_int_info.signedness) {
1457 .signed => {1482 .signed => {
1458 try writer.writeByte('(');1483 try w.writeByte('(');
1459 try dg.renderValue(writer, Value.fromInterned(field_val), .Other);1484 try dg.renderValue(w, Value.fromInterned(field_val), .Other);
1460 try writer.writeAll(" & ");1485 try w.writeAll(" & ");
1461 const field_uint_ty = try pt.intType(.unsigned, field_int_info.bits);1486 const field_uint_ty = try pt.intType(.unsigned, field_int_info.bits);
1462 try dg.renderValue(writer, try field_uint_ty.maxIntScalar(pt, field_uint_ty), .Other);1487 try dg.renderValue(w, try field_uint_ty.maxIntScalar(pt, field_uint_ty), .Other);
1463 try writer.writeByte(')');1488 try w.writeByte(')');
1464 },1489 },
1465 .unsigned => try dg.renderValue(writer, Value.fromInterned(field_val), .Other),1490 .unsigned => try dg.renderValue(w, Value.fromInterned(field_val), .Other),
1466 }1491 }
1467 if (bit_offset != 0) {1492 if (bit_offset != 0) {
1468 try writer.writeAll(" << ");1493 try w.writeAll(" << ");
1469 try dg.renderValue(writer, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);1494 try dg.renderValue(w, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
1470 }1495 }
14711496
1472 bit_offset += field_ty.bitSize(zcu);1497 bit_offset += field_ty.bitSize(zcu);
1473 empty = false;1498 empty = false;
1474 }1499 }
1475 try writer.writeByte(')');1500 try w.writeByte(')');
1476 }1501 }
1477 },1502 },
1478 }1503 }
...@@ -1486,11 +1511,11 @@ pub const DeclGen = struct {...@@ -1486,11 +1511,11 @@ pub const DeclGen = struct {
1486 switch (loaded_union.flagsUnordered(ip).layout) {1511 switch (loaded_union.flagsUnordered(ip).layout) {
1487 .@"packed" => {1512 .@"packed" => {
1488 if (!location.isInitializer()) {1513 if (!location.isInitializer()) {
1489 try writer.writeByte('(');1514 try w.writeByte('(');
1490 try dg.renderType(writer, backing_ty);1515 try dg.renderType(w, backing_ty);
1491 try writer.writeByte(')');1516 try w.writeByte(')');
1492 }1517 }
1493 try dg.renderValue(writer, Value.fromInterned(un.val), location);1518 try dg.renderValue(w, Value.fromInterned(un.val), location);
1494 },1519 },
1495 .@"extern" => {1520 .@"extern" => {
1496 if (location == .StaticInitializer) {1521 if (location == .StaticInitializer) {
...@@ -1498,21 +1523,21 @@ pub const DeclGen = struct {...@@ -1498,21 +1523,21 @@ pub const DeclGen = struct {
1498 }1523 }
14991524
1500 const ptr_ty = try pt.singleConstPtrType(ty);1525 const ptr_ty = try pt.singleConstPtrType(ty);
1501 try writer.writeAll("*((");1526 try w.writeAll("*((");
1502 try dg.renderType(writer, ptr_ty);1527 try dg.renderType(w, ptr_ty);
1503 try writer.writeAll(")(");1528 try w.writeAll(")(");
1504 try dg.renderType(writer, backing_ty);1529 try dg.renderType(w, backing_ty);
1505 try writer.writeAll("){");1530 try w.writeAll("){");
1506 try dg.renderValue(writer, Value.fromInterned(un.val), location);1531 try dg.renderValue(w, Value.fromInterned(un.val), location);
1507 try writer.writeAll("})");1532 try w.writeAll("})");
1508 },1533 },
1509 else => unreachable,1534 else => unreachable,
1510 }1535 }
1511 } else {1536 } else {
1512 if (!location.isInitializer()) {1537 if (!location.isInitializer()) {
1513 try writer.writeByte('(');1538 try w.writeByte('(');
1514 try dg.renderCType(writer, ctype);1539 try dg.renderCType(w, ctype);
1515 try writer.writeByte(')');1540 try w.writeByte(')');
1516 }1541 }
15171542
1518 const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?;1543 const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?;
...@@ -1521,57 +1546,57 @@ pub const DeclGen = struct {...@@ -1521,57 +1546,57 @@ pub const DeclGen = struct {
1521 if (loaded_union.flagsUnordered(ip).layout == .@"packed") {1546 if (loaded_union.flagsUnordered(ip).layout == .@"packed") {
1522 if (field_ty.hasRuntimeBits(zcu)) {1547 if (field_ty.hasRuntimeBits(zcu)) {
1523 if (field_ty.isPtrAtRuntime(zcu)) {1548 if (field_ty.isPtrAtRuntime(zcu)) {
1524 try writer.writeByte('(');1549 try w.writeByte('(');
1525 try dg.renderCType(writer, ctype);1550 try dg.renderCType(w, ctype);
1526 try writer.writeByte(')');1551 try w.writeByte(')');
1527 } else if (field_ty.zigTypeTag(zcu) == .float) {1552 } else if (field_ty.zigTypeTag(zcu) == .float) {
1528 try writer.writeByte('(');1553 try w.writeByte('(');
1529 try dg.renderCType(writer, ctype);1554 try dg.renderCType(w, ctype);
1530 try writer.writeByte(')');1555 try w.writeByte(')');
1531 }1556 }
1532 try dg.renderValue(writer, Value.fromInterned(un.val), location);1557 try dg.renderValue(w, Value.fromInterned(un.val), location);
1533 } else try writer.writeAll("0");1558 } else try w.writeByte('0');
1534 return;1559 return;
1535 }1560 }
15361561
1537 const has_tag = loaded_union.hasTag(ip);1562 const has_tag = loaded_union.hasTag(ip);
1538 if (has_tag) try writer.writeByte('{');1563 if (has_tag) try w.writeByte('{');
1539 const aggregate = ctype.info(ctype_pool).aggregate;1564 const aggregate = ctype.info(ctype_pool).aggregate;
1540 for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {1565 for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {
1541 if (outer_field_index > 0) try writer.writeByte(',');1566 if (outer_field_index > 0) try w.writeByte(',');
1542 switch (if (has_tag)1567 switch (if (has_tag)
1543 aggregate.fields.at(outer_field_index, ctype_pool).name.index1568 aggregate.fields.at(outer_field_index, ctype_pool).name.index
1544 else1569 else
1545 .payload) {1570 .payload) {
1546 .tag => try dg.renderValue(1571 .tag => try dg.renderValue(
1547 writer,1572 w,
1548 Value.fromInterned(un.tag),1573 Value.fromInterned(un.tag),
1549 initializer_type,1574 initializer_type,
1550 ),1575 ),
1551 .payload => {1576 .payload => {
1552 try writer.writeByte('{');1577 try w.writeByte('{');
1553 if (field_ty.hasRuntimeBits(zcu)) {1578 if (field_ty.hasRuntimeBits(zcu)) {
1554 try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))});1579 try w.print(" .{f} = ", .{fmtIdentSolo(field_name.toSlice(ip))});
1555 try dg.renderValue(1580 try dg.renderValue(
1556 writer,1581 w,
1557 Value.fromInterned(un.val),1582 Value.fromInterned(un.val),
1558 initializer_type,1583 initializer_type,
1559 );1584 );
1560 try writer.writeByte(' ');1585 try w.writeByte(' ');
1561 } else for (0..loaded_union.field_types.len) |inner_field_index| {1586 } else for (0..loaded_union.field_types.len) |inner_field_index| {
1562 const inner_field_ty: Type = .fromInterned(1587 const inner_field_ty: Type = .fromInterned(
1563 loaded_union.field_types.get(ip)[inner_field_index],1588 loaded_union.field_types.get(ip)[inner_field_index],
1564 );1589 );
1565 if (!inner_field_ty.hasRuntimeBits(zcu)) continue;1590 if (!inner_field_ty.hasRuntimeBits(zcu)) continue;
1566 try dg.renderUndefValue(writer, inner_field_ty, initializer_type);1591 try dg.renderUndefValue(w, inner_field_ty, initializer_type);
1567 break;1592 break;
1568 }1593 }
1569 try writer.writeByte('}');1594 try w.writeByte('}');
1570 },1595 },
1571 else => unreachable,1596 else => unreachable,
1572 }1597 }
1573 }1598 }
1574 if (has_tag) try writer.writeByte('}');1599 if (has_tag) try w.writeByte('}');
1575 }1600 }
1576 },1601 },
1577 }1602 }
...@@ -1579,10 +1604,10 @@ pub const DeclGen = struct {...@@ -1579,10 +1604,10 @@ pub const DeclGen = struct {
15791604
1580 fn renderUndefValue(1605 fn renderUndefValue(
1581 dg: *DeclGen,1606 dg: *DeclGen,
1582 writer: anytype,1607 w: *Writer,
1583 ty: Type,1608 ty: Type,
1584 location: ValueRenderLocation,1609 location: ValueRenderLocation,
1585 ) error{ OutOfMemory, AnalysisFail }!void {1610 ) Error!void {
1586 const pt = dg.pt;1611 const pt = dg.pt;
1587 const zcu = pt.zcu;1612 const zcu = pt.zcu;
1588 const ip = &zcu.intern_pool;1613 const ip = &zcu.intern_pool;
...@@ -1612,57 +1637,57 @@ pub const DeclGen = struct {...@@ -1612,57 +1637,57 @@ pub const DeclGen = struct {
1612 // All unsigned ints matching float types are pre-allocated.1637 // All unsigned ints matching float types are pre-allocated.
1613 const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;1638 const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;
16141639
1615 try writer.writeAll("zig_make_");1640 try w.writeAll("zig_make_");
1616 try dg.renderTypeForBuiltinFnName(writer, ty);1641 try dg.renderTypeForBuiltinFnName(w, ty);
1617 try writer.writeByte('(');1642 try w.writeByte('(');
1618 switch (bits) {1643 switch (bits) {
1619 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),1644 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
1620 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),1645 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
1621 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),1646 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
1622 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),1647 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
1623 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),1648 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
1624 else => unreachable,1649 else => unreachable,
1625 }1650 }
1626 try writer.writeAll(", ");1651 try w.writeAll(", ");
1627 try dg.renderUndefValue(writer, repr_ty, .FunctionArgument);1652 try dg.renderUndefValue(w, repr_ty, .FunctionArgument);
1628 return writer.writeByte(')');1653 return w.writeByte(')');
1629 },1654 },
1630 .bool_type => try writer.writeAll(if (safety_on) "0xaa" else "false"),1655 .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"),
1631 else => switch (ip.indexToKey(ty.toIntern())) {1656 else => switch (ip.indexToKey(ty.toIntern())) {
1632 .simple_type,1657 .simple_type,
1633 .int_type,1658 .int_type,
1634 .enum_type,1659 .enum_type,
1635 .error_set_type,1660 .error_set_type,
1636 .inferred_error_set_type,1661 .inferred_error_set_type,
1637 => return writer.print("{x}", .{1662 => return w.print("{f}", .{
1638 try dg.fmtIntLiteral(try pt.undefValue(ty), location),1663 try dg.fmtIntLiteralHex(try pt.undefValue(ty), location),
1639 }),1664 }),
1640 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {1665 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1641 .one, .many, .c => {1666 .one, .many, .c => {
1642 try writer.writeAll("((");1667 try w.writeAll("((");
1643 try dg.renderCType(writer, ctype);1668 try dg.renderCType(w, ctype);
1644 return writer.print("){x})", .{1669 return w.print("){f})", .{
1645 try dg.fmtIntLiteral(.undef_usize, .Other),1670 try dg.fmtIntLiteralHex(.undef_usize, .Other),
1646 });1671 });
1647 },1672 },
1648 .slice => {1673 .slice => {
1649 if (!location.isInitializer()) {1674 if (!location.isInitializer()) {
1650 try writer.writeByte('(');1675 try w.writeByte('(');
1651 try dg.renderCType(writer, ctype);1676 try dg.renderCType(w, ctype);
1652 try writer.writeByte(')');1677 try w.writeByte(')');
1653 }1678 }
16541679
1655 try writer.writeAll("{(");1680 try w.writeAll("{(");
1656 const ptr_ty = ty.slicePtrFieldType(zcu);1681 const ptr_ty = ty.slicePtrFieldType(zcu);
1657 try dg.renderType(writer, ptr_ty);1682 try dg.renderType(w, ptr_ty);
1658 return writer.print("){x}, {0x}}}", .{1683 return w.print("){f}, {0f}}}", .{
1659 try dg.fmtIntLiteral(.undef_usize, .Other),1684 try dg.fmtIntLiteralHex(.undef_usize, .Other),
1660 });1685 });
1661 },1686 },
1662 },1687 },
1663 .opt_type => |child_type| switch (ctype.info(ctype_pool)) {1688 .opt_type => |child_type| switch (ctype.info(ctype_pool)) {
1664 .basic, .pointer => try dg.renderUndefValue(1689 .basic, .pointer => try dg.renderUndefValue(
1665 writer,1690 w,
1666 .fromInterned(if (ctype.isBool()) .bool_type else child_type),1691 .fromInterned(if (ctype.isBool()) .bool_type else child_type),
1667 location,1692 location,
1668 ),1693 ),
...@@ -1671,21 +1696,21 @@ pub const DeclGen = struct {...@@ -1671,21 +1696,21 @@ pub const DeclGen = struct {
1671 switch (aggregate.fields.at(0, ctype_pool).name.index) {1696 switch (aggregate.fields.at(0, ctype_pool).name.index) {
1672 .is_null, .payload => {},1697 .is_null, .payload => {},
1673 .ptr, .len => return dg.renderUndefValue(1698 .ptr, .len => return dg.renderUndefValue(
1674 writer,1699 w,
1675 .fromInterned(child_type),1700 .fromInterned(child_type),
1676 location,1701 location,
1677 ),1702 ),
1678 else => unreachable,1703 else => unreachable,
1679 }1704 }
1680 if (!location.isInitializer()) {1705 if (!location.isInitializer()) {
1681 try writer.writeByte('(');1706 try w.writeByte('(');
1682 try dg.renderCType(writer, ctype);1707 try dg.renderCType(w, ctype);
1683 try writer.writeByte(')');1708 try w.writeByte(')');
1684 }1709 }
1685 try writer.writeByte('{');1710 try w.writeByte('{');
1686 for (0..aggregate.fields.len) |field_index| {1711 for (0..aggregate.fields.len) |field_index| {
1687 if (field_index > 0) try writer.writeByte(',');1712 if (field_index > 0) try w.writeByte(',');
1688 try dg.renderUndefValue(writer, .fromInterned(1713 try dg.renderUndefValue(w, .fromInterned(
1689 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {1714 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1690 .is_null => .bool_type,1715 .is_null => .bool_type,
1691 .payload => child_type,1716 .payload => child_type,
...@@ -1693,7 +1718,7 @@ pub const DeclGen = struct {...@@ -1693,7 +1718,7 @@ pub const DeclGen = struct {
1693 },1718 },
1694 ), initializer_type);1719 ), initializer_type);
1695 }1720 }
1696 try writer.writeByte('}');1721 try w.writeByte('}');
1697 },1722 },
1698 },1723 },
1699 .struct_type => {1724 .struct_type => {
...@@ -1701,117 +1726,117 @@ pub const DeclGen = struct {...@@ -1701,117 +1726,117 @@ pub const DeclGen = struct {
1701 switch (loaded_struct.layout) {1726 switch (loaded_struct.layout) {
1702 .auto, .@"extern" => {1727 .auto, .@"extern" => {
1703 if (!location.isInitializer()) {1728 if (!location.isInitializer()) {
1704 try writer.writeByte('(');1729 try w.writeByte('(');
1705 try dg.renderCType(writer, ctype);1730 try dg.renderCType(w, ctype);
1706 try writer.writeByte(')');1731 try w.writeByte(')');
1707 }1732 }
17081733
1709 try writer.writeByte('{');1734 try w.writeByte('{');
1710 var field_it = loaded_struct.iterateRuntimeOrder(ip);1735 var field_it = loaded_struct.iterateRuntimeOrder(ip);
1711 var need_comma = false;1736 var need_comma = false;
1712 while (field_it.next()) |field_index| {1737 while (field_it.next()) |field_index| {
1713 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);1738 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1714 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;1739 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
17151740
1716 if (need_comma) try writer.writeByte(',');1741 if (need_comma) try w.writeByte(',');
1717 need_comma = true;1742 need_comma = true;
1718 try dg.renderUndefValue(writer, field_ty, initializer_type);1743 try dg.renderUndefValue(w, field_ty, initializer_type);
1719 }1744 }
1720 return writer.writeByte('}');1745 return w.writeByte('}');
1721 },1746 },
1722 .@"packed" => return writer.print("{x}", .{1747 .@"packed" => return w.print("{f}", .{
1723 try dg.fmtIntLiteral(try pt.undefValue(ty), .Other),1748 try dg.fmtIntLiteralHex(try pt.undefValue(ty), .Other),
1724 }),1749 }),
1725 }1750 }
1726 },1751 },
1727 .tuple_type => |tuple_info| {1752 .tuple_type => |tuple_info| {
1728 if (!location.isInitializer()) {1753 if (!location.isInitializer()) {
1729 try writer.writeByte('(');1754 try w.writeByte('(');
1730 try dg.renderCType(writer, ctype);1755 try dg.renderCType(w, ctype);
1731 try writer.writeByte(')');1756 try w.writeByte(')');
1732 }1757 }
17331758
1734 try writer.writeByte('{');1759 try w.writeByte('{');
1735 var need_comma = false;1760 var need_comma = false;
1736 for (0..tuple_info.types.len) |field_index| {1761 for (0..tuple_info.types.len) |field_index| {
1737 if (tuple_info.values.get(ip)[field_index] != .none) continue;1762 if (tuple_info.values.get(ip)[field_index] != .none) continue;
1738 const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]);1763 const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]);
1739 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;1764 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
17401765
1741 if (need_comma) try writer.writeByte(',');1766 if (need_comma) try w.writeByte(',');
1742 need_comma = true;1767 need_comma = true;
1743 try dg.renderUndefValue(writer, field_ty, initializer_type);1768 try dg.renderUndefValue(w, field_ty, initializer_type);
1744 }1769 }
1745 return writer.writeByte('}');1770 return w.writeByte('}');
1746 },1771 },
1747 .union_type => {1772 .union_type => {
1748 const loaded_union = ip.loadUnionType(ty.toIntern());1773 const loaded_union = ip.loadUnionType(ty.toIntern());
1749 switch (loaded_union.flagsUnordered(ip).layout) {1774 switch (loaded_union.flagsUnordered(ip).layout) {
1750 .auto, .@"extern" => {1775 .auto, .@"extern" => {
1751 if (!location.isInitializer()) {1776 if (!location.isInitializer()) {
1752 try writer.writeByte('(');1777 try w.writeByte('(');
1753 try dg.renderCType(writer, ctype);1778 try dg.renderCType(w, ctype);
1754 try writer.writeByte(')');1779 try w.writeByte(')');
1755 }1780 }
17561781
1757 const has_tag = loaded_union.hasTag(ip);1782 const has_tag = loaded_union.hasTag(ip);
1758 if (has_tag) try writer.writeByte('{');1783 if (has_tag) try w.writeByte('{');
1759 const aggregate = ctype.info(ctype_pool).aggregate;1784 const aggregate = ctype.info(ctype_pool).aggregate;
1760 for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {1785 for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {
1761 if (outer_field_index > 0) try writer.writeByte(',');1786 if (outer_field_index > 0) try w.writeByte(',');
1762 switch (if (has_tag)1787 switch (if (has_tag)
1763 aggregate.fields.at(outer_field_index, ctype_pool).name.index1788 aggregate.fields.at(outer_field_index, ctype_pool).name.index
1764 else1789 else
1765 .payload) {1790 .payload) {
1766 .tag => try dg.renderUndefValue(1791 .tag => try dg.renderUndefValue(
1767 writer,1792 w,
1768 .fromInterned(loaded_union.enum_tag_ty),1793 .fromInterned(loaded_union.enum_tag_ty),
1769 initializer_type,1794 initializer_type,
1770 ),1795 ),
1771 .payload => {1796 .payload => {
1772 try writer.writeByte('{');1797 try w.writeByte('{');
1773 for (0..loaded_union.field_types.len) |inner_field_index| {1798 for (0..loaded_union.field_types.len) |inner_field_index| {
1774 const inner_field_ty: Type = .fromInterned(1799 const inner_field_ty: Type = .fromInterned(
1775 loaded_union.field_types.get(ip)[inner_field_index],1800 loaded_union.field_types.get(ip)[inner_field_index],
1776 );1801 );
1777 if (!inner_field_ty.hasRuntimeBits(pt.zcu)) continue;1802 if (!inner_field_ty.hasRuntimeBits(pt.zcu)) continue;
1778 try dg.renderUndefValue(1803 try dg.renderUndefValue(
1779 writer,1804 w,
1780 inner_field_ty,1805 inner_field_ty,
1781 initializer_type,1806 initializer_type,
1782 );1807 );
1783 break;1808 break;
1784 }1809 }
1785 try writer.writeByte('}');1810 try w.writeByte('}');
1786 },1811 },
1787 else => unreachable,1812 else => unreachable,
1788 }1813 }
1789 }1814 }
1790 if (has_tag) try writer.writeByte('}');1815 if (has_tag) try w.writeByte('}');
1791 },1816 },
1792 .@"packed" => return writer.print("{x}", .{1817 .@"packed" => return w.print("{f}", .{
1793 try dg.fmtIntLiteral(try pt.undefValue(ty), .Other),1818 try dg.fmtIntLiteralHex(try pt.undefValue(ty), .Other),
1794 }),1819 }),
1795 }1820 }
1796 },1821 },
1797 .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) {1822 .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) {
1798 .basic => try dg.renderUndefValue(1823 .basic => try dg.renderUndefValue(
1799 writer,1824 w,
1800 .fromInterned(error_union_type.error_set_type),1825 .fromInterned(error_union_type.error_set_type),
1801 location,1826 location,
1802 ),1827 ),
1803 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,1828 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1804 .aggregate => |aggregate| {1829 .aggregate => |aggregate| {
1805 if (!location.isInitializer()) {1830 if (!location.isInitializer()) {
1806 try writer.writeByte('(');1831 try w.writeByte('(');
1807 try dg.renderCType(writer, ctype);1832 try dg.renderCType(w, ctype);
1808 try writer.writeByte(')');1833 try w.writeByte(')');
1809 }1834 }
1810 try writer.writeByte('{');1835 try w.writeByte('{');
1811 for (0..aggregate.fields.len) |field_index| {1836 for (0..aggregate.fields.len) |field_index| {
1812 if (field_index > 0) try writer.writeByte(',');1837 if (field_index > 0) try w.writeByte(',');
1813 try dg.renderUndefValue(1838 try dg.renderUndefValue(
1814 writer,1839 w,
1815 .fromInterned(1840 .fromInterned(
1816 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {1841 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1817 .@"error" => error_union_type.error_set_type,1842 .@"error" => error_union_type.error_set_type,
...@@ -1822,14 +1847,14 @@ pub const DeclGen = struct {...@@ -1822,14 +1847,14 @@ pub const DeclGen = struct {
1822 initializer_type,1847 initializer_type,
1823 );1848 );
1824 }1849 }
1825 try writer.writeByte('}');1850 try w.writeByte('}');
1826 },1851 },
1827 },1852 },
1828 .array_type, .vector_type => {1853 .array_type, .vector_type => {
1829 const ai = ty.arrayInfo(zcu);1854 const ai = ty.arrayInfo(zcu);
1830 if (ai.elem_type.eql(.u8, zcu)) {1855 if (ai.elem_type.eql(.u8, zcu)) {
1831 const c_len = ty.arrayLenIncludingSentinel(zcu);1856 const c_len = ty.arrayLenIncludingSentinel(zcu);
1832 var literal = stringLiteral(writer, c_len);1857 var literal: StringLiteral = .init(w, @intCast(c_len));
1833 try literal.start();1858 try literal.start();
1834 var index: u64 = 0;1859 var index: u64 = 0;
1835 while (index < c_len) : (index += 1)1860 while (index < c_len) : (index += 1)
...@@ -1837,19 +1862,19 @@ pub const DeclGen = struct {...@@ -1837,19 +1862,19 @@ pub const DeclGen = struct {
1837 return literal.end();1862 return literal.end();
1838 } else {1863 } else {
1839 if (!location.isInitializer()) {1864 if (!location.isInitializer()) {
1840 try writer.writeByte('(');1865 try w.writeByte('(');
1841 try dg.renderCType(writer, ctype);1866 try dg.renderCType(w, ctype);
1842 try writer.writeByte(')');1867 try w.writeByte(')');
1843 }1868 }
18441869
1845 try writer.writeByte('{');1870 try w.writeByte('{');
1846 const c_len = ty.arrayLenIncludingSentinel(zcu);1871 const c_len = ty.arrayLenIncludingSentinel(zcu);
1847 var index: u64 = 0;1872 var index: u64 = 0;
1848 while (index < c_len) : (index += 1) {1873 while (index < c_len) : (index += 1) {
1849 if (index > 0) try writer.writeAll(", ");1874 if (index > 0) try w.writeAll(", ");
1850 try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type);1875 try dg.renderUndefValue(w, ty.childType(zcu), initializer_type);
1851 }1876 }
1852 return writer.writeByte('}');1877 return w.writeByte('}');
1853 }1878 }
1854 },1879 },
1855 .anyframe_type,1880 .anyframe_type,
...@@ -1882,13 +1907,13 @@ pub const DeclGen = struct {...@@ -1882,13 +1907,13 @@ pub const DeclGen = struct {
18821907
1883 fn renderFunctionSignature(1908 fn renderFunctionSignature(
1884 dg: *DeclGen,1909 dg: *DeclGen,
1885 w: anytype,1910 w: *Writer,
1886 fn_val: Value,1911 fn_val: Value,
1887 fn_align: InternPool.Alignment,1912 fn_align: InternPool.Alignment,
1888 kind: CType.Kind,1913 kind: CType.Kind,
1889 name: union(enum) {1914 name: union(enum) {
1890 nav: InternPool.Nav.Index,1915 nav: InternPool.Nav.Index,
1891 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),1916 fmt_ctype_pool_string: std.fmt.Formatter(CTypePoolStringFormatData, formatCTypePoolString),
1892 @"export": struct {1917 @"export": struct {
1893 main_name: InternPool.NullTerminatedString,1918 main_name: InternPool.NullTerminatedString,
1894 extern_name: InternPool.NullTerminatedString,1919 extern_name: InternPool.NullTerminatedString,
...@@ -1925,15 +1950,15 @@ pub const DeclGen = struct {...@@ -1925,15 +1950,15 @@ pub const DeclGen = struct {
1925 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});1950 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});
19261951
1927 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {1952 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
1928 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });1953 try w.print("{f}zig_callconv({s})", .{ trailing, call_conv });
1929 trailing = .maybe_space;1954 trailing = .maybe_space;
1930 }1955 }
19311956
1932 try w.print("{}", .{trailing});1957 try w.print("{f}", .{trailing});
1933 switch (name) {1958 switch (name) {
1934 .nav => |nav| try dg.renderNavName(w, nav),1959 .nav => |nav| try dg.renderNavName(w, nav),
1935 .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}),1960 .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}),
1936 .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}),1961 .@"export" => |@"export"| try w.print("{f}", .{fmtIdentSolo(@"export".extern_name.toSlice(ip))}),
1937 }1962 }
19381963
1939 try renderTypeSuffix(1964 try renderTypeSuffix(
...@@ -1960,17 +1985,17 @@ pub const DeclGen = struct {...@@ -1960,17 +1985,17 @@ pub const DeclGen = struct {
1960 const is_mangled = isMangledIdent(extern_name, true);1985 const is_mangled = isMangledIdent(extern_name, true);
1961 const is_export = @"export".extern_name != @"export".main_name;1986 const is_export = @"export".extern_name != @"export".main_name;
1962 if (is_mangled and is_export) {1987 if (is_mangled and is_export) {
1963 try w.print(" zig_mangled_export({ }, {s}, {s})", .{1988 try w.print(" zig_mangled_export({f}, {f}, {f})", .{
1964 fmtIdent(extern_name),1989 fmtIdentSolo(extern_name),
1965 fmtStringLiteral(extern_name, null),1990 fmtStringLiteral(extern_name, null),
1966 fmtStringLiteral(@"export".main_name.toSlice(ip), null),1991 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1967 });1992 });
1968 } else if (is_mangled) {1993 } else if (is_mangled) {
1969 try w.print(" zig_mangled({ }, {s})", .{1994 try w.print(" zig_mangled({f}, {f})", .{
1970 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),1995 fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null),
1971 });1996 });
1972 } else if (is_export) {1997 } else if (is_export) {
1973 try w.print(" zig_export({s}, {s})", .{1998 try w.print(" zig_export({f}, {f})", .{
1974 fmtStringLiteral(@"export".main_name.toSlice(ip), null),1999 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1975 fmtStringLiteral(extern_name, null),2000 fmtStringLiteral(extern_name, null),
1976 });2001 });
...@@ -2003,11 +2028,11 @@ pub const DeclGen = struct {...@@ -2003,11 +2028,11 @@ pub const DeclGen = struct {
2003 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |2028 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2004 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |2029 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2005 ///2030 ///
2006 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{OutOfMemory}!void {2031 fn renderType(dg: *DeclGen, w: *Writer, t: Type) Error!void {
2007 try dg.renderCType(w, try dg.ctypeFromType(t, .complete));2032 try dg.renderCType(w, try dg.ctypeFromType(t, .complete));
2008 }2033 }
20092034
2010 fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{OutOfMemory}!void {2035 fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void {
2011 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});2036 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
2012 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});2037 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
2013 }2038 }
...@@ -2022,7 +2047,7 @@ pub const DeclGen = struct {...@@ -2022,7 +2047,7 @@ pub const DeclGen = struct {
2022 value: Value,2047 value: Value,
2023 },2048 },
20242049
2025 pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, location: ValueRenderLocation) !void {2050 pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void {
2026 switch (self.*) {2051 switch (self.*) {
2027 .c_value => |v| {2052 .c_value => |v| {
2028 try v.f.writeCValue(w, v.value, location);2053 try v.f.writeCValue(w, v.value, location);
...@@ -2068,7 +2093,7 @@ pub const DeclGen = struct {...@@ -2068,7 +2093,7 @@ pub const DeclGen = struct {
2068 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))2093 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
2069 fn renderIntCast(2094 fn renderIntCast(
2070 dg: *DeclGen,2095 dg: *DeclGen,
2071 w: anytype,2096 w: *Writer,
2072 dest_ty: Type,2097 dest_ty: Type,
2073 context: IntCastContext,2098 context: IntCastContext,
2074 src_ty: Type,2099 src_ty: Type,
...@@ -2118,7 +2143,7 @@ pub const DeclGen = struct {...@@ -2118,7 +2143,7 @@ pub const DeclGen = struct {
2118 } else if (dest_bits > 64 and src_bits <= 64) {2143 } else if (dest_bits > 64 and src_bits <= 64) {
2119 try w.writeAll("zig_make_");2144 try w.writeAll("zig_make_");
2120 try dg.renderTypeForBuiltinFnName(w, dest_ty);2145 try dg.renderTypeForBuiltinFnName(w, dest_ty);
2121 try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral?2146 try w.writeAll("(0, ");
2122 if (src_is_ptr) {2147 if (src_is_ptr) {
2123 try w.writeByte('(');2148 try w.writeByte('(');
2124 try dg.renderType(w, src_eff_ty);2149 try dg.renderType(w, src_eff_ty);
...@@ -2152,13 +2177,13 @@ pub const DeclGen = struct {...@@ -2152,13 +2177,13 @@ pub const DeclGen = struct {
2152 ///2177 ///
2153 fn renderTypeAndName(2178 fn renderTypeAndName(
2154 dg: *DeclGen,2179 dg: *DeclGen,
2155 w: anytype,2180 w: *Writer,
2156 ty: Type,2181 ty: Type,
2157 name: CValue,2182 name: CValue,
2158 qualifiers: CQualifiers,2183 qualifiers: CQualifiers,
2159 alignment: Alignment,2184 alignment: Alignment,
2160 kind: CType.Kind,2185 kind: CType.Kind,
2161 ) error{ OutOfMemory, AnalysisFail }!void {2186 ) !void {
2162 try dg.renderCTypeAndName(2187 try dg.renderCTypeAndName(
2163 w,2188 w,
2164 try dg.ctypeFromType(ty, kind),2189 try dg.ctypeFromType(ty, kind),
...@@ -2173,12 +2198,12 @@ pub const DeclGen = struct {...@@ -2173,12 +2198,12 @@ pub const DeclGen = struct {
21732198
2174 fn renderCTypeAndName(2199 fn renderCTypeAndName(
2175 dg: *DeclGen,2200 dg: *DeclGen,
2176 w: anytype,2201 w: *Writer,
2177 ctype: CType,2202 ctype: CType,
2178 name: CValue,2203 name: CValue,
2179 qualifiers: CQualifiers,2204 qualifiers: CQualifiers,
2180 alignas: CType.AlignAs,2205 alignas: CType.AlignAs,
2181 ) error{ OutOfMemory, AnalysisFail }!void {2206 ) !void {
2182 const zcu = dg.pt.zcu;2207 const zcu = dg.pt.zcu;
2183 switch (alignas.abiOrder()) {2208 switch (alignas.abiOrder()) {
2184 .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),2209 .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),
...@@ -2186,24 +2211,24 @@ pub const DeclGen = struct {...@@ -2186,24 +2211,24 @@ pub const DeclGen = struct {
2186 .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),2211 .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
2187 }2212 }
21882213
2189 try w.print("{}", .{2214 try w.print("{f}", .{
2190 try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers),2215 try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers),
2191 });2216 });
2192 try dg.writeName(w, name);2217 try dg.writeName(w, name);
2193 try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{});2218 try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{});
2194 }2219 }
21952220
2196 fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {2221 fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void {
2197 switch (c_value) {2222 switch (c_value) {
2198 .new_local, .local => |i| try w.print("t{d}", .{i}),2223 .new_local, .local => |i| try w.print("t{d}", .{i}),
2199 .constant => |uav| try renderUavName(w, uav),2224 .constant => |uav| try renderUavName(w, uav),
2200 .nav => |nav| try dg.renderNavName(w, nav),2225 .nav => |nav| try dg.renderNavName(w, nav),
2201 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),2226 .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}),
2202 else => unreachable,2227 else => unreachable,
2203 }2228 }
2204 }2229 }
22052230
2206 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {2231 fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void {
2207 switch (c_value) {2232 switch (c_value) {
2208 .none, .new_local, .local, .local_ref => unreachable,2233 .none, .new_local, .local, .local_ref => unreachable,
2209 .constant => |uav| try renderUavName(w, uav),2234 .constant => |uav| try renderUavName(w, uav),
...@@ -2215,18 +2240,18 @@ pub const DeclGen = struct {...@@ -2215,18 +2240,18 @@ pub const DeclGen = struct {
2215 try dg.renderNavName(w, nav);2240 try dg.renderNavName(w, nav);
2216 },2241 },
2217 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),2242 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),
2218 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),2243 .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}),
2219 .payload_identifier => |ident| try w.print("{ }.{ }", .{2244 .payload_identifier => |ident| try w.print("{f}.{f}", .{
2220 fmtIdent("payload"),2245 fmtIdentSolo("payload"),
2221 fmtIdent(ident),2246 fmtIdentSolo(ident),
2222 }),2247 }),
2223 .ctype_pool_string => |string| try w.print("{ }", .{2248 .ctype_pool_string => |string| try w.print("{f}", .{
2224 fmtCTypePoolString(string, &dg.ctype_pool),2249 fmtCTypePoolString(string, &dg.ctype_pool, true),
2225 }),2250 }),
2226 }2251 }
2227 }2252 }
22282253
2229 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {2254 fn writeCValueDeref(dg: *DeclGen, w: *Writer, c_value: CValue) !void {
2230 switch (c_value) {2255 switch (c_value) {
2231 .none,2256 .none,
2232 .new_local,2257 .new_local,
...@@ -2245,26 +2270,31 @@ pub const DeclGen = struct {...@@ -2245,26 +2270,31 @@ pub const DeclGen = struct {
2245 },2270 },
2246 .nav_ref => |nav| try dg.renderNavName(w, nav),2271 .nav_ref => |nav| try dg.renderNavName(w, nav),
2247 .undef => unreachable,2272 .undef => unreachable,
2248 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),2273 .identifier => |ident| try w.print("(*{f})", .{fmtIdentSolo(ident)}),
2249 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{2274 .payload_identifier => |ident| try w.print("(*{f}.{f})", .{
2250 fmtIdent("payload"),2275 fmtIdentSolo("payload"),
2251 fmtIdent(ident),2276 fmtIdentSolo(ident),
2252 }),2277 }),
2253 }2278 }
2254 }2279 }
22552280
2256 fn writeCValueMember(2281 fn writeCValueMember(
2257 dg: *DeclGen,2282 dg: *DeclGen,
2258 writer: anytype,2283 w: *Writer,
2259 c_value: CValue,2284 c_value: CValue,
2260 member: CValue,2285 member: CValue,
2261 ) error{ OutOfMemory, AnalysisFail }!void {2286 ) Error!void {
2262 try dg.writeCValue(writer, c_value);2287 try dg.writeCValue(w, c_value);
2263 try writer.writeByte('.');2288 try w.writeByte('.');
2264 try dg.writeCValue(writer, member);2289 try dg.writeCValue(w, member);
2265 }2290 }
22662291
2267 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {2292 fn writeCValueDerefMember(
2293 dg: *DeclGen,
2294 w: *Writer,
2295 c_value: CValue,
2296 member: CValue,
2297 ) !void {
2268 switch (c_value) {2298 switch (c_value) {
2269 .none,2299 .none,
2270 .new_local,2300 .new_local,
...@@ -2278,15 +2308,15 @@ pub const DeclGen = struct {...@@ -2278,15 +2308,15 @@ pub const DeclGen = struct {
2278 .ctype_pool_string,2308 .ctype_pool_string,
2279 => unreachable,2309 => unreachable,
2280 .nav, .identifier, .payload_identifier => {2310 .nav, .identifier, .payload_identifier => {
2281 try dg.writeCValue(writer, c_value);2311 try dg.writeCValue(w, c_value);
2282 try writer.writeAll("->");2312 try w.writeAll("->");
2283 },2313 },
2284 .nav_ref => {2314 .nav_ref => {
2285 try dg.writeCValueDeref(writer, c_value);2315 try dg.writeCValueDeref(w, c_value);
2286 try writer.writeByte('.');2316 try w.writeByte('.');
2287 },2317 },
2288 }2318 }
2289 try dg.writeCValue(writer, member);2319 try dg.writeCValue(w, member);
2290 }2320 }
22912321
2292 fn renderFwdDecl(2322 fn renderFwdDecl(
...@@ -2302,7 +2332,7 @@ pub const DeclGen = struct {...@@ -2302,7 +2332,7 @@ pub const DeclGen = struct {
2302 const zcu = dg.pt.zcu;2332 const zcu = dg.pt.zcu;
2303 const ip = &zcu.intern_pool;2333 const ip = &zcu.intern_pool;
2304 const nav = ip.getNav(nav_index);2334 const nav = ip.getNav(nav_index);
2305 const fwd = dg.fwdDeclWriter();2335 const fwd = &dg.fwd_decl.writer;
2306 try fwd.writeAll(switch (flags.linkage) {2336 try fwd.writeAll(switch (flags.linkage) {
2307 .internal => "static ",2337 .internal => "static ",
2308 .strong, .weak, .link_once => "zig_extern ",2338 .strong, .weak, .link_once => "zig_extern ",
...@@ -2328,36 +2358,36 @@ pub const DeclGen = struct {...@@ -2328,36 +2358,36 @@ pub const DeclGen = struct {
2328 try fwd.writeAll(";\n");2358 try fwd.writeAll(";\n");
2329 }2359 }
23302360
2331 fn renderNavName(dg: *DeclGen, writer: anytype, nav_index: InternPool.Nav.Index) !void {2361 fn renderNavName(dg: *DeclGen, w: *Writer, nav_index: InternPool.Nav.Index) !void {
2332 const zcu = dg.pt.zcu;2362 const zcu = dg.pt.zcu;
2333 const ip = &zcu.intern_pool;2363 const ip = &zcu.intern_pool;
2334 const nav = ip.getNav(nav_index);2364 const nav = ip.getNav(nav_index);
2335 if (nav.getExtern(ip)) |@"extern"| {2365 if (nav.getExtern(ip)) |@"extern"| {
2336 try writer.print("{ }", .{2366 try w.print("{f}", .{
2337 fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),2367 fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),
2338 });2368 });
2339 } else {2369 } else {
2340 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),2370 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
2341 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.2371 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
2342 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);2372 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
2343 try writer.print("{}__{d}", .{2373 try w.print("{f}__{d}", .{
2344 fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),2374 fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]),
2345 @intFromEnum(nav_index),2375 @intFromEnum(nav_index),
2346 });2376 });
2347 }2377 }
2348 }2378 }
23492379
2350 fn renderUavName(writer: anytype, uav: Value) !void {2380 fn renderUavName(w: *Writer, uav: Value) !void {
2351 try writer.print("__anon_{d}", .{@intFromEnum(uav.toIntern())});2381 try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())});
2352 }2382 }
23532383
2354 fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void {2384 fn renderTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ty: Type) !void {
2355 try dg.renderCTypeForBuiltinFnName(writer, try dg.ctypeFromType(ty, .complete));2385 try dg.renderCTypeForBuiltinFnName(w, try dg.ctypeFromType(ty, .complete));
2356 }2386 }
23572387
2358 fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void {2388 fn renderCTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ctype: CType) !void {
2359 switch (ctype.info(&dg.ctype_pool)) {2389 switch (ctype.info(&dg.ctype_pool)) {
2360 else => |ctype_info| try writer.print("{c}{d}", .{2390 else => |ctype_info| try w.print("{c}{d}", .{
2361 if (ctype.isBool())2391 if (ctype.isBool())
2362 signAbbrev(.unsigned)2392 signAbbrev(.unsigned)
2363 else if (ctype.isInteger())2393 else if (ctype.isInteger())
...@@ -2370,11 +2400,11 @@ pub const DeclGen = struct {...@@ -2370,11 +2400,11 @@ pub const DeclGen = struct {
2370 return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}),2400 return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}),
2371 if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8,2401 if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8,
2372 }),2402 }),
2373 .array => try writer.writeAll("big"),2403 .array => try w.writeAll("big"),
2374 }2404 }
2375 }2405 }
23762406
2377 fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {2407 fn renderBuiltinInfo(dg: *DeclGen, w: *Writer, ty: Type, info: BuiltinInfo) !void {
2378 const ctype = try dg.ctypeFromType(ty, .complete);2408 const ctype = try dg.ctypeFromType(ty, .complete);
2379 const is_big = ctype.info(&dg.ctype_pool) == .array;2409 const is_big = ctype.info(&dg.ctype_pool) == .array;
2380 switch (info) {2410 switch (info) {
...@@ -2389,8 +2419,8 @@ pub const DeclGen = struct {...@@ -2389,8 +2419,8 @@ pub const DeclGen = struct {
2389 .bits = @intCast(ty.bitSize(zcu)),2419 .bits = @intCast(ty.bitSize(zcu)),
2390 };2420 };
23912421
2392 if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});2422 if (is_big) try w.print(", {}", .{int_info.signedness == .signed});
2393 try writer.print(", {}", .{try dg.fmtIntLiteral(2423 try w.print(", {f}", .{try dg.fmtIntLiteralDec(
2394 try pt.intValue(if (is_big) .u16 else .u8, int_info.bits),2424 try pt.intValue(if (is_big) .u16 else .u8, int_info.bits),
2395 .FunctionArgument,2425 .FunctionArgument,
2396 )});2426 )});
...@@ -2400,18 +2430,38 @@ pub const DeclGen = struct {...@@ -2400,18 +2430,38 @@ pub const DeclGen = struct {
2400 dg: *DeclGen,2430 dg: *DeclGen,
2401 val: Value,2431 val: Value,
2402 loc: ValueRenderLocation,2432 loc: ValueRenderLocation,
2403 ) !std.fmt.Formatter(formatIntLiteral) {2433 base: u8,
2434 case: std.fmt.Case,
2435 ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
2404 const zcu = dg.pt.zcu;2436 const zcu = dg.pt.zcu;
2405 const kind = loc.toCTypeKind();2437 const kind = loc.toCTypeKind();
2406 const ty = val.typeOf(zcu);2438 const ty = val.typeOf(zcu);
2407 return std.fmt.Formatter(formatIntLiteral){ .data = .{2439 return .{ .data = .{
2408 .dg = dg,2440 .dg = dg,
2409 .int_info = ty.intInfo(zcu),2441 .int_info = ty.intInfo(zcu),
2410 .kind = kind,2442 .kind = kind,
2411 .ctype = try dg.ctypeFromType(ty, kind),2443 .ctype = try dg.ctypeFromType(ty, kind),
2412 .val = val,2444 .val = val,
2445 .base = base,
2446 .case = case,
2413 } };2447 } };
2414 }2448 }
2449
2450 fn fmtIntLiteralDec(
2451 dg: *DeclGen,
2452 val: Value,
2453 loc: ValueRenderLocation,
2454 ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
2455 return fmtIntLiteral(dg, val, loc, 10, .lower);
2456 }
2457
2458 fn fmtIntLiteralHex(
2459 dg: *DeclGen,
2460 val: Value,
2461 loc: ValueRenderLocation,
2462 ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
2463 return fmtIntLiteral(dg, val, loc, 16, .lower);
2464 }
2415};2465};
24162466
2417const CTypeFix = enum { prefix, suffix };2467const CTypeFix = enum { prefix, suffix };
...@@ -2421,28 +2471,19 @@ const RenderCTypeTrailing = enum {...@@ -2421,28 +2471,19 @@ const RenderCTypeTrailing = enum {
2421 no_space,2471 no_space,
2422 maybe_space,2472 maybe_space,
24232473
2424 pub fn format(2474 pub fn format(self: @This(), w: *Writer) Writer.Error!void {
2425 self: @This(),
2426 comptime fmt: []const u8,
2427 _: std.fmt.FormatOptions,
2428 w: anytype,
2429 ) @TypeOf(w).Error!void {
2430 if (fmt.len != 0)
2431 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++
2432 @typeName(@This()) ++ "'");
2433 comptime assert(fmt.len == 0);
2434 switch (self) {2475 switch (self) {
2435 .no_space => {},2476 .no_space => {},
2436 .maybe_space => try w.writeByte(' '),2477 .maybe_space => try w.writeByte(' '),
2437 }2478 }
2438 }2479 }
2439};2480};
2440fn renderAlignedTypeName(w: anytype, ctype: CType) !void {2481fn renderAlignedTypeName(w: *Writer, ctype: CType) !void {
2441 try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});2482 try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});
2442}2483}
2443fn renderFwdDeclTypeName(2484fn renderFwdDeclTypeName(
2444 zcu: *Zcu,2485 zcu: *Zcu,
2445 w: anytype,2486 w: *Writer,
2446 ctype: CType,2487 ctype: CType,
2447 fwd_decl: CType.Info.FwdDecl,2488 fwd_decl: CType.Info.FwdDecl,
2448 attributes: []const u8,2489 attributes: []const u8,
...@@ -2451,8 +2492,8 @@ fn renderFwdDeclTypeName(...@@ -2451,8 +2492,8 @@ fn renderFwdDeclTypeName(
2451 try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });2492 try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });
2452 switch (fwd_decl.name) {2493 switch (fwd_decl.name) {
2453 .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),2494 .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),
2454 .index => |index| try w.print("{}__{d}", .{2495 .index => |index| try w.print("{f}__{d}", .{
2455 fmtIdent(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),2496 fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),
2456 @intFromEnum(index),2497 @intFromEnum(index),
2457 }),2498 }),
2458 }2499 }
...@@ -2461,17 +2502,17 @@ fn renderTypePrefix(...@@ -2461,17 +2502,17 @@ fn renderTypePrefix(
2461 pass: DeclGen.Pass,2502 pass: DeclGen.Pass,
2462 ctype_pool: *const CType.Pool,2503 ctype_pool: *const CType.Pool,
2463 zcu: *Zcu,2504 zcu: *Zcu,
2464 w: anytype,2505 w: *Writer,
2465 ctype: CType,2506 ctype: CType,
2466 parent_fix: CTypeFix,2507 parent_fix: CTypeFix,
2467 qualifiers: CQualifiers,2508 qualifiers: CQualifiers,
2468) @TypeOf(w).Error!RenderCTypeTrailing {2509) Writer.Error!RenderCTypeTrailing {
2469 var trailing = RenderCTypeTrailing.maybe_space;2510 var trailing = RenderCTypeTrailing.maybe_space;
2470 switch (ctype.info(ctype_pool)) {2511 switch (ctype.info(ctype_pool)) {
2471 .basic => |basic_info| try w.writeAll(@tagName(basic_info)),2512 .basic => |basic_info| try w.writeAll(@tagName(basic_info)),
24722513
2473 .pointer => |pointer_info| {2514 .pointer => |pointer_info| {
2474 try w.print("{}*", .{try renderTypePrefix(2515 try w.print("{f}*", .{try renderTypePrefix(
2475 pass,2516 pass,
2476 ctype_pool,2517 ctype_pool,
2477 zcu,2518 zcu,
...@@ -2508,7 +2549,7 @@ fn renderTypePrefix(...@@ -2508,7 +2549,7 @@ fn renderTypePrefix(
2508 );2549 );
2509 switch (parent_fix) {2550 switch (parent_fix) {
2510 .prefix => {2551 .prefix => {
2511 try w.print("{}(", .{child_trailing});2552 try w.print("{f}(", .{child_trailing});
2512 return .no_space;2553 return .no_space;
2513 },2554 },
2514 .suffix => return child_trailing,2555 .suffix => return child_trailing,
...@@ -2560,7 +2601,7 @@ fn renderTypePrefix(...@@ -2560,7 +2601,7 @@ fn renderTypePrefix(
2560 );2601 );
2561 switch (parent_fix) {2602 switch (parent_fix) {
2562 .prefix => {2603 .prefix => {
2563 try w.print("{}(", .{child_trailing});2604 try w.print("{f}(", .{child_trailing});
2564 return .no_space;2605 return .no_space;
2565 },2606 },
2566 .suffix => return child_trailing,2607 .suffix => return child_trailing,
...@@ -2569,7 +2610,7 @@ fn renderTypePrefix(...@@ -2569,7 +2610,7 @@ fn renderTypePrefix(
2569 }2610 }
2570 var qualifier_it = qualifiers.iterator();2611 var qualifier_it = qualifiers.iterator();
2571 while (qualifier_it.next()) |qualifier| {2612 while (qualifier_it.next()) |qualifier| {
2572 try w.print("{}{s}", .{ trailing, @tagName(qualifier) });2613 try w.print("{f}{s}", .{ trailing, @tagName(qualifier) });
2573 trailing = .maybe_space;2614 trailing = .maybe_space;
2574 }2615 }
2575 return trailing;2616 return trailing;
...@@ -2578,11 +2619,11 @@ fn renderTypeSuffix(...@@ -2578,11 +2619,11 @@ fn renderTypeSuffix(
2578 pass: DeclGen.Pass,2619 pass: DeclGen.Pass,
2579 ctype_pool: *const CType.Pool,2620 ctype_pool: *const CType.Pool,
2580 zcu: *Zcu,2621 zcu: *Zcu,
2581 w: anytype,2622 w: *Writer,
2582 ctype: CType,2623 ctype: CType,
2583 parent_fix: CTypeFix,2624 parent_fix: CTypeFix,
2584 qualifiers: CQualifiers,2625 qualifiers: CQualifiers,
2585) @TypeOf(w).Error!void {2626) Writer.Error!void {
2586 switch (ctype.info(ctype_pool)) {2627 switch (ctype.info(ctype_pool)) {
2587 .basic, .aligned, .fwd_decl, .aggregate => {},2628 .basic, .aligned, .fwd_decl, .aggregate => {},
2588 .pointer => |pointer_info| try renderTypeSuffix(2629 .pointer => |pointer_info| try renderTypeSuffix(
...@@ -2617,7 +2658,7 @@ fn renderTypeSuffix(...@@ -2617,7 +2658,7 @@ fn renderTypeSuffix(
2617 need_comma = true;2658 need_comma = true;
2618 const trailing =2659 const trailing =
2619 try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers);2660 try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers);
2620 if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index });2661 if (qualifiers.contains(.@"const")) try w.print("{f}a{d}", .{ trailing, param_index });
2621 try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});2662 try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});
2622 }2663 }
2623 if (function_info.varargs) {2664 if (function_info.varargs) {
...@@ -2634,49 +2675,49 @@ fn renderTypeSuffix(...@@ -2634,49 +2675,49 @@ fn renderTypeSuffix(
2634}2675}
2635fn renderFields(2676fn renderFields(
2636 zcu: *Zcu,2677 zcu: *Zcu,
2637 writer: anytype,2678 w: *Writer,
2638 ctype_pool: *const CType.Pool,2679 ctype_pool: *const CType.Pool,
2639 aggregate_info: CType.Info.Aggregate,2680 aggregate_info: CType.Info.Aggregate,
2640 indent: usize,2681 indent: usize,
2641) !void {2682) !void {
2642 try writer.writeAll("{\n");2683 try w.writeAll("{\n");
2643 for (0..aggregate_info.fields.len) |field_index| {2684 for (0..aggregate_info.fields.len) |field_index| {
2644 const field_info = aggregate_info.fields.at(field_index, ctype_pool);2685 const field_info = aggregate_info.fields.at(field_index, ctype_pool);
2645 try writer.writeByteNTimes(' ', indent + 1);2686 try w.splatByteAll(' ', indent + 1);
2646 switch (field_info.alignas.abiOrder()) {2687 switch (field_info.alignas.abiOrder()) {
2647 .lt => {2688 .lt => {
2648 std.debug.assert(aggregate_info.@"packed");2689 std.debug.assert(aggregate_info.@"packed");
2649 if (field_info.alignas.@"align" != .@"1") try writer.print("zig_under_align({}) ", .{2690 if (field_info.alignas.@"align" != .@"1") try w.print("zig_under_align({}) ", .{
2650 field_info.alignas.toByteUnits(),2691 field_info.alignas.toByteUnits(),
2651 });2692 });
2652 },2693 },
2653 .eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1")2694 .eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1")
2654 try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}),2695 try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}),
2655 .gt => {2696 .gt => {
2656 std.debug.assert(field_info.alignas.@"align" != .@"1");2697 std.debug.assert(field_info.alignas.@"align" != .@"1");
2657 try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()});2698 try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()});
2658 },2699 },
2659 }2700 }
2660 const trailing = try renderTypePrefix(2701 const trailing = try renderTypePrefix(
2661 .flush,2702 .flush,
2662 ctype_pool,2703 ctype_pool,
2663 zcu,2704 zcu,
2664 writer,2705 w,
2665 field_info.ctype,2706 field_info.ctype,
2666 .suffix,2707 .suffix,
2667 .{},2708 .{},
2668 );2709 );
2669 try writer.print("{}{ }", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool) });2710 try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) });
2670 try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{});2711 try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});
2671 try writer.writeAll(";\n");2712 try w.writeAll(";\n");
2672 }2713 }
2673 try writer.writeByteNTimes(' ', indent);2714 try w.splatByteAll(' ', indent);
2674 try writer.writeByte('}');2715 try w.writeByte('}');
2675}2716}
26762717
2677pub fn genTypeDecl(2718pub fn genTypeDecl(
2678 zcu: *Zcu,2719 zcu: *Zcu,
2679 writer: anytype,2720 w: *Writer,
2680 global_ctype_pool: *const CType.Pool,2721 global_ctype_pool: *const CType.Pool,
2681 global_ctype: CType,2722 global_ctype: CType,
2682 pass: DeclGen.Pass,2723 pass: DeclGen.Pass,
...@@ -2689,27 +2730,27 @@ pub fn genTypeDecl(...@@ -2689,27 +2730,27 @@ pub fn genTypeDecl(
2689 .aligned => |aligned_info| {2730 .aligned => |aligned_info| {
2690 if (!found_existing) {2731 if (!found_existing) {
2691 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));2732 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));
2692 try writer.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});2733 try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});
2693 try writer.print("{}", .{try renderTypePrefix(2734 try w.print("{f}", .{try renderTypePrefix(
2694 .flush,2735 .flush,
2695 global_ctype_pool,2736 global_ctype_pool,
2696 zcu,2737 zcu,
2697 writer,2738 w,
2698 aligned_info.ctype,2739 aligned_info.ctype,
2699 .suffix,2740 .suffix,
2700 .{},2741 .{},
2701 )});2742 )});
2702 try renderAlignedTypeName(writer, global_ctype);2743 try renderAlignedTypeName(w, global_ctype);
2703 try renderTypeSuffix(.flush, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{});2744 try renderTypeSuffix(.flush, global_ctype_pool, zcu, w, aligned_info.ctype, .suffix, .{});
2704 try writer.writeAll(";\n");2745 try w.writeAll(";\n");
2705 }2746 }
2706 switch (pass) {2747 switch (pass) {
2707 .nav, .uav => {2748 .nav, .uav => {
2708 try writer.writeAll("typedef ");2749 try w.writeAll("typedef ");
2709 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});2750 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
2710 try writer.writeByte(' ');2751 try w.writeByte(' ');
2711 _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{});2752 _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{});
2712 try writer.writeAll(";\n");2753 try w.writeAll(";\n");
2713 },2754 },
2714 .flush => {},2755 .flush => {},
2715 }2756 }
...@@ -2717,24 +2758,24 @@ pub fn genTypeDecl(...@@ -2717,24 +2758,24 @@ pub fn genTypeDecl(
2717 .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {2758 .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {
2718 .anon => switch (pass) {2759 .anon => switch (pass) {
2719 .nav, .uav => {2760 .nav, .uav => {
2720 try writer.writeAll("typedef ");2761 try w.writeAll("typedef ");
2721 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});2762 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
2722 try writer.writeByte(' ');2763 try w.writeByte(' ');
2723 _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{});2764 _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{});
2724 try writer.writeAll(";\n");2765 try w.writeAll(";\n");
2725 },2766 },
2726 .flush => {},2767 .flush => {},
2727 },2768 },
2728 .index => |index| if (!found_existing) {2769 .index => |index| if (!found_existing) {
2729 const ip = &zcu.intern_pool;2770 const ip = &zcu.intern_pool;
2730 const ty: Type = .fromInterned(index);2771 const ty: Type = .fromInterned(index);
2731 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});2772 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
2732 try writer.writeByte(';');2773 try w.writeByte(';');
2733 const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);2774 const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);
2734 if (!zcu.fileByIndex(file_scope).mod.?.strip) try writer.print(" /* {} */", .{2775 if (!zcu.fileByIndex(file_scope).mod.?.strip) try w.print(" /* {f} */", .{
2735 ty.containerTypeName(ip).fmt(ip),2776 ty.containerTypeName(ip).fmt(ip),
2736 });2777 });
2737 try writer.writeByte('\n');2778 try w.writeByte('\n');
2738 },2779 },
2739 },2780 },
2740 .aggregate => |aggregate_info| switch (aggregate_info.name) {2781 .aggregate => |aggregate_info| switch (aggregate_info.name) {
...@@ -2742,38 +2783,39 @@ pub fn genTypeDecl(...@@ -2742,38 +2783,39 @@ pub fn genTypeDecl(
2742 .fwd_decl => |fwd_decl| if (!found_existing) {2783 .fwd_decl => |fwd_decl| if (!found_existing) {
2743 try renderFwdDeclTypeName(2784 try renderFwdDeclTypeName(
2744 zcu,2785 zcu,
2745 writer,2786 w,
2746 fwd_decl,2787 fwd_decl,
2747 fwd_decl.info(global_ctype_pool).fwd_decl,2788 fwd_decl.info(global_ctype_pool).fwd_decl,
2748 if (aggregate_info.@"packed") "zig_packed(" else "",2789 if (aggregate_info.@"packed") "zig_packed(" else "",
2749 );2790 );
2750 try writer.writeByte(' ');2791 try w.writeByte(' ');
2751 try renderFields(zcu, writer, global_ctype_pool, aggregate_info, 0);2792 try renderFields(zcu, w, global_ctype_pool, aggregate_info, 0);
2752 if (aggregate_info.@"packed") try writer.writeByte(')');2793 if (aggregate_info.@"packed") try w.writeByte(')');
2753 try writer.writeAll(";\n");2794 try w.writeAll(";\n");
2754 },2795 },
2755 },2796 },
2756 }2797 }
2757}2798}
27582799
2759pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void {2800pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
2760 for (zcu.global_assembly.values()) |asm_source| {2801 for (zcu.global_assembly.values()) |asm_source| {
2761 try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)});2802 try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)});
2762 }2803 }
2763}2804}
27642805
2765pub fn genErrDecls(o: *Object) !void {2806pub fn genErrDecls(o: *Object) Error!void {
2766 const pt = o.dg.pt;2807 const pt = o.dg.pt;
2767 const zcu = pt.zcu;2808 const zcu = pt.zcu;
2768 const ip = &zcu.intern_pool;2809 const ip = &zcu.intern_pool;
2769 const writer = o.writer();2810 const w = &o.code.writer;
27702811
2771 var max_name_len: usize = 0;2812 var max_name_len: usize = 0;
2772 // do not generate an invalid empty enum when the global error set is empty2813 // do not generate an invalid empty enum when the global error set is empty
2773 const names = ip.global_error_set.getNamesFromMainThread();2814 const names = ip.global_error_set.getNamesFromMainThread();
2774 if (names.len > 0) {2815 if (names.len > 0) {
2775 try writer.writeAll("enum {\n");2816 try w.writeAll("enum {");
2776 o.indent_writer.pushIndent();2817 o.indent();
2818 try o.newline();
2777 for (names, 1..) |name_nts, value| {2819 for (names, 1..) |name_nts, value| {
2778 const name = name_nts.toSlice(ip);2820 const name = name_nts.toSlice(ip);
2779 max_name_len = @max(name.len, max_name_len);2821 max_name_len = @max(name.len, max_name_len);
...@@ -2781,11 +2823,13 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2781,11 +2823,13 @@ pub fn genErrDecls(o: *Object) !void {
2781 .ty = .anyerror_type,2823 .ty = .anyerror_type,
2782 .name = name_nts,2824 .name = name_nts,
2783 } });2825 } });
2784 try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other);2826 try o.dg.renderValue(w, Value.fromInterned(err_val), .Other);
2785 try writer.print(" = {d}u,\n", .{value});2827 try w.print(" = {d}u,", .{value});
2828 try o.newline();
2786 }2829 }
2787 o.indent_writer.popIndent();2830 try o.outdent();
2788 try writer.writeAll("};\n");2831 try w.writeAll("};");
2832 try o.newline();
2789 }2833 }
2790 const array_identifier = "zig_errorName";2834 const array_identifier = "zig_errorName";
2791 const name_prefix = array_identifier ++ "_";2835 const name_prefix = array_identifier ++ "_";
...@@ -2808,18 +2852,19 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2808,18 +2852,19 @@ pub fn genErrDecls(o: *Object) !void {
2808 .storage = .{ .bytes = name.toString() },2852 .storage = .{ .bytes = name.toString() },
2809 } });2853 } });
28102854
2811 try writer.writeAll("static ");2855 try w.writeAll("static ");
2812 try o.dg.renderTypeAndName(2856 try o.dg.renderTypeAndName(
2813 writer,2857 w,
2814 name_ty,2858 name_ty,
2815 .{ .identifier = identifier },2859 .{ .identifier = identifier },
2816 Const,2860 Const,
2817 .none,2861 .none,
2818 .complete,2862 .complete,
2819 );2863 );
2820 try writer.writeAll(" = ");2864 try w.writeAll(" = ");
2821 try o.dg.renderValue(writer, Value.fromInterned(name_val), .StaticInitializer);2865 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
2822 try writer.writeAll(";\n");2866 try w.writeByte(';');
2867 try o.newline();
2823 }2868 }
28242869
2825 const name_array_ty = try pt.arrayType(.{2870 const name_array_ty = try pt.arrayType(.{
...@@ -2827,33 +2872,34 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2827,33 +2872,34 @@ pub fn genErrDecls(o: *Object) !void {
2827 .child = .slice_const_u8_sentinel_0_type,2872 .child = .slice_const_u8_sentinel_0_type,
2828 });2873 });
28292874
2830 try writer.writeAll("static ");2875 try w.writeAll("static ");
2831 try o.dg.renderTypeAndName(2876 try o.dg.renderTypeAndName(
2832 writer,2877 w,
2833 name_array_ty,2878 name_array_ty,
2834 .{ .identifier = array_identifier },2879 .{ .identifier = array_identifier },
2835 Const,2880 Const,
2836 .none,2881 .none,
2837 .complete,2882 .complete,
2838 );2883 );
2839 try writer.writeAll(" = {");2884 try w.writeAll(" = {");
2840 for (names, 1..) |name_nts, val| {2885 for (names, 1..) |name_nts, val| {
2841 const name = name_nts.toSlice(ip);2886 const name = name_nts.toSlice(ip);
2842 if (val > 1) try writer.writeAll(", ");2887 if (val > 1) try w.writeAll(", ");
2843 try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{2888 try w.print("{{" ++ name_prefix ++ "{f}, {f}}}", .{
2844 fmtIdent(name),2889 fmtIdentUnsolo(name),
2845 try o.dg.fmtIntLiteral(try pt.intValue(.usize, name.len), .StaticInitializer),2890 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer),
2846 });2891 });
2847 }2892 }
2848 try writer.writeAll("};\n");2893 try w.writeAll("};");
2894 try o.newline();
2849}2895}
28502896
2851pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {2897pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) Error!void {
2852 const pt = o.dg.pt;2898 const pt = o.dg.pt;
2853 const zcu = pt.zcu;2899 const zcu = pt.zcu;
2854 const ip = &zcu.intern_pool;2900 const ip = &zcu.intern_pool;
2855 const ctype_pool = &o.dg.ctype_pool;2901 const ctype_pool = &o.dg.ctype_pool;
2856 const w = o.writer();2902 const w = &o.code.writer;
2857 const key = lazy_fn.key_ptr.*;2903 const key = lazy_fn.key_ptr.*;
2858 const val = lazy_fn.value_ptr;2904 const val = lazy_fn.value_ptr;
2859 switch (key) {2905 switch (key) {
...@@ -2863,9 +2909,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2863,9 +2909,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
28632909
2864 try w.writeAll("static ");2910 try w.writeAll("static ");
2865 try o.dg.renderType(w, name_slice_ty);2911 try o.dg.renderType(w, name_slice_ty);
2866 try w.print(" {}(", .{val.fn_name.fmt(lazy_ctype_pool)});2912 try w.print(" {f}(", .{val.fn_name.fmt(lazy_ctype_pool)});
2867 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);2913 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
2868 try w.writeAll(") {\n switch (tag) {\n");2914 try w.writeAll(") {");
2915 o.indent();
2916 try o.newline();
2917 try w.writeAll("switch (tag) {");
2918 o.indent();
2919 try o.newline();
2869 const tag_names = enum_ty.enumFields(zcu);2920 const tag_names = enum_ty.enumFields(zcu);
2870 for (0..tag_names.len) |tag_index| {2921 for (0..tag_names.len) |tag_index| {
2871 const tag_name = tag_names.get(ip)[tag_index];2922 const tag_name = tag_names.get(ip)[tag_index];
...@@ -2882,34 +2933,43 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2882,34 +2933,43 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2882 .storage = .{ .bytes = tag_name.toString() },2933 .storage = .{ .bytes = tag_name.toString() },
2883 } });2934 } });
28842935
2885 try w.print(" case {}: {{\n static ", .{2936 try w.print("case {f}: {{", .{
2886 try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, pt), .Other),2937 try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other),
2887 });2938 });
2939 o.indent();
2940 try o.newline();
2941 try w.writeAll("static ");
2888 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);2942 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
2889 try w.writeAll(" = ");2943 try w.writeAll(" = ");
2890 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);2944 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
2891 try w.writeAll(";\n return (");2945 try w.writeByte(';');
2946 try o.newline();
2947 try w.writeAll("return (");
2892 try o.dg.renderType(w, name_slice_ty);2948 try o.dg.renderType(w, name_slice_ty);
2893 try w.print("){{{}, {}}};\n", .{2949 try w.print("){{{f}, {f}}};", .{
2894 fmtIdent("name"),2950 fmtIdentUnsolo("name"),
2895 try o.dg.fmtIntLiteral(try pt.intValue(.usize, tag_name_len), .Other),2951 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other),
2896 });2952 });
28972953 try o.newline();
2898 try w.writeAll(" }\n");2954 try o.outdent();
2955 try w.writeByte('}');
2956 try o.newline();
2899 }2957 }
2900 try w.writeAll(" }\n while (");2958 try o.outdent();
2901 try o.dg.renderValue(w, Value.true, .Other);2959 try w.writeByte('}');
2902 try w.writeAll(") ");2960 try o.newline();
2903 _ = try airBreakpoint(w);2961 try airUnreach(o);
2904 try w.writeAll("}\n");2962 try o.outdent();
2963 try w.writeByte('}');
2964 try o.newline();
2905 },2965 },
2906 .never_tail, .never_inline => |fn_nav_index| {2966 .never_tail, .never_inline => |fn_nav_index| {
2907 const fn_val = zcu.navValue(fn_nav_index);2967 const fn_val = zcu.navValue(fn_nav_index);
2908 const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete);2968 const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete);
2909 const fn_info = fn_ctype.info(ctype_pool).function;2969 const fn_info = fn_ctype.info(ctype_pool).function;
2910 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);2970 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool, true);
29112971
2912 const fwd = o.dg.fwdDeclWriter();2972 const fwd = &o.dg.fwd_decl.writer;
2913 try fwd.print("static zig_{s} ", .{@tagName(key)});2973 try fwd.print("static zig_{s} ", .{@tagName(key)});
2914 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{2974 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{
2915 .fmt_ctype_pool_string = fn_name,2975 .fmt_ctype_pool_string = fn_name,
...@@ -2920,14 +2980,21 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2920,14 +2980,21 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2920 try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{2980 try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{
2921 .fmt_ctype_pool_string = fn_name,2981 .fmt_ctype_pool_string = fn_name,
2922 });2982 });
2923 try w.writeAll(" {\n return ");2983 try w.writeAll(" {");
2984 o.indent();
2985 try o.newline();
2986 try w.writeAll("return ");
2924 try o.dg.renderNavName(w, fn_nav_index);2987 try o.dg.renderNavName(w, fn_nav_index);
2925 try w.writeByte('(');2988 try w.writeByte('(');
2926 for (0..fn_info.param_ctypes.len) |arg| {2989 for (0..fn_info.param_ctypes.len) |arg| {
2927 if (arg > 0) try w.writeAll(", ");2990 if (arg > 0) try w.writeAll(", ");
2928 try w.print("a{d}", .{arg});2991 try w.print("a{d}", .{arg});
2929 }2992 }
2930 try w.writeAll(");\n}\n");2993 try w.writeAll(");");
2994 try o.newline();
2995 try o.outdent();
2996 try w.writeByte('}');
2997 try o.newline();
2931 },2998 },
2932 }2999 }
2933}3000}
...@@ -2967,12 +3034,14 @@ pub fn generate(...@@ -2967,12 +3034,14 @@ pub fn generate(
2967 .scratch = .empty,3034 .scratch = .empty,
2968 .uavs = .empty,3035 .uavs = .empty,
2969 },3036 },
3037 .code_header = .init(gpa),
2970 .code = .init(gpa),3038 .code = .init(gpa),
2971 .indent_writer = undefined, // set later so we can get a pointer to object.code3039 .indent_counter = 0,
2972 },3040 },
2973 .lazy_fns = .empty,3041 .lazy_fns = .empty,
2974 };3042 };
2975 defer {3043 defer {
3044 function.object.code_header.deinit();
2976 function.object.code.deinit();3045 function.object.code.deinit();
2977 function.object.dg.fwd_decl.deinit();3046 function.object.dg.fwd_decl.deinit();
2978 function.object.dg.ctype_pool.deinit(gpa);3047 function.object.dg.ctype_pool.deinit(gpa);
...@@ -2981,22 +3050,24 @@ pub fn generate(...@@ -2981,22 +3050,24 @@ pub fn generate(
2981 function.deinit();3050 function.deinit();
2982 }3051 }
2983 try function.object.dg.ctype_pool.init(gpa);3052 try function.object.dg.ctype_pool.init(gpa);
2984 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
29853053
2986 genFunc(&function) catch |err| switch (err) {3054 genFunc(&function) catch |err| switch (err) {
2987 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),3055 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),
2988 error.OutOfMemory => |e| return e,3056 error.OutOfMemory => return error.OutOfMemory,
3057 error.WriteFailed => return error.OutOfMemory,
2989 };3058 };
29903059
2991 var mir: Mir = .{3060 var mir: Mir = .{
2992 .uavs = .empty,3061 .uavs = .empty,
2993 .code = &.{},3062 .code = &.{},
3063 .code_header = &.{},
2994 .fwd_decl = &.{},3064 .fwd_decl = &.{},
2995 .ctype_pool = .empty,3065 .ctype_pool = .empty,
2996 .lazy_fns = .empty,3066 .lazy_fns = .empty,
2997 };3067 };
2998 errdefer mir.deinit(gpa);3068 errdefer mir.deinit(gpa);
2999 mir.uavs = function.object.dg.uavs.move();3069 mir.uavs = function.object.dg.uavs.move();
3070 mir.code_header = try function.object.code_header.toOwnedSlice();
3000 mir.code = try function.object.code.toOwnedSlice();3071 mir.code = try function.object.code.toOwnedSlice();
3001 mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();3072 mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();
3002 mir.ctype_pool = function.object.dg.ctype_pool.move();3073 mir.ctype_pool = function.object.dg.ctype_pool.move();
...@@ -3004,7 +3075,7 @@ pub fn generate(...@@ -3004,7 +3075,7 @@ pub fn generate(
3004 return mir;3075 return mir;
3005}3076}
30063077
3007fn genFunc(f: *Function) !void {3078pub fn genFunc(f: *Function) Error!void {
3008 const tracy = trace(@src());3079 const tracy = trace(@src());
3009 defer tracy.end();3080 defer tracy.end();
30103081
...@@ -3016,10 +3087,7 @@ fn genFunc(f: *Function) !void {...@@ -3016,10 +3087,7 @@ fn genFunc(f: *Function) !void {
3016 const nav_val = zcu.navValue(nav_index);3087 const nav_val = zcu.navValue(nav_index);
3017 const nav = ip.getNav(nav_index);3088 const nav = ip.getNav(nav_index);
30183089
3019 o.code_header = std.ArrayList(u8).init(gpa);3090 const fwd = &o.dg.fwd_decl.writer;
3020 defer o.code_header.deinit();
3021
3022 const fwd = o.dg.fwdDeclWriter();
3023 try fwd.writeAll("static ");3091 try fwd.writeAll("static ");
3024 try o.dg.renderFunctionSignature(3092 try o.dg.renderFunctionSignature(
3025 fwd,3093 fwd,
...@@ -3030,29 +3098,26 @@ fn genFunc(f: *Function) !void {...@@ -3030,29 +3098,26 @@ fn genFunc(f: *Function) !void {
3030 );3098 );
3031 try fwd.writeAll(";\n");3099 try fwd.writeAll(";\n");
30323100
3101 const ch = &o.code_header.writer;
3033 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|3102 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|
3034 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});3103 try ch.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});
3035 try o.dg.renderFunctionSignature(3104 try o.dg.renderFunctionSignature(
3036 o.writer(),3105 ch,
3037 nav_val,3106 nav_val,
3038 .none,3107 .none,
3039 .complete,3108 .complete,
3040 .{ .nav = nav_index },3109 .{ .nav = nav_index },
3041 );3110 );
3042 try o.writer().writeByte(' ');3111 try ch.writeAll(" {\n ");
3043
3044 // In case we need to use the header, populate it with a copy of the function
3045 // signature here. We anticipate a brace, newline, and space.
3046 try o.code_header.ensureUnusedCapacity(o.code.items.len + 3);
3047 o.code_header.appendSliceAssumeCapacity(o.code.items);
3048 o.code_header.appendSliceAssumeCapacity("{\n ");
3049 const empty_header_len = o.code_header.items.len;
30503112
3051 f.free_locals_map.clearRetainingCapacity();3113 f.free_locals_map.clearRetainingCapacity();
30523114
3053 const main_body = f.air.getMainBody();3115 const main_body = f.air.getMainBody();
3054 try genBodyResolveState(f, undefined, &.{}, main_body, false);3116 o.indent();
3055 try o.indent_writer.insertNewline();3117 try genBodyResolveState(f, undefined, &.{}, main_body, true);
3118 try o.outdent();
3119 try o.code.writer.writeByte('}');
3120 try o.newline();
3056 if (o.dg.expected_block) |_|3121 if (o.dg.expected_block) |_|
3057 return f.fail("runtime code not allowed in naked function", .{});3122 return f.fail("runtime code not allowed in naked function", .{});
30583123
...@@ -3083,24 +3148,16 @@ fn genFunc(f: *Function) !void {...@@ -3083,24 +3148,16 @@ fn genFunc(f: *Function) !void {
3083 };3148 };
3084 free_locals.sort(SortContext{ .keys = free_locals.keys() });3149 free_locals.sort(SortContext{ .keys = free_locals.keys() });
30853150
3086 const w = o.codeHeaderWriter();
3087 for (free_locals.values()) |list| {3151 for (free_locals.values()) |list| {
3088 for (list.keys()) |local_index| {3152 for (list.keys()) |local_index| {
3089 const local = f.locals.items[local_index];3153 const local = f.locals.items[local_index];
3090 try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);3154 try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);
3091 try w.writeAll(";\n ");3155 try ch.writeAll(";\n ");
3092 }3156 }
3093 }3157 }
3094
3095 // If we have a header to insert, append the body to the header
3096 // and then return the result, freeing the body.
3097 if (o.code_header.items.len > empty_header_len) {
3098 try o.code_header.appendSlice(o.code.items[empty_header_len..]);
3099 mem.swap(std.ArrayList(u8), &o.code, &o.code_header);
3100 }
3101}3158}
31023159
3103pub fn genDecl(o: *Object) !void {3160pub fn genDecl(o: *Object) Error!void {
3104 const tracy = trace(@src());3161 const tracy = trace(@src());
3105 defer tracy.end();3162 defer tracy.end();
31063163
...@@ -3120,7 +3177,7 @@ pub fn genDecl(o: *Object) !void {...@@ -3120,7 +3177,7 @@ pub fn genDecl(o: *Object) !void {
3120 .visibility = @"extern".visibility,3177 .visibility = @"extern".visibility,
3121 });3178 });
31223179
3123 const fwd = o.dg.fwdDeclWriter();3180 const fwd = &o.dg.fwd_decl.writer;
3124 try fwd.writeAll("zig_extern ");3181 try fwd.writeAll("zig_extern ");
3125 try o.dg.renderFunctionSignature(3182 try o.dg.renderFunctionSignature(
3126 fwd,3183 fwd,
...@@ -3141,10 +3198,10 @@ pub fn genDecl(o: *Object) !void {...@@ -3141,10 +3198,10 @@ pub fn genDecl(o: *Object) !void {
3141 .linkage = .internal,3198 .linkage = .internal,
3142 .visibility = .default,3199 .visibility = .default,
3143 });3200 });
3144 const w = o.writer();3201 const w = &o.code.writer;
3145 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");3202 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
3146 if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|3203 if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
3147 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});3204 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
3148 try o.dg.renderTypeAndName(3205 try o.dg.renderTypeAndName(
3149 w,3206 w,
3150 nav_ty,3207 nav_ty,
...@@ -3156,7 +3213,7 @@ pub fn genDecl(o: *Object) !void {...@@ -3156,7 +3213,7 @@ pub fn genDecl(o: *Object) !void {
3156 try w.writeAll(" = ");3213 try w.writeAll(" = ");
3157 try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);3214 try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);
3158 try w.writeByte(';');3215 try w.writeByte(';');
3159 try o.indent_writer.insertNewline();3216 try o.newline();
3160 },3217 },
3161 else => try genDeclValue(3218 else => try genDeclValue(
3162 o,3219 o,
...@@ -3174,28 +3231,29 @@ pub fn genDeclValue(...@@ -3174,28 +3231,29 @@ pub fn genDeclValue(
3174 decl_c_value: CValue,3231 decl_c_value: CValue,
3175 alignment: Alignment,3232 alignment: Alignment,
3176 @"linksection": InternPool.OptionalNullTerminatedString,3233 @"linksection": InternPool.OptionalNullTerminatedString,
3177) !void {3234) Error!void {
3178 const zcu = o.dg.pt.zcu;3235 const zcu = o.dg.pt.zcu;
3179 const ty = val.typeOf(zcu);3236 const ty = val.typeOf(zcu);
31803237
3181 const fwd = o.dg.fwdDeclWriter();3238 const fwd = &o.dg.fwd_decl.writer;
3182 try fwd.writeAll("static ");3239 try fwd.writeAll("static ");
3183 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);3240 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
3184 try fwd.writeAll(";\n");3241 try fwd.writeAll(";\n");
31853242
3186 const w = o.writer();3243 const w = &o.code.writer;
3187 if (@"linksection".toSlice(&zcu.intern_pool)) |s|3244 if (@"linksection".toSlice(&zcu.intern_pool)) |s|
3188 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});3245 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
3189 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);3246 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
3190 try w.writeAll(" = ");3247 try w.writeAll(" = ");
3191 try o.dg.renderValue(w, val, .StaticInitializer);3248 try o.dg.renderValue(w, val, .StaticInitializer);
3192 try w.writeAll(";\n");3249 try w.writeByte(';');
3250 try o.newline();
3193}3251}
31943252
3195pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {3253pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {
3196 const zcu = dg.pt.zcu;3254 const zcu = dg.pt.zcu;
3197 const ip = &zcu.intern_pool;3255 const ip = &zcu.intern_pool;
3198 const fwd = dg.fwdDeclWriter();3256 const fwd = &dg.fwd_decl.writer;
31993257
3200 const main_name = export_indices[0].ptr(zcu).opts.name;3258 const main_name = export_indices[0].ptr(zcu).opts.name;
3201 try fwd.writeAll("#define ");3259 try fwd.writeAll("#define ");
...@@ -3204,7 +3262,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3204,7 +3262,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
3204 .uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)),3262 .uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)),
3205 }3263 }
3206 try fwd.writeByte(' ');3264 try fwd.writeByte(' ');
3207 try fwd.print("{ }", .{fmtIdent(main_name.toSlice(ip))});3265 try fwd.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))});
3208 try fwd.writeByte('\n');3266 try fwd.writeByte('\n');
32093267
3210 const exported_val = exported.getValue(zcu);3268 const exported_val = exported.getValue(zcu);
...@@ -3234,7 +3292,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3234,7 +3292,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
3234 const @"export" = export_index.ptr(zcu);3292 const @"export" = export_index.ptr(zcu);
3235 try fwd.writeAll("zig_extern ");3293 try fwd.writeAll("zig_extern ");
3236 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");3294 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
3237 if (@"export".opts.section.toSlice(ip)) |s| try fwd.print("zig_linksection({s}) ", .{3295 if (@"export".opts.section.toSlice(ip)) |s| try fwd.print("zig_linksection({f}) ", .{
3238 fmtStringLiteral(s, null),3296 fmtStringLiteral(s, null),
3239 });3297 });
3240 const extern_name = @"export".opts.name.toSlice(ip);3298 const extern_name = @"export".opts.name.toSlice(ip);
...@@ -3249,17 +3307,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3249,17 +3307,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
3249 .complete,3307 .complete,
3250 );3308 );
3251 if (is_mangled and is_export) {3309 if (is_mangled and is_export) {
3252 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{3310 try fwd.print(" zig_mangled_export({f}, {f}, {f})", .{
3253 fmtIdent(extern_name),3311 fmtIdentSolo(extern_name),
3254 fmtStringLiteral(extern_name, null),3312 fmtStringLiteral(extern_name, null),
3255 fmtStringLiteral(main_name.toSlice(ip), null),3313 fmtStringLiteral(main_name.toSlice(ip), null),
3256 });3314 });
3257 } else if (is_mangled) {3315 } else if (is_mangled) {
3258 try fwd.print(" zig_mangled({ }, {s})", .{3316 try fwd.print(" zig_mangled({f}, {f})", .{
3259 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),3317 fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null),
3260 });3318 });
3261 } else if (is_export) {3319 } else if (is_export) {
3262 try fwd.print(" zig_export({s}, {s})", .{3320 try fwd.print(" zig_export({f}, {f})", .{
3263 fmtStringLiteral(main_name.toSlice(ip), null),3321 fmtStringLiteral(main_name.toSlice(ip), null),
3264 fmtStringLiteral(extern_name, null),3322 fmtStringLiteral(extern_name, null),
3265 });3323 });
...@@ -3272,16 +3330,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3272,16 +3330,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
3272/// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not3330/// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not
3273/// have been added to `free_locals_map`. For a version of this function that restores this state,3331/// have been added to `free_locals_map`. For a version of this function that restores this state,
3274/// see `genBodyResolveState`.3332/// see `genBodyResolveState`.
3275fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {3333fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void {
3276 const writer = f.object.writer();3334 const w = &f.object.code.writer;
3277 if (body.len == 0) {3335 if (body.len == 0) {
3278 try writer.writeAll("{}");3336 try w.writeAll("{}");
3279 } else {3337 } else {
3280 try writer.writeAll("{\n");3338 try w.writeByte('{');
3281 f.object.indent_writer.pushIndent();3339 f.object.indent();
3340 try f.object.newline();
3282 try genBodyInner(f, body);3341 try genBodyInner(f, body);
3283 f.object.indent_writer.popIndent();3342 try f.object.outdent();
3284 try writer.writeByte('}');3343 try w.writeByte('}');
3285 }3344 }
3286}3345}
32873346
...@@ -3291,10 +3350,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -3291,10 +3350,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
3291/// `leading_deaths` have their deaths processed before the body is generated.3350/// `leading_deaths` have their deaths processed before the body is generated.
3292/// A scope is introduced (using braces) only if `inner` is `false`.3351/// A scope is introduced (using braces) only if `inner` is `false`.
3293/// If `leading_deaths` is empty, `inst` may be `undefined`.3352/// If `leading_deaths` is empty, `inst` may be `undefined`.
3294fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) error{ AnalysisFail, OutOfMemory }!void {3353fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) Error!void {
3295 if (body.len == 0) {3354 if (body.len == 0) {
3296 // Don't go to the expense of cloning everything!3355 // Don't go to the expense of cloning everything!
3297 if (!inner) try f.object.writer().writeAll("{}");3356 if (!inner) try f.object.code.writer.writeAll("{}");
3298 return;3357 return;
3299 }3358 }
33003359
...@@ -3340,7 +3399,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con...@@ -3340,7 +3399,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
3340 }3399 }
3341}3400}
33423401
3343fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {3402fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
3344 const zcu = f.object.dg.pt.zcu;3403 const zcu = f.object.dg.pt.zcu;
3345 const ip = &zcu.intern_pool;3404 const ip = &zcu.intern_pool;
3346 const air_tags = f.air.instructions.items(.tag);3405 const air_tags = f.air.instructions.items(.tag);
...@@ -3358,7 +3417,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3358,7 +3417,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
33583417
3359 .arg => try airArg(f, inst),3418 .arg => try airArg(f, inst),
33603419
3361 .breakpoint => try airBreakpoint(f.object.writer()),3420 .breakpoint => try airBreakpoint(f),
3362 .ret_addr => try airRetAddr(f, inst),3421 .ret_addr => try airRetAddr(f, inst),
3363 .frame_addr => try airFrameAddress(f, inst),3422 .frame_addr => try airFrameAddress(f, inst),
33643423
...@@ -3611,8 +3670,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3611,8 +3670,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3611 .ret => return airRet(f, inst, false),3670 .ret => return airRet(f, inst, false),
3612 .ret_safe => return airRet(f, inst, false), // TODO3671 .ret_safe => return airRet(f, inst, false), // TODO
3613 .ret_load => return airRet(f, inst, true),3672 .ret_load => return airRet(f, inst, true),
3614 .trap => return airTrap(f, f.object.writer()),3673 .trap => return airTrap(f, &f.object.code.writer),
3615 .unreach => return airUnreach(f),3674 .unreach => return airUnreach(&f.object),
36163675
3617 // Instructions which may be `noreturn`.3676 // Instructions which may be `noreturn`.
3618 .block => res: {3677 .block => res: {
...@@ -3655,16 +3714,16 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [...@@ -3655,16 +3714,16 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
3655 const operand = try f.resolveInst(ty_op.operand);3714 const operand = try f.resolveInst(ty_op.operand);
3656 try reap(f, inst, &.{ty_op.operand});3715 try reap(f, inst, &.{ty_op.operand});
36573716
3658 const writer = f.object.writer();3717 const w = &f.object.code.writer;
3659 const local = try f.allocLocal(inst, inst_ty);3718 const local = try f.allocLocal(inst, inst_ty);
3660 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));3719 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3661 try f.writeCValue(writer, local, .Other);3720 try f.writeCValue(w, local, .Other);
3662 try a.assign(f, writer);3721 try a.assign(f, w);
3663 if (is_ptr) {3722 if (is_ptr) {
3664 try writer.writeByte('&');3723 try w.writeByte('&');
3665 try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name });3724 try f.writeCValueDerefMember(w, operand, .{ .identifier = field_name });
3666 } else try f.writeCValueMember(writer, operand, .{ .identifier = field_name });3725 } else try f.writeCValueMember(w, operand, .{ .identifier = field_name });
3667 try a.end(f, writer);3726 try a.end(f, w);
3668 return local;3727 return local;
3669}3728}
36703729
...@@ -3681,16 +3740,16 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3681,16 +3740,16 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3681 const index = try f.resolveInst(bin_op.rhs);3740 const index = try f.resolveInst(bin_op.rhs);
3682 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3741 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
36833742
3684 const writer = f.object.writer();3743 const w = &f.object.code.writer;
3685 const local = try f.allocLocal(inst, inst_ty);3744 const local = try f.allocLocal(inst, inst_ty);
3686 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));3745 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3687 try f.writeCValue(writer, local, .Other);3746 try f.writeCValue(w, local, .Other);
3688 try a.assign(f, writer);3747 try a.assign(f, w);
3689 try f.writeCValue(writer, ptr, .Other);3748 try f.writeCValue(w, ptr, .Other);
3690 try writer.writeByte('[');3749 try w.writeByte('[');
3691 try f.writeCValue(writer, index, .Other);3750 try f.writeCValue(w, index, .Other);
3692 try writer.writeByte(']');3751 try w.writeByte(']');
3693 try a.end(f, writer);3752 try a.end(f, w);
3694 return local;3753 return local;
3695}3754}
36963755
...@@ -3708,25 +3767,25 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3708,25 +3767,25 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3708 const index = try f.resolveInst(bin_op.rhs);3767 const index = try f.resolveInst(bin_op.rhs);
3709 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3768 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37103769
3711 const writer = f.object.writer();3770 const w = &f.object.code.writer;
3712 const local = try f.allocLocal(inst, inst_ty);3771 const local = try f.allocLocal(inst, inst_ty);
3713 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));3772 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3714 try f.writeCValue(writer, local, .Other);3773 try f.writeCValue(w, local, .Other);
3715 try a.assign(f, writer);3774 try a.assign(f, w);
3716 try writer.writeByte('(');3775 try w.writeByte('(');
3717 try f.renderType(writer, inst_ty);3776 try f.renderType(w, inst_ty);
3718 try writer.writeByte(')');3777 try w.writeByte(')');
3719 if (elem_has_bits) try writer.writeByte('&');3778 if (elem_has_bits) try w.writeByte('&');
3720 if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) {3779 if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) {
3721 // It's a pointer to an array, so we need to de-reference.3780 // It's a pointer to an array, so we need to de-reference.
3722 try f.writeCValueDeref(writer, ptr);3781 try f.writeCValueDeref(w, ptr);
3723 } else try f.writeCValue(writer, ptr, .Other);3782 } else try f.writeCValue(w, ptr, .Other);
3724 if (elem_has_bits) {3783 if (elem_has_bits) {
3725 try writer.writeByte('[');3784 try w.writeByte('[');
3726 try f.writeCValue(writer, index, .Other);3785 try f.writeCValue(w, index, .Other);
3727 try writer.writeByte(']');3786 try w.writeByte(']');
3728 }3787 }
3729 try a.end(f, writer);3788 try a.end(f, w);
3730 return local;3789 return local;
3731}3790}
37323791
...@@ -3743,16 +3802,16 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3743,16 +3802,16 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3743 const index = try f.resolveInst(bin_op.rhs);3802 const index = try f.resolveInst(bin_op.rhs);
3744 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3803 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37453804
3746 const writer = f.object.writer();3805 const w = &f.object.code.writer;
3747 const local = try f.allocLocal(inst, inst_ty);3806 const local = try f.allocLocal(inst, inst_ty);
3748 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));3807 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3749 try f.writeCValue(writer, local, .Other);3808 try f.writeCValue(w, local, .Other);
3750 try a.assign(f, writer);3809 try a.assign(f, w);
3751 try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });3810 try f.writeCValueMember(w, slice, .{ .identifier = "ptr" });
3752 try writer.writeByte('[');3811 try w.writeByte('[');
3753 try f.writeCValue(writer, index, .Other);3812 try f.writeCValue(w, index, .Other);
3754 try writer.writeByte(']');3813 try w.writeByte(']');
3755 try a.end(f, writer);3814 try a.end(f, w);
3756 return local;3815 return local;
3757}3816}
37583817
...@@ -3771,19 +3830,19 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3771,19 +3830,19 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3771 const index = try f.resolveInst(bin_op.rhs);3830 const index = try f.resolveInst(bin_op.rhs);
3772 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3831 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37733832
3774 const writer = f.object.writer();3833 const w = &f.object.code.writer;
3775 const local = try f.allocLocal(inst, inst_ty);3834 const local = try f.allocLocal(inst, inst_ty);
3776 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));3835 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3777 try f.writeCValue(writer, local, .Other);3836 try f.writeCValue(w, local, .Other);
3778 try a.assign(f, writer);3837 try a.assign(f, w);
3779 if (elem_has_bits) try writer.writeByte('&');3838 if (elem_has_bits) try w.writeByte('&');
3780 try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });3839 try f.writeCValueMember(w, slice, .{ .identifier = "ptr" });
3781 if (elem_has_bits) {3840 if (elem_has_bits) {
3782 try writer.writeByte('[');3841 try w.writeByte('[');
3783 try f.writeCValue(writer, index, .Other);3842 try f.writeCValue(w, index, .Other);
3784 try writer.writeByte(']');3843 try w.writeByte(']');
3785 }3844 }
3786 try a.end(f, writer);3845 try a.end(f, w);
3787 return local;3846 return local;
3788}3847}
37893848
...@@ -3800,16 +3859,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3800,16 +3859,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3800 const index = try f.resolveInst(bin_op.rhs);3859 const index = try f.resolveInst(bin_op.rhs);
3801 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3860 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38023861
3803 const writer = f.object.writer();3862 const w = &f.object.code.writer;
3804 const local = try f.allocLocal(inst, inst_ty);3863 const local = try f.allocLocal(inst, inst_ty);
3805 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));3864 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3806 try f.writeCValue(writer, local, .Other);3865 try f.writeCValue(w, local, .Other);
3807 try a.assign(f, writer);3866 try a.assign(f, w);
3808 try f.writeCValue(writer, array, .Other);3867 try f.writeCValue(w, array, .Other);
3809 try writer.writeByte('[');3868 try w.writeByte('[');
3810 try f.writeCValue(writer, index, .Other);3869 try f.writeCValue(w, index, .Other);
3811 try writer.writeByte(']');3870 try w.writeByte(']');
3812 try a.end(f, writer);3871 try a.end(f, w);
3813 return local;3872 return local;
3814}3873}
38153874
...@@ -3863,12 +3922,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3863,12 +3922,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
3863 .{ .arg_array = i };3922 .{ .arg_array = i };
38643923
3865 if (f.liveness.isUnused(inst)) {3924 if (f.liveness.isUnused(inst)) {
3866 const writer = f.object.writer();3925 const w = &f.object.code.writer;
3867 try writer.writeByte('(');3926 try w.writeByte('(');
3868 try f.renderType(writer, .void);3927 try f.renderType(w, .void);
3869 try writer.writeByte(')');3928 try w.writeByte(')');
3870 try f.writeCValue(writer, result, .Other);3929 try f.writeCValue(w, result, .Other);
3871 try writer.writeAll(";\n");3930 try w.writeByte(';');
3931 try f.object.newline();
3872 return .none;3932 return .none;
3873 }3933 }
38743934
...@@ -3901,21 +3961,21 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3901,21 +3961,21 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3901 const is_array = lowersToArray(src_ty, pt);3961 const is_array = lowersToArray(src_ty, pt);
3902 const need_memcpy = !is_aligned or is_array;3962 const need_memcpy = !is_aligned or is_array;
39033963
3904 const writer = f.object.writer();3964 const w = &f.object.code.writer;
3905 const local = try f.allocLocal(inst, src_ty);3965 const local = try f.allocLocal(inst, src_ty);
3906 const v = try Vectorize.start(f, inst, writer, ptr_ty);3966 const v = try Vectorize.start(f, inst, w, ptr_ty);
39073967
3908 if (need_memcpy) {3968 if (need_memcpy) {
3909 try writer.writeAll("memcpy(");3969 try w.writeAll("memcpy(");
3910 if (!is_array) try writer.writeByte('&');3970 if (!is_array) try w.writeByte('&');
3911 try f.writeCValue(writer, local, .Other);3971 try f.writeCValue(w, local, .Other);
3912 try v.elem(f, writer);3972 try v.elem(f, w);
3913 try writer.writeAll(", (const char *)");3973 try w.writeAll(", (const char *)");
3914 try f.writeCValue(writer, operand, .Other);3974 try f.writeCValue(w, operand, .Other);
3915 try v.elem(f, writer);3975 try v.elem(f, w);
3916 try writer.writeAll(", sizeof(");3976 try w.writeAll(", sizeof(");
3917 try f.renderType(writer, src_ty);3977 try f.renderType(w, src_ty);
3918 try writer.writeAll("))");3978 try w.writeAll("))");
3919 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {3979 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
3920 const host_bits: u16 = ptr_info.packed_offset.host_size * 8;3980 const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
3921 const host_ty = try pt.intType(.unsigned, host_bits);3981 const host_ty = try pt.intType(.unsigned, host_bits);
...@@ -3925,40 +3985,41 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3925,40 +3985,41 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
39253985
3926 const field_ty = try pt.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu))));3986 const field_ty = try pt.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu))));
39273987
3928 try f.writeCValue(writer, local, .Other);3988 try f.writeCValue(w, local, .Other);
3929 try v.elem(f, writer);3989 try v.elem(f, w);
3930 try writer.writeAll(" = (");3990 try w.writeAll(" = (");
3931 try f.renderType(writer, src_ty);3991 try f.renderType(w, src_ty);
3932 try writer.writeAll(")zig_wrap_");3992 try w.writeAll(")zig_wrap_");
3933 try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty);3993 try f.object.dg.renderTypeForBuiltinFnName(w, field_ty);
3934 try writer.writeAll("((");3994 try w.writeAll("((");
3935 try f.renderType(writer, field_ty);3995 try f.renderType(w, field_ty);
3936 try writer.writeByte(')');3996 try w.writeByte(')');
3937 const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;3997 const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;
3938 if (cant_cast) {3998 if (cant_cast) {
3939 if (field_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});3999 if (field_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
3940 try writer.writeAll("zig_lo_");4000 try w.writeAll("zig_lo_");
3941 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);4001 try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
3942 try writer.writeByte('(');4002 try w.writeByte('(');
3943 }4003 }
3944 try writer.writeAll("zig_shr_");4004 try w.writeAll("zig_shr_");
3945 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);4005 try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
3946 try writer.writeByte('(');4006 try w.writeByte('(');
3947 try f.writeCValueDeref(writer, operand);4007 try f.writeCValueDeref(w, operand);
3948 try v.elem(f, writer);4008 try v.elem(f, w);
3949 try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_val)});4009 try w.print(", {f})", .{try f.fmtIntLiteralDec(bit_offset_val)});
3950 if (cant_cast) try writer.writeByte(')');4010 if (cant_cast) try w.writeByte(')');
3951 try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits);4011 try f.object.dg.renderBuiltinInfo(w, field_ty, .bits);
3952 try writer.writeByte(')');4012 try w.writeByte(')');
3953 } else {4013 } else {
3954 try f.writeCValue(writer, local, .Other);4014 try f.writeCValue(w, local, .Other);
3955 try v.elem(f, writer);4015 try v.elem(f, w);
3956 try writer.writeAll(" = ");4016 try w.writeAll(" = ");
3957 try f.writeCValueDeref(writer, operand);4017 try f.writeCValueDeref(w, operand);
3958 try v.elem(f, writer);4018 try v.elem(f, w);
3959 }4019 }
3960 try writer.writeAll(";\n");4020 try w.writeByte(';');
3961 try v.end(f, inst, writer);4021 try f.object.newline();
4022 try v.end(f, inst, w);
39624023
3963 return local;4024 return local;
3964}4025}
...@@ -3967,7 +4028,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -3967,7 +4028,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
3967 const pt = f.object.dg.pt;4028 const pt = f.object.dg.pt;
3968 const zcu = pt.zcu;4029 const zcu = pt.zcu;
3969 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4030 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3970 const writer = f.object.writer();4031 const w = &f.object.code.writer;
3971 const op_inst = un_op.toIndex();4032 const op_inst = un_op.toIndex();
3972 const op_ty = f.typeOf(un_op);4033 const op_ty = f.typeOf(un_op);
3973 const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;4034 const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;
...@@ -3986,33 +4047,34 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -3986,33 +4047,34 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
3986 .ctype = ret_ctype,4047 .ctype = ret_ctype,
3987 .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)),4048 .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)),
3988 });4049 });
3989 try writer.writeAll("memcpy(");4050 try w.writeAll("memcpy(");
3990 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });4051 try f.writeCValueMember(w, array_local, .{ .identifier = "array" });
3991 try writer.writeAll(", ");4052 try w.writeAll(", ");
3992 if (deref)4053 if (deref)
3993 try f.writeCValueDeref(writer, operand)4054 try f.writeCValueDeref(w, operand)
3994 else4055 else
3995 try f.writeCValue(writer, operand, .FunctionArgument);4056 try f.writeCValue(w, operand, .FunctionArgument);
3996 deref = false;4057 deref = false;
3997 try writer.writeAll(", sizeof(");4058 try w.writeAll(", sizeof(");
3998 try f.renderType(writer, ret_ty);4059 try f.renderType(w, ret_ty);
3999 try writer.writeAll("));\n");4060 try w.writeAll("));");
4061 try f.object.newline();
4000 break :ret_val array_local;4062 break :ret_val array_local;
4001 } else operand;4063 } else operand;
40024064
4003 try writer.writeAll("return ");4065 try w.writeAll("return ");
4004 if (deref)4066 if (deref)
4005 try f.writeCValueDeref(writer, ret_val)4067 try f.writeCValueDeref(w, ret_val)
4006 else4068 else
4007 try f.writeCValue(writer, ret_val, .Other);4069 try f.writeCValue(w, ret_val, .Other);
4008 try writer.writeAll(";\n");4070 try w.writeAll(";\n");
4009 if (is_array) {4071 if (is_array) {
4010 try freeLocal(f, inst, ret_val.new_local, null);4072 try freeLocal(f, inst, ret_val.new_local, null);
4011 }4073 }
4012 } else {4074 } else {
4013 try reap(f, inst, &.{un_op});4075 try reap(f, inst, &.{un_op});
4014 // Not even allowed to return void in a naked function.4076 // Not even allowed to return void in a naked function.
4015 if (!f.object.dg.is_naked_fn) try writer.writeAll("return;\n");4077 if (!f.object.dg.is_naked_fn) try w.writeAll("return;\n");
4016 }4078 }
4017}4079}
40184080
...@@ -4031,16 +4093,16 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4031,16 +4093,16 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
40314093
4032 if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);4094 if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);
40334095
4034 const writer = f.object.writer();4096 const w = &f.object.code.writer;
4035 const local = try f.allocLocal(inst, inst_ty);4097 const local = try f.allocLocal(inst, inst_ty);
4036 const v = try Vectorize.start(f, inst, writer, operand_ty);4098 const v = try Vectorize.start(f, inst, w, operand_ty);
4037 const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));4099 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
4038 try f.writeCValue(writer, local, .Other);4100 try f.writeCValue(w, local, .Other);
4039 try v.elem(f, writer);4101 try v.elem(f, w);
4040 try a.assign(f, writer);4102 try a.assign(f, w);
4041 try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other);4103 try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .Other);
4042 try a.end(f, writer);4104 try a.end(f, w);
4043 try v.end(f, inst, writer);4105 try v.end(f, inst, w);
4044 return local;4106 return local;
4045}4107}
40464108
...@@ -4067,35 +4129,35 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4067,35 +4129,35 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
4067 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);4129 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
4068 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);4130 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);
40694131
4070 const writer = f.object.writer();4132 const w = &f.object.code.writer;
4071 const local = try f.allocLocal(inst, inst_ty);4133 const local = try f.allocLocal(inst, inst_ty);
4072 const v = try Vectorize.start(f, inst, writer, operand_ty);4134 const v = try Vectorize.start(f, inst, w, operand_ty);
4073 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete));4135 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));
4074 try f.writeCValue(writer, local, .Other);4136 try f.writeCValue(w, local, .Other);
4075 try v.elem(f, writer);4137 try v.elem(f, w);
4076 try a.assign(f, writer);4138 try a.assign(f, w);
4077 if (need_cast) {4139 if (need_cast) {
4078 try writer.writeByte('(');4140 try w.writeByte('(');
4079 try f.renderType(writer, inst_scalar_ty);4141 try f.renderType(w, inst_scalar_ty);
4080 try writer.writeByte(')');4142 try w.writeByte(')');
4081 }4143 }
4082 if (need_lo) {4144 if (need_lo) {
4083 try writer.writeAll("zig_lo_");4145 try w.writeAll("zig_lo_");
4084 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);4146 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
4085 try writer.writeByte('(');4147 try w.writeByte('(');
4086 }4148 }
4087 if (!need_mask) {4149 if (!need_mask) {
4088 try f.writeCValue(writer, operand, .Other);4150 try f.writeCValue(w, operand, .Other);
4089 try v.elem(f, writer);4151 try v.elem(f, w);
4090 } else switch (dest_int_info.signedness) {4152 } else switch (dest_int_info.signedness) {
4091 .unsigned => {4153 .unsigned => {
4092 try writer.writeAll("zig_and_");4154 try w.writeAll("zig_and_");
4093 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);4155 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
4094 try writer.writeByte('(');4156 try w.writeByte('(');
4095 try f.writeCValue(writer, operand, .FunctionArgument);4157 try f.writeCValue(w, operand, .FunctionArgument);
4096 try v.elem(f, writer);4158 try v.elem(f, w);
4097 try writer.print(", {x})", .{4159 try w.print(", {f})", .{
4098 try f.fmtIntLiteral(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)),4160 try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)),
4099 });4161 });
4100 },4162 },
4101 .signed => {4163 .signed => {
...@@ -4103,30 +4165,30 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4103,30 +4165,30 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
4103 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});4165 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
4104 const shift_val = try pt.intValue(.u8, c_bits - dest_bits);4166 const shift_val = try pt.intValue(.u8, c_bits - dest_bits);
41054167
4106 try writer.writeAll("zig_shr_");4168 try w.writeAll("zig_shr_");
4107 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);4169 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
4108 if (c_bits == 128) {4170 if (c_bits == 128) {
4109 try writer.print("(zig_bitCast_i{d}(", .{c_bits});4171 try w.print("(zig_bitCast_i{d}(", .{c_bits});
4110 } else {4172 } else {
4111 try writer.print("((int{d}_t)", .{c_bits});4173 try w.print("((int{d}_t)", .{c_bits});
4112 }4174 }
4113 try writer.print("zig_shl_u{d}(", .{c_bits});4175 try w.print("zig_shl_u{d}(", .{c_bits});
4114 if (c_bits == 128) {4176 if (c_bits == 128) {
4115 try writer.print("zig_bitCast_u{d}(", .{c_bits});4177 try w.print("zig_bitCast_u{d}(", .{c_bits});
4116 } else {4178 } else {
4117 try writer.print("(uint{d}_t)", .{c_bits});4179 try w.print("(uint{d}_t)", .{c_bits});
4118 }4180 }
4119 try f.writeCValue(writer, operand, .FunctionArgument);4181 try f.writeCValue(w, operand, .FunctionArgument);
4120 try v.elem(f, writer);4182 try v.elem(f, w);
4121 if (c_bits == 128) try writer.writeByte(')');4183 if (c_bits == 128) try w.writeByte(')');
4122 try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});4184 try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
4123 if (c_bits == 128) try writer.writeByte(')');4185 if (c_bits == 128) try w.writeByte(')');
4124 try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});4186 try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
4125 },4187 },
4126 }4188 }
4127 if (need_lo) try writer.writeByte(')');4189 if (need_lo) try w.writeByte(')');
4128 try a.end(f, writer);4190 try a.end(f, w);
4129 try v.end(f, inst, writer);4191 try v.end(f, inst, w);
4130 return local;4192 return local;
4131}4193}
41324194
...@@ -4145,15 +4207,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4145,15 +4207,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
41454207
4146 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndefDeep(zcu) else false;4208 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndefDeep(zcu) else false;
41474209
4210 const w = &f.object.code.writer;
4148 if (val_is_undef) {4211 if (val_is_undef) {
4149 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4212 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
4150 if (safety and ptr_info.packed_offset.host_size == 0) {4213 if (safety and ptr_info.packed_offset.host_size == 0) {
4151 const writer = f.object.writer();4214 try w.writeAll("memset(");
4152 try writer.writeAll("memset(");4215 try f.writeCValue(w, ptr_val, .FunctionArgument);
4153 try f.writeCValue(writer, ptr_val, .FunctionArgument);4216 try w.writeAll(", 0xaa, sizeof(");
4154 try writer.writeAll(", 0xaa, sizeof(");4217 try f.renderType(w, .fromInterned(ptr_info.child));
4155 try f.renderType(writer, .fromInterned(ptr_info.child));4218 try w.writeAll("));");
4156 try writer.writeAll("));\n");4219 try f.object.newline();
4157 }4220 }
4158 return .none;4221 return .none;
4159 }4222 }
...@@ -4169,7 +4232,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4169,7 +4232,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4169 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4232 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
41704233
4171 const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);4234 const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);
4172 const writer = f.object.writer();
4173 if (need_memcpy) {4235 if (need_memcpy) {
4174 // For this memcpy to safely work we need the rhs to have the same4236 // For this memcpy to safely work we need the rhs to have the same
4175 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).4237 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
...@@ -4180,28 +4242,30 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4180,28 +4242,30 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4180 // TODO this should be done by manually initializing elements of the dest array4242 // TODO this should be done by manually initializing elements of the dest array
4181 const array_src = if (src_val == .constant) blk: {4243 const array_src = if (src_val == .constant) blk: {
4182 const new_local = try f.allocLocal(inst, src_ty);4244 const new_local = try f.allocLocal(inst, src_ty);
4183 try f.writeCValue(writer, new_local, .Other);4245 try f.writeCValue(w, new_local, .Other);
4184 try writer.writeAll(" = ");4246 try w.writeAll(" = ");
4185 try f.writeCValue(writer, src_val, .Other);4247 try f.writeCValue(w, src_val, .Other);
4186 try writer.writeAll(";\n");4248 try w.writeByte(';');
4249 try f.object.newline();
41874250
4188 break :blk new_local;4251 break :blk new_local;
4189 } else src_val;4252 } else src_val;
41904253
4191 const v = try Vectorize.start(f, inst, writer, ptr_ty);4254 const v = try Vectorize.start(f, inst, w, ptr_ty);
4192 try writer.writeAll("memcpy((char *)");4255 try w.writeAll("memcpy((char *)");
4193 try f.writeCValue(writer, ptr_val, .FunctionArgument);4256 try f.writeCValue(w, ptr_val, .FunctionArgument);
4194 try v.elem(f, writer);4257 try v.elem(f, w);
4195 try writer.writeAll(", ");4258 try w.writeAll(", ");
4196 if (!is_array) try writer.writeByte('&');4259 if (!is_array) try w.writeByte('&');
4197 try f.writeCValue(writer, array_src, .FunctionArgument);4260 try f.writeCValue(w, array_src, .FunctionArgument);
4198 try v.elem(f, writer);4261 try v.elem(f, w);
4199 try writer.writeAll(", sizeof(");4262 try w.writeAll(", sizeof(");
4200 try f.renderType(writer, src_ty);4263 try f.renderType(w, src_ty);
4201 try writer.writeAll("))");4264 try w.writeAll("))");
4202 try f.freeCValue(inst, array_src);4265 try f.freeCValue(inst, array_src);
4203 try writer.writeAll(";\n");4266 try w.writeByte(';');
4204 try v.end(f, inst, writer);4267 try f.object.newline();
4268 try v.end(f, inst, w);
4205 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {4269 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
4206 const host_bits = ptr_info.packed_offset.host_size * 8;4270 const host_bits = ptr_info.packed_offset.host_size * 8;
4207 const host_ty = try pt.intType(.unsigned, host_bits);4271 const host_ty = try pt.intType(.unsigned, host_bits);
...@@ -4218,50 +4282,50 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4218,50 +4282,50 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4218 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));4282 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));
4219 defer mask.deinit();4283 defer mask.deinit();
42204284
4221 try mask.setTwosCompIntLimit(.max, .unsigned, @as(usize, @intCast(src_bits)));4285 try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(src_bits));
4222 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);4286 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
4223 try mask.bitNotWrap(&mask, .unsigned, host_bits);4287 try mask.bitNotWrap(&mask, .unsigned, host_bits);
42244288
4225 const mask_val = try pt.intValue_big(host_ty, mask.toConst());4289 const mask_val = try pt.intValue_big(host_ty, mask.toConst());
42264290
4227 const v = try Vectorize.start(f, inst, writer, ptr_ty);4291 const v = try Vectorize.start(f, inst, w, ptr_ty);
4228 const a = try Assignment.start(f, writer, src_scalar_ctype);4292 const a = try Assignment.start(f, w, src_scalar_ctype);
4229 try f.writeCValueDeref(writer, ptr_val);4293 try f.writeCValueDeref(w, ptr_val);
4230 try v.elem(f, writer);4294 try v.elem(f, w);
4231 try a.assign(f, writer);4295 try a.assign(f, w);
4232 try writer.writeAll("zig_or_");4296 try w.writeAll("zig_or_");
4233 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);4297 try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
4234 try writer.writeAll("(zig_and_");4298 try w.writeAll("(zig_and_");
4235 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);4299 try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
4236 try writer.writeByte('(');4300 try w.writeByte('(');
4237 try f.writeCValueDeref(writer, ptr_val);4301 try f.writeCValueDeref(w, ptr_val);
4238 try v.elem(f, writer);4302 try v.elem(f, w);
4239 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(mask_val)});4303 try w.print(", {f}), zig_shl_", .{try f.fmtIntLiteralHex(mask_val)});
4240 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);4304 try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
4241 try writer.writeByte('(');4305 try w.writeByte('(');
4242 const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;4306 const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;
4243 if (cant_cast) {4307 if (cant_cast) {
4244 if (src_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});4308 if (src_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
4245 try writer.writeAll("zig_make_");4309 try w.writeAll("zig_make_");
4246 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);4310 try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
4247 try writer.writeAll("(0, ");4311 try w.writeAll("(0, ");
4248 } else {4312 } else {
4249 try writer.writeByte('(');4313 try w.writeByte('(');
4250 try f.renderType(writer, host_ty);4314 try f.renderType(w, host_ty);
4251 try writer.writeByte(')');4315 try w.writeByte(')');
4252 }4316 }
42534317
4254 if (src_ty.isPtrAtRuntime(zcu)) {4318 if (src_ty.isPtrAtRuntime(zcu)) {
4255 try writer.writeByte('(');4319 try w.writeByte('(');
4256 try f.renderType(writer, .usize);4320 try f.renderType(w, .usize);
4257 try writer.writeByte(')');4321 try w.writeByte(')');
4258 }4322 }
4259 try f.writeCValue(writer, src_val, .Other);4323 try f.writeCValue(w, src_val, .Other);
4260 try v.elem(f, writer);4324 try v.elem(f, w);
4261 if (cant_cast) try writer.writeByte(')');4325 if (cant_cast) try w.writeByte(')');
4262 try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)});4326 try w.print(", {f}))", .{try f.fmtIntLiteralDec(bit_offset_val)});
4263 try a.end(f, writer);4327 try a.end(f, w);
4264 try v.end(f, inst, writer);4328 try v.end(f, inst, w);
4265 } else {4329 } else {
4266 switch (ptr_val) {4330 switch (ptr_val) {
4267 .local_ref => |ptr_local_index| switch (src_val) {4331 .local_ref => |ptr_local_index| switch (src_val) {
...@@ -4271,15 +4335,15 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4271,15 +4335,15 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4271 },4335 },
4272 else => {},4336 else => {},
4273 }4337 }
4274 const v = try Vectorize.start(f, inst, writer, ptr_ty);4338 const v = try Vectorize.start(f, inst, w, ptr_ty);
4275 const a = try Assignment.start(f, writer, src_scalar_ctype);4339 const a = try Assignment.start(f, w, src_scalar_ctype);
4276 try f.writeCValueDeref(writer, ptr_val);4340 try f.writeCValueDeref(w, ptr_val);
4277 try v.elem(f, writer);4341 try v.elem(f, w);
4278 try a.assign(f, writer);4342 try a.assign(f, w);
4279 try f.writeCValue(writer, src_val, .Other);4343 try f.writeCValue(w, src_val, .Other);
4280 try v.elem(f, writer);4344 try v.elem(f, w);
4281 try a.end(f, writer);4345 try a.end(f, w);
4282 try v.end(f, inst, writer);4346 try v.end(f, inst, w);
4283 }4347 }
4284 return .none;4348 return .none;
4285}4349}
...@@ -4298,7 +4362,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -4298,7 +4362,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
4298 const operand_ty = f.typeOf(bin_op.lhs);4362 const operand_ty = f.typeOf(bin_op.lhs);
4299 const scalar_ty = operand_ty.scalarType(zcu);4363 const scalar_ty = operand_ty.scalarType(zcu);
43004364
4301 const w = f.object.writer();4365 const w = &f.object.code.writer;
4302 const local = try f.allocLocal(inst, inst_ty);4366 const local = try f.allocLocal(inst, inst_ty);
4303 const v = try Vectorize.start(f, inst, w, operand_ty);4367 const v = try Vectorize.start(f, inst, w, operand_ty);
4304 try f.writeCValueMember(w, local, .{ .field = 1 });4368 try f.writeCValueMember(w, local, .{ .field = 1 });
...@@ -4317,7 +4381,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -4317,7 +4381,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
4317 try f.writeCValue(w, rhs, .FunctionArgument);4381 try f.writeCValue(w, rhs, .FunctionArgument);
4318 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);4382 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
4319 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);4383 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
4320 try w.writeAll(");\n");4384 try w.writeAll(");");
4385 try f.object.newline();
4321 try v.end(f, inst, w);4386 try v.end(f, inst, w);
43224387
4323 return local;4388 return local;
...@@ -4336,17 +4401,18 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4336,17 +4401,18 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
43364401
4337 const inst_ty = f.typeOfIndex(inst);4402 const inst_ty = f.typeOfIndex(inst);
43384403
4339 const writer = f.object.writer();4404 const w = &f.object.code.writer;
4340 const local = try f.allocLocal(inst, inst_ty);4405 const local = try f.allocLocal(inst, inst_ty);
4341 const v = try Vectorize.start(f, inst, writer, operand_ty);4406 const v = try Vectorize.start(f, inst, w, operand_ty);
4342 try f.writeCValue(writer, local, .Other);4407 try f.writeCValue(w, local, .Other);
4343 try v.elem(f, writer);4408 try v.elem(f, w);
4344 try writer.writeAll(" = ");4409 try w.writeAll(" = ");
4345 try writer.writeByte('!');4410 try w.writeByte('!');
4346 try f.writeCValue(writer, op, .Other);4411 try f.writeCValue(w, op, .Other);
4347 try v.elem(f, writer);4412 try v.elem(f, w);
4348 try writer.writeAll(";\n");4413 try w.writeByte(';');
4349 try v.end(f, inst, writer);4414 try f.object.newline();
4415 try v.end(f, inst, w);
43504416
4351 return local;4417 return local;
4352}4418}
...@@ -4372,21 +4438,22 @@ fn airBinOp(...@@ -4372,21 +4438,22 @@ fn airBinOp(
43724438
4373 const inst_ty = f.typeOfIndex(inst);4439 const inst_ty = f.typeOfIndex(inst);
43744440
4375 const writer = f.object.writer();4441 const w = &f.object.code.writer;
4376 const local = try f.allocLocal(inst, inst_ty);4442 const local = try f.allocLocal(inst, inst_ty);
4377 const v = try Vectorize.start(f, inst, writer, operand_ty);4443 const v = try Vectorize.start(f, inst, w, operand_ty);
4378 try f.writeCValue(writer, local, .Other);4444 try f.writeCValue(w, local, .Other);
4379 try v.elem(f, writer);4445 try v.elem(f, w);
4380 try writer.writeAll(" = ");4446 try w.writeAll(" = ");
4381 try f.writeCValue(writer, lhs, .Other);4447 try f.writeCValue(w, lhs, .Other);
4382 try v.elem(f, writer);4448 try v.elem(f, w);
4383 try writer.writeByte(' ');4449 try w.writeByte(' ');
4384 try writer.writeAll(operator);4450 try w.writeAll(operator);
4385 try writer.writeByte(' ');4451 try w.writeByte(' ');
4386 try f.writeCValue(writer, rhs, .Other);4452 try f.writeCValue(w, rhs, .Other);
4387 try v.elem(f, writer);4453 try v.elem(f, w);
4388 try writer.writeAll(";\n");4454 try w.writeByte(';');
4389 try v.end(f, inst, writer);4455 try f.object.newline();
4456 try v.end(f, inst, w);
43904457
4391 return local;4458 return local;
4392}4459}
...@@ -4422,27 +4489,27 @@ fn airCmpOp(...@@ -4422,27 +4489,27 @@ fn airCmpOp(
44224489
4423 const rhs_ty = f.typeOf(data.rhs);4490 const rhs_ty = f.typeOf(data.rhs);
4424 const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu);4491 const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu);
4425 const writer = f.object.writer();4492 const w = &f.object.code.writer;
4426 const local = try f.allocLocal(inst, inst_ty);4493 const local = try f.allocLocal(inst, inst_ty);
4427 const v = try Vectorize.start(f, inst, writer, lhs_ty);4494 const v = try Vectorize.start(f, inst, w, lhs_ty);
4428 const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));4495 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
4429 try f.writeCValue(writer, local, .Other);4496 try f.writeCValue(w, local, .Other);
4430 try v.elem(f, writer);4497 try v.elem(f, w);
4431 try a.assign(f, writer);4498 try a.assign(f, w);
4432 if (lhs != .undef and lhs.eql(rhs)) try writer.writeAll(switch (operator) {4499 if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) {
4433 .lt, .neq, .gt => "false",4500 .lt, .neq, .gt => "false",
4434 .lte, .eq, .gte => "true",4501 .lte, .eq, .gte => "true",
4435 }) else {4502 }) else {
4436 if (need_cast) try writer.writeAll("(void*)");4503 if (need_cast) try w.writeAll("(void*)");
4437 try f.writeCValue(writer, lhs, .Other);4504 try f.writeCValue(w, lhs, .Other);
4438 try v.elem(f, writer);4505 try v.elem(f, w);
4439 try writer.writeAll(compareOperatorC(operator));4506 try w.writeAll(compareOperatorC(operator));
4440 if (need_cast) try writer.writeAll("(void*)");4507 if (need_cast) try w.writeAll("(void*)");
4441 try f.writeCValue(writer, rhs, .Other);4508 try f.writeCValue(w, rhs, .Other);
4442 try v.elem(f, writer);4509 try v.elem(f, w);
4443 }4510 }
4444 try a.end(f, writer);4511 try a.end(f, w);
4445 try v.end(f, inst, writer);4512 try v.end(f, inst, w);
44464513
4447 return local;4514 return local;
4448}4515}
...@@ -4475,41 +4542,41 @@ fn airEquality(...@@ -4475,41 +4542,41 @@ fn airEquality(
4475 const rhs = try f.resolveInst(bin_op.rhs);4542 const rhs = try f.resolveInst(bin_op.rhs);
4476 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4543 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
44774544
4478 const writer = f.object.writer();4545 const w = &f.object.code.writer;
4479 const local = try f.allocLocal(inst, .bool);4546 const local = try f.allocLocal(inst, .bool);
4480 const a = try Assignment.start(f, writer, .bool);4547 const a = try Assignment.start(f, w, .bool);
4481 try f.writeCValue(writer, local, .Other);4548 try f.writeCValue(w, local, .Other);
4482 try a.assign(f, writer);4549 try a.assign(f, w);
44834550
4484 const operand_ctype = try f.ctypeFromType(operand_ty, .complete);4551 const operand_ctype = try f.ctypeFromType(operand_ty, .complete);
4485 if (lhs != .undef and lhs.eql(rhs)) try writer.writeAll(switch (operator) {4552 if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) {
4486 .lt, .lte, .gte, .gt => unreachable,4553 .lt, .lte, .gte, .gt => unreachable,
4487 .neq => "false",4554 .neq => "false",
4488 .eq => "true",4555 .eq => "true",
4489 }) else switch (operand_ctype.info(ctype_pool)) {4556 }) else switch (operand_ctype.info(ctype_pool)) {
4490 .basic, .pointer => {4557 .basic, .pointer => {
4491 try f.writeCValue(writer, lhs, .Other);4558 try f.writeCValue(w, lhs, .Other);
4492 try writer.writeAll(compareOperatorC(operator));4559 try w.writeAll(compareOperatorC(operator));
4493 try f.writeCValue(writer, rhs, .Other);4560 try f.writeCValue(w, rhs, .Other);
4494 },4561 },
4495 .aligned, .array, .vector, .fwd_decl, .function => unreachable,4562 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
4496 .aggregate => |aggregate| if (aggregate.fields.len == 2 and4563 .aggregate => |aggregate| if (aggregate.fields.len == 2 and
4497 (aggregate.fields.at(0, ctype_pool).name.index == .is_null or4564 (aggregate.fields.at(0, ctype_pool).name.index == .is_null or
4498 aggregate.fields.at(1, ctype_pool).name.index == .is_null))4565 aggregate.fields.at(1, ctype_pool).name.index == .is_null))
4499 {4566 {
4500 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });4567 try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" });
4501 try writer.writeAll(" || ");4568 try w.writeAll(" || ");
4502 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });4569 try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" });
4503 try writer.writeAll(" ? ");4570 try w.writeAll(" ? ");
4504 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });4571 try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" });
4505 try writer.writeAll(compareOperatorC(operator));4572 try w.writeAll(compareOperatorC(operator));
4506 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });4573 try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" });
4507 try writer.writeAll(" : ");4574 try w.writeAll(" : ");
4508 try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" });4575 try f.writeCValueMember(w, lhs, .{ .identifier = "payload" });
4509 try writer.writeAll(compareOperatorC(operator));4576 try w.writeAll(compareOperatorC(operator));
4510 try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" });4577 try f.writeCValueMember(w, rhs, .{ .identifier = "payload" });
4511 } else for (0..aggregate.fields.len) |field_index| {4578 } else for (0..aggregate.fields.len) |field_index| {
4512 if (field_index > 0) try writer.writeAll(switch (operator) {4579 if (field_index > 0) try w.writeAll(switch (operator) {
4513 .lt, .lte, .gte, .gt => unreachable,4580 .lt, .lte, .gte, .gt => unreachable,
4514 .eq => " && ",4581 .eq => " && ",
4515 .neq => " || ",4582 .neq => " || ",
...@@ -4517,12 +4584,12 @@ fn airEquality(...@@ -4517,12 +4584,12 @@ fn airEquality(
4517 const field_name: CValue = .{4584 const field_name: CValue = .{
4518 .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name,4585 .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name,
4519 };4586 };
4520 try f.writeCValueMember(writer, lhs, field_name);4587 try f.writeCValueMember(w, lhs, field_name);
4521 try writer.writeAll(compareOperatorC(operator));4588 try w.writeAll(compareOperatorC(operator));
4522 try f.writeCValueMember(writer, rhs, field_name);4589 try f.writeCValueMember(w, rhs, field_name);
4523 },4590 },
4524 }4591 }
4525 try a.end(f, writer);4592 try a.end(f, w);
45264593
4527 return local;4594 return local;
4528}4595}
...@@ -4533,12 +4600,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4533,12 +4600,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
4533 const operand = try f.resolveInst(un_op);4600 const operand = try f.resolveInst(un_op);
4534 try reap(f, inst, &.{un_op});4601 try reap(f, inst, &.{un_op});
45354602
4536 const writer = f.object.writer();4603 const w = &f.object.code.writer;
4537 const local = try f.allocLocal(inst, .bool);4604 const local = try f.allocLocal(inst, .bool);
4538 try f.writeCValue(writer, local, .Other);4605 try f.writeCValue(w, local, .Other);
4539 try writer.writeAll(" = ");4606 try w.writeAll(" = ");
4540 try f.writeCValue(writer, operand, .Other);4607 try f.writeCValue(w, operand, .Other);
4541 try writer.print(" < sizeof({ }) / sizeof(*{0 });\n", .{fmtIdent("zig_errorName")});4608 try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")});
4609 try f.object.newline();
4542 return local;4610 return local;
4543}4611}
45444612
...@@ -4559,30 +4627,30 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -4559,30 +4627,30 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
4559 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);4627 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
45604628
4561 const local = try f.allocLocal(inst, inst_ty);4629 const local = try f.allocLocal(inst, inst_ty);
4562 const writer = f.object.writer();4630 const w = &f.object.code.writer;
4563 const v = try Vectorize.start(f, inst, writer, inst_ty);4631 const v = try Vectorize.start(f, inst, w, inst_ty);
4564 const a = try Assignment.start(f, writer, inst_scalar_ctype);4632 const a = try Assignment.start(f, w, inst_scalar_ctype);
4565 try f.writeCValue(writer, local, .Other);4633 try f.writeCValue(w, local, .Other);
4566 try v.elem(f, writer);4634 try v.elem(f, w);
4567 try a.assign(f, writer);4635 try a.assign(f, w);
4568 // We must convert to and from integer types to prevent UB if the operation4636 // We must convert to and from integer types to prevent UB if the operation
4569 // results in a NULL pointer, or if LHS is NULL. The operation is only UB4637 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
4570 // if the result is NULL and then dereferenced.4638 // if the result is NULL and then dereferenced.
4571 try writer.writeByte('(');4639 try w.writeByte('(');
4572 try f.renderCType(writer, inst_scalar_ctype);4640 try f.renderCType(w, inst_scalar_ctype);
4573 try writer.writeAll(")(((uintptr_t)");4641 try w.writeAll(")(((uintptr_t)");
4574 try f.writeCValue(writer, lhs, .Other);4642 try f.writeCValue(w, lhs, .Other);
4575 try v.elem(f, writer);4643 try v.elem(f, w);
4576 try writer.writeAll(") ");4644 try w.writeAll(") ");
4577 try writer.writeByte(operator);4645 try w.writeByte(operator);
4578 try writer.writeAll(" (");4646 try w.writeAll(" (");
4579 try f.writeCValue(writer, rhs, .Other);4647 try f.writeCValue(w, rhs, .Other);
4580 try v.elem(f, writer);4648 try v.elem(f, w);
4581 try writer.writeAll("*sizeof(");4649 try w.writeAll("*sizeof(");
4582 try f.renderType(writer, elem_ty);4650 try f.renderType(w, elem_ty);
4583 try writer.writeAll(")))");4651 try w.writeAll(")))");
4584 try a.end(f, writer);4652 try a.end(f, w);
4585 try v.end(f, inst, writer);4653 try v.end(f, inst, w);
4586 return local;4654 return local;
4587}4655}
45884656
...@@ -4601,28 +4669,29 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -4601,28 +4669,29 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
4601 const rhs = try f.resolveInst(bin_op.rhs);4669 const rhs = try f.resolveInst(bin_op.rhs);
4602 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4670 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
46034671
4604 const writer = f.object.writer();4672 const w = &f.object.code.writer;
4605 const local = try f.allocLocal(inst, inst_ty);4673 const local = try f.allocLocal(inst, inst_ty);
4606 const v = try Vectorize.start(f, inst, writer, inst_ty);4674 const v = try Vectorize.start(f, inst, w, inst_ty);
4607 try f.writeCValue(writer, local, .Other);4675 try f.writeCValue(w, local, .Other);
4608 try v.elem(f, writer);4676 try v.elem(f, w);
4609 // (lhs <> rhs) ? lhs : rhs4677 // (lhs <> rhs) ? lhs : rhs
4610 try writer.writeAll(" = (");4678 try w.writeAll(" = (");
4611 try f.writeCValue(writer, lhs, .Other);4679 try f.writeCValue(w, lhs, .Other);
4612 try v.elem(f, writer);4680 try v.elem(f, w);
4613 try writer.writeByte(' ');4681 try w.writeByte(' ');
4614 try writer.writeByte(operator);4682 try w.writeByte(operator);
4615 try writer.writeByte(' ');4683 try w.writeByte(' ');
4616 try f.writeCValue(writer, rhs, .Other);4684 try f.writeCValue(w, rhs, .Other);
4617 try v.elem(f, writer);4685 try v.elem(f, w);
4618 try writer.writeAll(") ? ");4686 try w.writeAll(") ? ");
4619 try f.writeCValue(writer, lhs, .Other);4687 try f.writeCValue(w, lhs, .Other);
4620 try v.elem(f, writer);4688 try v.elem(f, w);
4621 try writer.writeAll(" : ");4689 try w.writeAll(" : ");
4622 try f.writeCValue(writer, rhs, .Other);4690 try f.writeCValue(w, rhs, .Other);
4623 try v.elem(f, writer);4691 try v.elem(f, w);
4624 try writer.writeAll(";\n");4692 try w.writeByte(';');
4625 try v.end(f, inst, writer);4693 try f.object.newline();
4694 try v.end(f, inst, w);
46264695
4627 return local;4696 return local;
4628}4697}
...@@ -4640,21 +4709,21 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4640,21 +4709,21 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
4640 const inst_ty = f.typeOfIndex(inst);4709 const inst_ty = f.typeOfIndex(inst);
4641 const ptr_ty = inst_ty.slicePtrFieldType(zcu);4710 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
46424711
4643 const writer = f.object.writer();4712 const w = &f.object.code.writer;
4644 const local = try f.allocLocal(inst, inst_ty);4713 const local = try f.allocLocal(inst, inst_ty);
4645 {4714 {
4646 const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete));4715 const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));
4647 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });4716 try f.writeCValueMember(w, local, .{ .identifier = "ptr" });
4648 try a.assign(f, writer);4717 try a.assign(f, w);
4649 try f.writeCValue(writer, ptr, .Other);4718 try f.writeCValue(w, ptr, .Other);
4650 try a.end(f, writer);4719 try a.end(f, w);
4651 }4720 }
4652 {4721 {
4653 const a = try Assignment.start(f, writer, .usize);4722 const a = try Assignment.start(f, w, .usize);
4654 try f.writeCValueMember(writer, local, .{ .identifier = "len" });4723 try f.writeCValueMember(w, local, .{ .identifier = "len" });
4655 try a.assign(f, writer);4724 try a.assign(f, w);
4656 try f.writeCValue(writer, len, .Other);4725 try f.writeCValue(w, len, .Other);
4657 try a.end(f, writer);4726 try a.end(f, w);
4658 }4727 }
4659 return local;4728 return local;
4660}4729}
...@@ -4671,7 +4740,7 @@ fn airCall(...@@ -4671,7 +4740,7 @@ fn airCall(
4671 if (f.object.dg.is_naked_fn) return .none;4740 if (f.object.dg.is_naked_fn) return .none;
46724741
4673 const gpa = f.object.dg.gpa;4742 const gpa = f.object.dg.gpa;
4674 const writer = f.object.writer();4743 const w = &f.object.code.writer;
46754744
4676 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4745 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4677 const extra = f.air.extraData(Air.Call, pl_op.payload);4746 const extra = f.air.extraData(Air.Call, pl_op.payload);
...@@ -4692,13 +4761,14 @@ fn airCall(...@@ -4692,13 +4761,14 @@ fn airCall(
4692 .ctype = arg_ctype,4761 .ctype = arg_ctype,
4693 .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)),4762 .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)),
4694 });4763 });
4695 try writer.writeAll("memcpy(");4764 try w.writeAll("memcpy(");
4696 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });4765 try f.writeCValueMember(w, array_local, .{ .identifier = "array" });
4697 try writer.writeAll(", ");4766 try w.writeAll(", ");
4698 try f.writeCValue(writer, resolved_arg.*, .FunctionArgument);4767 try f.writeCValue(w, resolved_arg.*, .FunctionArgument);
4699 try writer.writeAll(", sizeof(");4768 try w.writeAll(", sizeof(");
4700 try f.renderCType(writer, arg_ctype);4769 try f.renderCType(w, arg_ctype);
4701 try writer.writeAll("));\n");4770 try w.writeAll("));");
4771 try f.object.newline();
4702 resolved_arg.* = array_local;4772 resolved_arg.* = array_local;
4703 }4773 }
4704 }4774 }
...@@ -4726,22 +4796,22 @@ fn airCall(...@@ -4726,22 +4796,22 @@ fn airCall(
47264796
4727 const result_local = result: {4797 const result_local = result: {
4728 if (modifier == .always_tail) {4798 if (modifier == .always_tail) {
4729 try writer.writeAll("zig_always_tail return ");4799 try w.writeAll("zig_always_tail return ");
4730 break :result .none;4800 break :result .none;
4731 } else if (ret_ctype.index == .void) {4801 } else if (ret_ctype.index == .void) {
4732 break :result .none;4802 break :result .none;
4733 } else if (f.liveness.isUnused(inst)) {4803 } else if (f.liveness.isUnused(inst)) {
4734 try writer.writeByte('(');4804 try w.writeByte('(');
4735 try f.renderCType(writer, .void);4805 try f.renderCType(w, .void);
4736 try writer.writeByte(')');4806 try w.writeByte(')');
4737 break :result .none;4807 break :result .none;
4738 } else {4808 } else {
4739 const local = try f.allocAlignedLocal(inst, .{4809 const local = try f.allocAlignedLocal(inst, .{
4740 .ctype = ret_ctype,4810 .ctype = ret_ctype,
4741 .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)),4811 .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)),
4742 });4812 });
4743 try f.writeCValue(writer, local, .Other);4813 try f.writeCValue(w, local, .Other);
4744 try writer.writeAll(" = ");4814 try w.writeAll(" = ");
4745 break :result local;4815 break :result local;
4746 }4816 }
4747 };4817 };
...@@ -4761,17 +4831,17 @@ fn airCall(...@@ -4761,17 +4831,17 @@ fn airCall(
4761 else => break :known,4831 else => break :known,
4762 };4832 };
4763 if (need_cast) {4833 if (need_cast) {
4764 try writer.writeAll("((");4834 try w.writeAll("((");
4765 try f.renderType(writer, if (callee_is_ptr) callee_ty else try pt.singleConstPtrType(callee_ty));4835 try f.renderType(w, if (callee_is_ptr) callee_ty else try pt.singleConstPtrType(callee_ty));
4766 try writer.writeByte(')');4836 try w.writeByte(')');
4767 if (!callee_is_ptr) try writer.writeByte('&');4837 if (!callee_is_ptr) try w.writeByte('&');
4768 }4838 }
4769 switch (modifier) {4839 switch (modifier) {
4770 .auto, .always_tail => try f.object.dg.renderNavName(writer, fn_nav),4840 .auto, .always_tail => try f.object.dg.renderNavName(w, fn_nav),
4771 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))),4841 inline .never_tail, .never_inline => |m| try w.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))),
4772 else => unreachable,4842 else => unreachable,
4773 }4843 }
4774 if (need_cast) try writer.writeByte(')');4844 if (need_cast) try w.writeByte(')');
4775 break :callee;4845 break :callee;
4776 }4846 }
4777 switch (modifier) {4847 switch (modifier) {
...@@ -4781,32 +4851,37 @@ fn airCall(...@@ -4781,32 +4851,37 @@ fn airCall(
4781 else => unreachable,4851 else => unreachable,
4782 }4852 }
4783 // Fall back to function pointer call.4853 // Fall back to function pointer call.
4784 try f.writeCValue(writer, callee, .Other);4854 try f.writeCValue(w, callee, .Other);
4785 }4855 }
47864856
4787 try writer.writeByte('(');4857 try w.writeByte('(');
4788 var need_comma = false;4858 var need_comma = false;
4789 for (resolved_args) |resolved_arg| {4859 for (resolved_args) |resolved_arg| {
4790 if (resolved_arg == .none) continue;4860 if (resolved_arg == .none) continue;
4791 if (need_comma) try writer.writeAll(", ");4861 if (need_comma) try w.writeAll(", ");
4792 need_comma = true;4862 need_comma = true;
4793 try f.writeCValue(writer, resolved_arg, .FunctionArgument);4863 try f.writeCValue(w, resolved_arg, .FunctionArgument);
4794 try f.freeCValue(inst, resolved_arg);4864 try f.freeCValue(inst, resolved_arg);
4795 }4865 }
4796 try writer.writeAll(");\n");4866 try w.writeAll(");");
4867 switch (modifier) {
4868 .always_tail => try w.writeByte('\n'),
4869 else => try f.object.newline(),
4870 }
47974871
4798 const result = result: {4872 const result = result: {
4799 if (result_local == .none or !lowersToArray(ret_ty, pt))4873 if (result_local == .none or !lowersToArray(ret_ty, pt))
4800 break :result result_local;4874 break :result result_local;
48014875
4802 const array_local = try f.allocLocal(inst, ret_ty);4876 const array_local = try f.allocLocal(inst, ret_ty);
4803 try writer.writeAll("memcpy(");4877 try w.writeAll("memcpy(");
4804 try f.writeCValue(writer, array_local, .FunctionArgument);4878 try f.writeCValue(w, array_local, .FunctionArgument);
4805 try writer.writeAll(", ");4879 try w.writeAll(", ");
4806 try f.writeCValueMember(writer, result_local, .{ .identifier = "array" });4880 try f.writeCValueMember(w, result_local, .{ .identifier = "array" });
4807 try writer.writeAll(", sizeof(");4881 try w.writeAll(", sizeof(");
4808 try f.renderType(writer, ret_ty);4882 try f.renderType(w, ret_ty);
4809 try writer.writeAll("));\n");4883 try w.writeAll("));");
4884 try f.object.newline();
4810 try freeLocal(f, inst, result_local.new_local, null);4885 try freeLocal(f, inst, result_local.new_local, null);
4811 break :result array_local;4886 break :result array_local;
4812 };4887 };
...@@ -4816,7 +4891,7 @@ fn airCall(...@@ -4816,7 +4891,7 @@ fn airCall(
48164891
4817fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {4892fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4818 const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;4893 const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
4819 const writer = f.object.writer();4894 const w = &f.object.code.writer;
4820 // TODO re-evaluate whether to emit these or not. If we naively emit4895 // TODO re-evaluate whether to emit these or not. If we naively emit
4821 // these directives, the output file will report bogus line numbers because4896 // these directives, the output file will report bogus line numbers because
4822 // every newline after the #line directive adds one to the line.4897 // every newline after the #line directive adds one to the line.
...@@ -4824,13 +4899,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4824,13 +4899,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4824 // If we wanted to go this route, we would need to go all the way and not output4899 // If we wanted to go this route, we would need to go all the way and not output
4825 // newlines until the next dbg_stmt occurs.4900 // newlines until the next dbg_stmt occurs.
4826 // Perhaps an additional compilation option is in order?4901 // Perhaps an additional compilation option is in order?
4827 //try writer.print("#line {d}\n", .{dbg_stmt.line + 1});4902 //try w.print("#line {d}", .{dbg_stmt.line + 1});
4828 try writer.print("/* file:{d}:{d} */\n", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });4903 //try f.object.newline();
4904 try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
4905 try f.object.newline();
4829 return .none;4906 return .none;
4830}4907}
48314908
4832fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {4909fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {
4833 try f.object.writer().writeAll("(void)0;\n");4910 try f.object.code.writer.writeAll("(void)0;");
4911 try f.object.newline();
4834 return .none;4912 return .none;
4835}4913}
48364914
...@@ -4841,8 +4919,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4841,8 +4919,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4841 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4919 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4842 const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);4920 const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
4843 const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);4921 const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);
4844 const writer = f.object.writer();4922 const w = &f.object.code.writer;
4845 try writer.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)});4923 try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
4924 try f.object.newline();
4846 return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));4925 return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));
4847}4926}
48484927
...@@ -4856,8 +4935,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4856,8 +4935,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4856 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);4935 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
48574936
4858 try reap(f, inst, &.{pl_op.operand});4937 try reap(f, inst, &.{pl_op.operand});
4859 const writer = f.object.writer();4938 const w = &f.object.code.writer;
4860 try writer.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) });4939 try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) });
4940 try f.object.newline();
4861 return .none;4941 return .none;
4862}4942}
48634943
...@@ -4874,7 +4954,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -4874,7 +4954,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
48744954
4875 const block_id = f.next_block_index;4955 const block_id = f.next_block_index;
4876 f.next_block_index += 1;4956 f.next_block_index += 1;
4877 const writer = f.object.writer();4957 const w = &f.object.code.writer;
48784958
4879 const inst_ty = f.typeOfIndex(inst);4959 const inst_ty = f.typeOfIndex(inst);
4880 const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst))4960 const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst))
...@@ -4896,8 +4976,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -4896,8 +4976,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
4896 try die(f, inst, death.toRef());4976 try die(f, inst, death.toRef());
4897 }4977 }
48984978
4899 try f.object.indent_writer.insertNewline();
4900
4901 // noreturn blocks have no `br` instructions reaching them, so we don't want a label4979 // noreturn blocks have no `br` instructions reaching them, so we don't want a label
4902 if (f.object.dg.is_naked_fn) {4980 if (f.object.dg.is_naked_fn) {
4903 if (f.object.dg.expected_block) |expected_block| {4981 if (f.object.dg.expected_block) |expected_block| {
...@@ -4907,7 +4985,8 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -4907,7 +4985,8 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
4907 }4985 }
4908 } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {4986 } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {
4909 // label must be followed by an expression, include an empty one.4987 // label must be followed by an expression, include an empty one.
4910 try writer.print("zig_block_{d}:;\n", .{block_id});4988 try w.print("\nzig_block_{d}:;", .{block_id});
4989 try f.object.newline();
4911 }4990 }
49124991
4913 return result;4992 return result;
...@@ -4944,31 +5023,31 @@ fn lowerTry(...@@ -4944,31 +5023,31 @@ fn lowerTry(
4944 const err_union = try f.resolveInst(operand);5023 const err_union = try f.resolveInst(operand);
4945 const inst_ty = f.typeOfIndex(inst);5024 const inst_ty = f.typeOfIndex(inst);
4946 const liveness_condbr = f.liveness.getCondBr(inst);5025 const liveness_condbr = f.liveness.getCondBr(inst);
4947 const writer = f.object.writer();5026 const w = &f.object.code.writer;
4948 const payload_ty = err_union_ty.errorUnionPayload(zcu);5027 const payload_ty = err_union_ty.errorUnionPayload(zcu);
4949 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);5028 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
49505029
4951 if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {5030 if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
4952 try writer.writeAll("if (");5031 try w.writeAll("if (");
4953 if (!payload_has_bits) {5032 if (!payload_has_bits) {
4954 if (is_ptr)5033 if (is_ptr)
4955 try f.writeCValueDeref(writer, err_union)5034 try f.writeCValueDeref(w, err_union)
4956 else5035 else
4957 try f.writeCValue(writer, err_union, .Other);5036 try f.writeCValue(w, err_union, .Other);
4958 } else {5037 } else {
4959 // Reap the operand so that it can be reused inside genBody.5038 // Reap the operand so that it can be reused inside genBody.
4960 // Remember we must avoid calling reap() twice for the same operand5039 // Remember we must avoid calling reap() twice for the same operand
4961 // in this function.5040 // in this function.
4962 try reap(f, inst, &.{operand});5041 try reap(f, inst, &.{operand});
4963 if (is_ptr)5042 if (is_ptr)
4964 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" })5043 try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" })
4965 else5044 else
4966 try f.writeCValueMember(writer, err_union, .{ .identifier = "error" });5045 try f.writeCValueMember(w, err_union, .{ .identifier = "error" });
4967 }5046 }
4968 try writer.writeAll(") ");5047 try w.writeAll(") ");
49695048
4970 try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false);5049 try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false);
4971 try f.object.indent_writer.insertNewline();5050 try f.object.newline();
4972 if (f.object.dg.expected_block) |_|5051 if (f.object.dg.expected_block) |_|
4973 return f.fail("runtime code not allowed in naked function", .{});5052 return f.fail("runtime code not allowed in naked function", .{});
4974 }5053 }
...@@ -4991,14 +5070,14 @@ fn lowerTry(...@@ -4991,14 +5070,14 @@ fn lowerTry(
4991 if (f.liveness.isUnused(inst)) return .none;5070 if (f.liveness.isUnused(inst)) return .none;
49925071
4993 const local = try f.allocLocal(inst, inst_ty);5072 const local = try f.allocLocal(inst, inst_ty);
4994 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));5073 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
4995 try f.writeCValue(writer, local, .Other);5074 try f.writeCValue(w, local, .Other);
4996 try a.assign(f, writer);5075 try a.assign(f, w);
4997 if (is_ptr) {5076 if (is_ptr) {
4998 try writer.writeByte('&');5077 try w.writeByte('&');
4999 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });5078 try f.writeCValueDerefMember(w, err_union, .{ .identifier = "payload" });
5000 } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });5079 } else try f.writeCValueMember(w, err_union, .{ .identifier = "payload" });
5001 try a.end(f, writer);5080 try a.end(f, w);
5002 return local;5081 return local;
5003}5082}
50045083
...@@ -5006,7 +5085,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {...@@ -5006,7 +5085,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
5006 const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br;5085 const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
5007 const block = f.blocks.get(branch.block_inst).?;5086 const block = f.blocks.get(branch.block_inst).?;
5008 const result = block.result;5087 const result = block.result;
5009 const writer = f.object.writer();5088 const w = &f.object.code.writer;
50105089
5011 if (f.object.dg.is_naked_fn) {5090 if (f.object.dg.is_naked_fn) {
5012 if (result != .none) return f.fail("runtime code not allowed in naked function", .{});5091 if (result != .none) return f.fail("runtime code not allowed in naked function", .{});
...@@ -5020,27 +5099,26 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {...@@ -5020,27 +5099,26 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
5020 const operand = try f.resolveInst(branch.operand);5099 const operand = try f.resolveInst(branch.operand);
5021 try reap(f, inst, &.{branch.operand});5100 try reap(f, inst, &.{branch.operand});
50225101
5023 const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete));5102 const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete));
5024 try f.writeCValue(writer, result, .Other);5103 try f.writeCValue(w, result, .Other);
5025 try a.assign(f, writer);5104 try a.assign(f, w);
5026 try f.writeCValue(writer, operand, .Other);5105 try f.writeCValue(w, operand, .Other);
5027 try a.end(f, writer);5106 try a.end(f, w);
5028 }5107 }
50295108
5030 try writer.print("goto zig_block_{d};\n", .{block.block_id});5109 try w.print("goto zig_block_{d};\n", .{block.block_id});
5031}5110}
50325111
5033fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {5112fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {
5034 const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;5113 const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
5035 const writer = f.object.writer();5114 try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
5036 try writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
5037}5115}
50385116
5039fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {5117fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
5040 const pt = f.object.dg.pt;5118 const pt = f.object.dg.pt;
5041 const zcu = pt.zcu;5119 const zcu = pt.zcu;
5042 const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br;5120 const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
5043 const writer = f.object.writer();5121 const w = &f.object.code.writer;
50445122
5045 if (try f.air.value(br.operand, pt)) |cond_val| {5123 if (try f.air.value(br.operand, pt)) |cond_val| {
5046 // Comptime-known dispatch. Iterate the cases to find the correct5124 // Comptime-known dispatch. Iterate the cases to find the correct
...@@ -5062,18 +5140,19 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {...@@ -5062,18 +5140,19 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
5062 }5140 }
5063 }5141 }
5064 } else switch_br.cases_len;5142 } else switch_br.cases_len;
5065 try writer.print("goto zig_switch_{d}_dispatch_{d};\n", .{ @intFromEnum(br.block_inst), target_case_idx });5143 try w.print("goto zig_switch_{d}_dispatch_{d};\n", .{ @intFromEnum(br.block_inst), target_case_idx });
5066 return;5144 return;
5067 }5145 }
50685146
5069 // Runtime-known dispatch. Set the switch condition, and branch back.5147 // Runtime-known dispatch. Set the switch condition, and branch back.
5070 const cond = try f.resolveInst(br.operand);5148 const cond = try f.resolveInst(br.operand);
5071 const cond_local = f.loop_switch_conds.get(br.block_inst).?;5149 const cond_local = f.loop_switch_conds.get(br.block_inst).?;
5072 try f.writeCValue(writer, .{ .local = cond_local }, .Other);5150 try f.writeCValue(w, .{ .local = cond_local }, .Other);
5073 try writer.writeAll(" = ");5151 try w.writeAll(" = ");
5074 try f.writeCValue(writer, cond, .Other);5152 try f.writeCValue(w, cond, .Other);
5075 try writer.writeAll(";\n");5153 try w.writeByte(';');
5076 try writer.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)});5154 try f.object.newline();
5155 try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)});
5077}5156}
50785157
5079fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {5158fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -5093,7 +5172,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5093,7 +5172,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5093 const zcu = pt.zcu;5172 const zcu = pt.zcu;
5094 const target = &f.object.dg.mod.resolved_target.result;5173 const target = &f.object.dg.mod.resolved_target.result;
5095 const ctype_pool = &f.object.dg.ctype_pool;5174 const ctype_pool = &f.object.dg.ctype_pool;
5096 const writer = f.object.writer();5175 const w = &f.object.code.writer;
50975176
5098 if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {5177 if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
5099 const src_info = dest_ty.intInfo(zcu);5178 const src_info = dest_ty.intInfo(zcu);
...@@ -5104,35 +5183,38 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5104,35 +5183,38 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
51045183
5105 if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) {5184 if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) {
5106 const local = try f.allocLocal(null, dest_ty);5185 const local = try f.allocLocal(null, dest_ty);
5107 try f.writeCValue(writer, local, .Other);5186 try f.writeCValue(w, local, .Other);
5108 try writer.writeAll(" = (");5187 try w.writeAll(" = (");
5109 try f.renderType(writer, dest_ty);5188 try f.renderType(w, dest_ty);
5110 try writer.writeByte(')');5189 try w.writeByte(')');
5111 try f.writeCValue(writer, operand, .Other);5190 try f.writeCValue(w, operand, .Other);
5112 try writer.writeAll(";\n");5191 try w.writeByte(';');
5192 try f.object.newline();
5113 return local;5193 return local;
5114 }5194 }
51155195
5116 const operand_lval = if (operand == .constant) blk: {5196 const operand_lval = if (operand == .constant) blk: {
5117 const operand_local = try f.allocLocal(null, operand_ty);5197 const operand_local = try f.allocLocal(null, operand_ty);
5118 try f.writeCValue(writer, operand_local, .Other);5198 try f.writeCValue(w, operand_local, .Other);
5119 try writer.writeAll(" = ");5199 try w.writeAll(" = ");
5120 try f.writeCValue(writer, operand, .Other);5200 try f.writeCValue(w, operand, .Other);
5121 try writer.writeAll(";\n");5201 try w.writeByte(';');
5202 try f.object.newline();
5122 break :blk operand_local;5203 break :blk operand_local;
5123 } else operand;5204 } else operand;
51245205
5125 const local = try f.allocLocal(null, dest_ty);5206 const local = try f.allocLocal(null, dest_ty);
5126 try writer.writeAll("memcpy(&");5207 try w.writeAll("memcpy(&");
5127 try f.writeCValue(writer, local, .Other);5208 try f.writeCValue(w, local, .Other);
5128 try writer.writeAll(", &");5209 try w.writeAll(", &");
5129 try f.writeCValue(writer, operand_lval, .Other);5210 try f.writeCValue(w, operand_lval, .Other);
5130 try writer.writeAll(", sizeof(");5211 try w.writeAll(", sizeof(");
5131 try f.renderType(5212 try f.renderType(
5132 writer,5213 w,
5133 if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,5214 if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
5134 );5215 );
5135 try writer.writeAll("));\n");5216 try w.writeAll("));");
5217 try f.object.newline();
51365218
5137 // Ensure padding bits have the expected value.5219 // Ensure padding bits have the expected value.
5138 if (dest_ty.isAbiInt(zcu)) {5220 if (dest_ty.isAbiInt(zcu)) {
...@@ -5142,11 +5224,11 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5142,11 +5224,11 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5142 var wrap_ctype: ?CType = null;5224 var wrap_ctype: ?CType = null;
5143 var need_bitcasts = false;5225 var need_bitcasts = false;
51445226
5145 try f.writeCValue(writer, local, .Other);5227 try f.writeCValue(w, local, .Other);
5146 switch (dest_ctype.info(ctype_pool)) {5228 switch (dest_ctype.info(ctype_pool)) {
5147 else => {},5229 else => {},
5148 .array => |array_info| {5230 .array => |array_info| {
5149 try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {5231 try w.print("[{d}]", .{switch (target.cpu.arch.endian()) {
5150 .little => array_info.len - 1,5232 .little => array_info.len - 1,
5151 .big => 0,5233 .big => 0,
5152 }});5234 }});
...@@ -5157,92 +5239,98 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5157,92 +5239,98 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5157 bits += 1;5239 bits += 1;
5158 },5240 },
5159 }5241 }
5160 try writer.writeAll(" = ");5242 try w.writeAll(" = ");
5161 if (need_bitcasts) {5243 if (need_bitcasts) {
5162 try writer.writeAll("zig_bitCast_");5244 try w.writeAll("zig_bitCast_");
5163 try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?.toUnsigned());5245 try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?.toUnsigned());
5164 try writer.writeByte('(');5246 try w.writeByte('(');
5165 }5247 }
5166 try writer.writeAll("zig_wrap_");5248 try w.writeAll("zig_wrap_");
5167 const info_ty = try pt.intType(dest_info.signedness, bits);5249 const info_ty = try pt.intType(dest_info.signedness, bits);
5168 if (wrap_ctype) |ctype|5250 if (wrap_ctype) |ctype|
5169 try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype)5251 try f.object.dg.renderCTypeForBuiltinFnName(w, ctype)
5170 else5252 else
5171 try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty);5253 try f.object.dg.renderTypeForBuiltinFnName(w, info_ty);
5172 try writer.writeByte('(');5254 try w.writeByte('(');
5173 if (need_bitcasts) {5255 if (need_bitcasts) {
5174 try writer.writeAll("zig_bitCast_");5256 try w.writeAll("zig_bitCast_");
5175 try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?);5257 try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?);
5176 try writer.writeByte('(');5258 try w.writeByte('(');
5177 }5259 }
5178 try f.writeCValue(writer, local, .Other);5260 try f.writeCValue(w, local, .Other);
5179 switch (dest_ctype.info(ctype_pool)) {5261 switch (dest_ctype.info(ctype_pool)) {
5180 else => {},5262 else => {},
5181 .array => |array_info| try writer.print("[{d}]", .{5263 .array => |array_info| try w.print("[{d}]", .{
5182 switch (target.cpu.arch.endian()) {5264 switch (target.cpu.arch.endian()) {
5183 .little => array_info.len - 1,5265 .little => array_info.len - 1,
5184 .big => 0,5266 .big => 0,
5185 },5267 },
5186 }),5268 }),
5187 }5269 }
5188 if (need_bitcasts) try writer.writeByte(')');5270 if (need_bitcasts) try w.writeByte(')');
5189 try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits);5271 try f.object.dg.renderBuiltinInfo(w, info_ty, .bits);
5190 if (need_bitcasts) try writer.writeByte(')');5272 if (need_bitcasts) try w.writeByte(')');
5191 try writer.writeAll(");\n");5273 try w.writeAll(");");
5274 try f.object.newline();
5192 }5275 }
51935276
5194 try f.freeCValue(null, operand_lval);5277 try f.freeCValue(null, operand_lval);
5195 return local;5278 return local;
5196}5279}
51975280
5198fn airTrap(f: *Function, writer: anytype) !void {5281fn airTrap(f: *Function, w: *Writer) !void {
5199 // Not even allowed to call trap in a naked function.5282 // Not even allowed to call trap in a naked function.
5200 if (f.object.dg.is_naked_fn) return;5283 if (f.object.dg.is_naked_fn) return;
5201 try writer.writeAll("zig_trap();\n");5284 try w.writeAll("zig_trap();\n");
5202}5285}
52035286
5204fn airBreakpoint(writer: anytype) !CValue {5287fn airBreakpoint(f: *Function) !CValue {
5205 try writer.writeAll("zig_breakpoint();\n");5288 const w = &f.object.code.writer;
5289 try w.writeAll("zig_breakpoint();");
5290 try f.object.newline();
5206 return .none;5291 return .none;
5207}5292}
52085293
5209fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {5294fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {
5210 const writer = f.object.writer();5295 const w = &f.object.code.writer;
5211 const local = try f.allocLocal(inst, .usize);5296 const local = try f.allocLocal(inst, .usize);
5212 try f.writeCValue(writer, local, .Other);5297 try f.writeCValue(w, local, .Other);
5213 try writer.writeAll(" = (");5298 try w.writeAll(" = (");
5214 try f.renderType(writer, .usize);5299 try f.renderType(w, .usize);
5215 try writer.writeAll(")zig_return_address();\n");5300 try w.writeAll(")zig_return_address();");
5301 try f.object.newline();
5216 return local;5302 return local;
5217}5303}
52185304
5219fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {5305fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
5220 const writer = f.object.writer();5306 const w = &f.object.code.writer;
5221 const local = try f.allocLocal(inst, .usize);5307 const local = try f.allocLocal(inst, .usize);
5222 try f.writeCValue(writer, local, .Other);5308 try f.writeCValue(w, local, .Other);
5223 try writer.writeAll(" = (");5309 try w.writeAll(" = (");
5224 try f.renderType(writer, .usize);5310 try f.renderType(w, .usize);
5225 try writer.writeAll(")zig_frame_address();\n");5311 try w.writeAll(")zig_frame_address();");
5312 try f.object.newline();
5226 return local;5313 return local;
5227}5314}
52285315
5229fn airUnreach(f: *Function) !void {5316fn airUnreach(o: *Object) !void {
5230 // Not even allowed to call unreachable in a naked function.5317 // Not even allowed to call unreachable in a naked function.
5231 if (f.object.dg.is_naked_fn) return;5318 if (o.dg.is_naked_fn) return;
5232 try f.object.writer().writeAll("zig_unreachable();\n");5319 try o.code.writer.writeAll("zig_unreachable();\n");
5233}5320}
52345321
5235fn airLoop(f: *Function, inst: Air.Inst.Index) !void {5322fn airLoop(f: *Function, inst: Air.Inst.Index) !void {
5236 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5323 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5237 const loop = f.air.extraData(Air.Block, ty_pl.payload);5324 const loop = f.air.extraData(Air.Block, ty_pl.payload);
5238 const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[loop.end..][0..loop.data.body_len]);5325 const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[loop.end..][0..loop.data.body_len]);
5239 const writer = f.object.writer();5326 const w = &f.object.code.writer;
52405327
5241 // `repeat` instructions matching this loop will branch to5328 // `repeat` instructions matching this loop will branch to
5242 // this label. Since we need a label for arbitrary `repeat`5329 // this label. Since we need a label for arbitrary `repeat`
5243 // anyway, there's actually no need to use a "real" looping5330 // anyway, there's actually no need to use a "real" looping
5244 // construct at all!5331 // construct at all!
5245 try writer.print("zig_loop_{d}:\n", .{@intFromEnum(inst)});5332 try w.print("zig_loop_{d}:", .{@intFromEnum(inst)});
5333 try f.object.newline();
5246 try genBodyInner(f, body); // no need to restore state, we're noreturn5334 try genBodyInner(f, body); // no need to restore state, we're noreturn
5247}5335}
52485336
...@@ -5254,14 +5342,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {...@@ -5254,14 +5342,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {
5254 const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);5342 const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);
5255 const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);5343 const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);
5256 const liveness_condbr = f.liveness.getCondBr(inst);5344 const liveness_condbr = f.liveness.getCondBr(inst);
5257 const writer = f.object.writer();5345 const w = &f.object.code.writer;
52585346
5259 try writer.writeAll("if (");5347 try w.writeAll("if (");
5260 try f.writeCValue(writer, cond, .Other);5348 try f.writeCValue(w, cond, .Other);
5261 try writer.writeAll(") ");5349 try w.writeAll(") ");
52625350
5263 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);5351 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);
5264 try writer.writeByte('\n');5352 try f.object.newline();
5265 if (else_body.len > 0) if (f.object.dg.expected_block) |_|5353 if (else_body.len > 0) if (f.object.dg.expected_block) |_|
5266 return f.fail("runtime code not allowed in naked function", .{});5354 return f.fail("runtime code not allowed in naked function", .{});
52675355
...@@ -5287,7 +5375,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5287,7 +5375,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5287 const init_condition = try f.resolveInst(switch_br.operand);5375 const init_condition = try f.resolveInst(switch_br.operand);
5288 try reap(f, inst, &.{switch_br.operand});5376 try reap(f, inst, &.{switch_br.operand});
5289 const condition_ty = f.typeOf(switch_br.operand);5377 const condition_ty = f.typeOf(switch_br.operand);
5290 const writer = f.object.writer();5378 const w = &f.object.code.writer;
52915379
5292 // For dispatches, we will create a local alloc to contain the condition value.5380 // For dispatches, we will create a local alloc to contain the condition value.
5293 // This may not result in optimal codegen for switch loops, but it minimizes the5381 // This may not result in optimal codegen for switch loops, but it minimizes the
...@@ -5295,7 +5383,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5295,7 +5383,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5295 const condition = if (is_dispatch_loop) cond: {5383 const condition = if (is_dispatch_loop) cond: {
5296 const new_local = try f.allocLocal(inst, condition_ty);5384 const new_local = try f.allocLocal(inst, condition_ty);
5297 try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition);5385 try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition);
5298 try writer.print("zig_switch_{d}_loop:\n", .{@intFromEnum(inst)});5386 try w.print("zig_switch_{d}_loop:", .{@intFromEnum(inst)});
5387 try f.object.newline();
5299 try f.loop_switch_conds.put(gpa, inst, new_local.new_local);5388 try f.loop_switch_conds.put(gpa, inst, new_local.new_local);
5300 break :cond new_local;5389 break :cond new_local;
5301 } else init_condition;5390 } else init_condition;
...@@ -5304,7 +5393,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5304,7 +5393,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5304 assert(f.loop_switch_conds.remove(inst));5393 assert(f.loop_switch_conds.remove(inst));
5305 };5394 };
53065395
5307 try writer.writeAll("switch (");5396 try w.writeAll("switch (");
53085397
5309 const lowered_condition_ty: Type = if (condition_ty.toIntern() == .bool_type)5398 const lowered_condition_ty: Type = if (condition_ty.toIntern() == .bool_type)
5310 .u15399 .u1
...@@ -5313,13 +5402,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5313,13 +5402,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5313 else5402 else
5314 condition_ty;5403 condition_ty;
5315 if (condition_ty.toIntern() != lowered_condition_ty.toIntern()) {5404 if (condition_ty.toIntern() != lowered_condition_ty.toIntern()) {
5316 try writer.writeByte('(');5405 try w.writeByte('(');
5317 try f.renderType(writer, lowered_condition_ty);5406 try f.renderType(w, lowered_condition_ty);
5318 try writer.writeByte(')');5407 try w.writeByte(')');
5319 }5408 }
5320 try f.writeCValue(writer, condition, .Other);5409 try f.writeCValue(w, condition, .Other);
5321 try writer.writeAll(") {");5410 try w.writeAll(") {");
5322 f.object.indent_writer.pushIndent();5411 f.object.indent();
53235412
5324 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1);5413 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1);
5325 defer gpa.free(liveness.deaths);5414 defer gpa.free(liveness.deaths);
...@@ -5332,35 +5421,37 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5332,35 +5421,37 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5332 continue;5421 continue;
5333 }5422 }
5334 for (case.items) |item| {5423 for (case.items) |item| {
5335 try f.object.indent_writer.insertNewline();5424 try f.object.newline();
5336 try writer.writeAll("case ");5425 try w.writeAll("case ");
5337 const item_value = try f.air.value(item, pt);5426 const item_value = try f.air.value(item, pt);
5338 // If `item_value` is a pointer with a known integer address, print the address5427 // If `item_value` is a pointer with a known integer address, print the address
5339 // with no cast to avoid a warning.5428 // with no cast to avoid a warning.
5340 write_val: {5429 write_val: {
5341 if (condition_ty.isPtrAtRuntime(zcu)) {5430 if (condition_ty.isPtrAtRuntime(zcu)) {
5342 if (item_value.?.getUnsignedInt(zcu)) |item_int| {5431 if (item_value.?.getUnsignedInt(zcu)) |item_int| {
5343 try writer.print("{}", .{try f.fmtIntLiteral(try pt.intValue(lowered_condition_ty, item_int))});5432 try w.print("{f}", .{try f.fmtIntLiteralDec(try pt.intValue(lowered_condition_ty, item_int))});
5344 break :write_val;5433 break :write_val;
5345 }5434 }
5346 }5435 }
5347 if (condition_ty.isPtrAtRuntime(zcu)) {5436 if (condition_ty.isPtrAtRuntime(zcu)) {
5348 try writer.writeByte('(');5437 try w.writeByte('(');
5349 try f.renderType(writer, .usize);5438 try f.renderType(w, .usize);
5350 try writer.writeByte(')');5439 try w.writeByte(')');
5351 }5440 }
5352 try f.object.dg.renderValue(writer, (try f.air.value(item, pt)).?, .Other);5441 try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other);
5353 }5442 }
5354 try writer.writeByte(':');5443 try w.writeByte(':');
5355 }5444 }
5356 try writer.writeAll(" {\n");5445 try w.writeAll(" {");
5357 f.object.indent_writer.pushIndent();5446 f.object.indent();
5447 try f.object.newline();
5358 if (is_dispatch_loop) {5448 if (is_dispatch_loop) {
5359 try writer.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });5449 try w.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx });
5450 try f.object.newline();
5360 }5451 }
5361 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);5452 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
5362 f.object.indent_writer.popIndent();5453 try f.object.outdent();
5363 try writer.writeByte('}');5454 try w.writeByte('}');
5364 if (f.object.dg.expected_block) |_|5455 if (f.object.dg.expected_block) |_|
5365 return f.fail("runtime code not allowed in naked function", .{});5456 return f.fail("runtime code not allowed in naked function", .{});
53665457
...@@ -5368,9 +5459,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5368,9 +5459,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5368 }5459 }
53695460
5370 const else_body = it.elseBody();5461 const else_body = it.elseBody();
5371 try f.object.indent_writer.insertNewline();5462 try f.object.newline();
53725463
5373 try writer.writeAll("default: ");5464 try w.writeAll("default: ");
5374 if (any_range_cases) {5465 if (any_range_cases) {
5375 // We will iterate the cases again to handle those with ranges, and generate5466 // We will iterate the cases again to handle those with ranges, and generate
5376 // code using conditions rather than switch cases for such cases.5467 // code using conditions rather than switch cases for such cases.
...@@ -5378,40 +5469,41 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5378,40 +5469,41 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5378 while (it.next()) |case| {5469 while (it.next()) |case| {
5379 if (case.ranges.len == 0) continue; // handled above5470 if (case.ranges.len == 0) continue; // handled above
53805471
5381 try writer.writeAll("if (");5472 try w.writeAll("if (");
5382 for (case.items, 0..) |item, item_i| {5473 for (case.items, 0..) |item, item_i| {
5383 if (item_i != 0) try writer.writeAll(" || ");5474 if (item_i != 0) try w.writeAll(" || ");
5384 try f.writeCValue(writer, condition, .Other);5475 try f.writeCValue(w, condition, .Other);
5385 try writer.writeAll(" == ");5476 try w.writeAll(" == ");
5386 try f.object.dg.renderValue(writer, (try f.air.value(item, pt)).?, .Other);5477 try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other);
5387 }5478 }
5388 for (case.ranges, 0..) |range, range_i| {5479 for (case.ranges, 0..) |range, range_i| {
5389 if (case.items.len != 0 or range_i != 0) try writer.writeAll(" || ");5480 if (case.items.len != 0 or range_i != 0) try w.writeAll(" || ");
5390 // "(x >= lower && x <= upper)"5481 // "(x >= lower && x <= upper)"
5391 try writer.writeByte('(');5482 try w.writeByte('(');
5392 try f.writeCValue(writer, condition, .Other);5483 try f.writeCValue(w, condition, .Other);
5393 try writer.writeAll(" >= ");5484 try w.writeAll(" >= ");
5394 try f.object.dg.renderValue(writer, (try f.air.value(range[0], pt)).?, .Other);5485 try f.object.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .Other);
5395 try writer.writeAll(" && ");5486 try w.writeAll(" && ");
5396 try f.writeCValue(writer, condition, .Other);5487 try f.writeCValue(w, condition, .Other);
5397 try writer.writeAll(" <= ");5488 try w.writeAll(" <= ");
5398 try f.object.dg.renderValue(writer, (try f.air.value(range[1], pt)).?, .Other);5489 try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other);
5399 try writer.writeByte(')');5490 try w.writeByte(')');
5400 }5491 }
5401 try writer.writeAll(") {\n");5492 try w.writeAll(") {");
5402 f.object.indent_writer.pushIndent();5493 f.object.indent();
5494 try f.object.newline();
5403 if (is_dispatch_loop) {5495 if (is_dispatch_loop) {
5404 try writer.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });5496 try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
5405 }5497 }
5406 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);5498 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
5407 f.object.indent_writer.popIndent();5499 try f.object.outdent();
5408 try writer.writeByte('}');5500 try w.writeByte('}');
5409 if (f.object.dg.expected_block) |_|5501 if (f.object.dg.expected_block) |_|
5410 return f.fail("runtime code not allowed in naked function", .{});5502 return f.fail("runtime code not allowed in naked function", .{});
5411 }5503 }
5412 }5504 }
5413 if (is_dispatch_loop) {5505 if (is_dispatch_loop) {
5414 try writer.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), switch_br.cases_len });5506 try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), switch_br.cases_len });
5415 }5507 }
5416 if (else_body.len > 0) {5508 if (else_body.len > 0) {
5417 // Note that this must be the last case, so we do not need to use `genBodyResolveState` since5509 // Note that this must be the last case, so we do not need to use `genBodyResolveState` since
...@@ -5422,13 +5514,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5422,13 +5514,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5422 try genBody(f, else_body);5514 try genBody(f, else_body);
5423 if (f.object.dg.expected_block) |_|5515 if (f.object.dg.expected_block) |_|
5424 return f.fail("runtime code not allowed in naked function", .{});5516 return f.fail("runtime code not allowed in naked function", .{});
5425 } else {5517 } else try airUnreach(&f.object);
5426 try writer.writeAll("zig_unreachable();");5518 try f.object.newline();
5427 }5519 try f.object.outdent();
5428 try f.object.indent_writer.insertNewline();5520 try w.writeAll("}\n");
5429
5430 f.object.indent_writer.popIndent();
5431 try writer.writeAll("}\n");
5432}5521}
54335522
5434fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {5523fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
...@@ -5466,7 +5555,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5466,7 +5555,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5466 extra_i += inputs.len;5555 extra_i += inputs.len;
54675556
5468 const result = result: {5557 const result = result: {
5469 const writer = f.object.writer();5558 const w = &f.object.code.writer;
5470 const inst_ty = f.typeOfIndex(inst);5559 const inst_ty = f.typeOfIndex(inst);
5471 const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {5560 const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
5472 const inst_local = try f.allocLocalValue(.{5561 const inst_local = try f.allocLocalValue(.{
...@@ -5474,10 +5563,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5474,10 +5563,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5474 .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)),5563 .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)),
5475 });5564 });
5476 if (f.wantSafety()) {5565 if (f.wantSafety()) {
5477 try f.writeCValue(writer, inst_local, .Other);5566 try f.writeCValue(w, inst_local, .Other);
5478 try writer.writeAll(" = ");5567 try w.writeAll(" = ");
5479 try f.writeCValue(writer, .{ .undef = inst_ty }, .Other);5568 try f.writeCValue(w, .{ .undef = inst_ty }, .Other);
5480 try writer.writeAll(";\n");5569 try w.writeByte(';');
5570 try f.object.newline();
5481 }5571 }
5482 break :local inst_local;5572 break :local inst_local;
5483 } else .none;5573 } else .none;
...@@ -5501,21 +5591,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5501,21 +5591,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5501 const is_reg = constraint[1] == '{';5591 const is_reg = constraint[1] == '{';
5502 if (is_reg) {5592 if (is_reg) {
5503 const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu);5593 const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu);
5504 try writer.writeAll("register ");5594 try w.writeAll("register ");
5505 const output_local = try f.allocLocalValue(.{5595 const output_local = try f.allocLocalValue(.{
5506 .ctype = try f.ctypeFromType(output_ty, .complete),5596 .ctype = try f.ctypeFromType(output_ty, .complete),
5507 .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)),5597 .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)),
5508 });5598 });
5509 try f.allocs.put(gpa, output_local.new_local, false);5599 try f.allocs.put(gpa, output_local.new_local, false);
5510 try f.object.dg.renderTypeAndName(writer, output_ty, output_local, .{}, .none, .complete);5600 try f.object.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none, .complete);
5511 try writer.writeAll(" __asm(\"");5601 try w.writeAll(" __asm(\"");
5512 try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);5602 try w.writeAll(constraint["={".len .. constraint.len - "}".len]);
5513 try writer.writeAll("\")");5603 try w.writeAll("\")");
5514 if (f.wantSafety()) {5604 if (f.wantSafety()) {
5515 try writer.writeAll(" = ");5605 try w.writeAll(" = ");
5516 try f.writeCValue(writer, .{ .undef = output_ty }, .Other);5606 try f.writeCValue(w, .{ .undef = output_ty }, .Other);
5517 }5607 }
5518 try writer.writeAll(";\n");5608 try w.writeByte(';');
5609 try f.object.newline();
5519 }5610 }
5520 }5611 }
5521 for (inputs) |input| {5612 for (inputs) |input| {
...@@ -5536,21 +5627,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5536,21 +5627,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5536 const input_val = try f.resolveInst(input);5627 const input_val = try f.resolveInst(input);
5537 if (asmInputNeedsLocal(f, constraint, input_val)) {5628 if (asmInputNeedsLocal(f, constraint, input_val)) {
5538 const input_ty = f.typeOf(input);5629 const input_ty = f.typeOf(input);
5539 if (is_reg) try writer.writeAll("register ");5630 if (is_reg) try w.writeAll("register ");
5540 const input_local = try f.allocLocalValue(.{5631 const input_local = try f.allocLocalValue(.{
5541 .ctype = try f.ctypeFromType(input_ty, .complete),5632 .ctype = try f.ctypeFromType(input_ty, .complete),
5542 .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)),5633 .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)),
5543 });5634 });
5544 try f.allocs.put(gpa, input_local.new_local, false);5635 try f.allocs.put(gpa, input_local.new_local, false);
5545 try f.object.dg.renderTypeAndName(writer, input_ty, input_local, Const, .none, .complete);5636 try f.object.dg.renderTypeAndName(w, input_ty, input_local, Const, .none, .complete);
5546 if (is_reg) {5637 if (is_reg) {
5547 try writer.writeAll(" __asm(\"");5638 try w.writeAll(" __asm(\"");
5548 try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);5639 try w.writeAll(constraint["{".len .. constraint.len - "}".len]);
5549 try writer.writeAll("\")");5640 try w.writeAll("\")");
5550 }5641 }
5551 try writer.writeAll(" = ");5642 try w.writeAll(" = ");
5552 try f.writeCValue(writer, input_val, .Other);5643 try f.writeCValue(w, input_val, .Other);
5553 try writer.writeAll(";\n");5644 try w.writeByte(';');
5645 try f.object.newline();
5554 }5646 }
5555 }5647 }
5556 for (0..clobbers_len) |_| {5648 for (0..clobbers_len) |_| {
...@@ -5610,14 +5702,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5610,14 +5702,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5610 }5702 }
5611 }5703 }
56125704
5613 try writer.writeAll("__asm");5705 try w.writeAll("__asm");
5614 if (is_volatile) try writer.writeAll(" volatile");5706 if (is_volatile) try w.writeAll(" volatile");
5615 try writer.print("({s}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)});5707 try w.print("({f}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)});
5616 }5708 }
56175709
5618 extra_i = constraints_extra_begin;5710 extra_i = constraints_extra_begin;
5619 var locals_index = locals_begin;5711 var locals_index = locals_begin;
5620 try writer.writeByte(':');5712 try w.writeByte(':');
5621 for (outputs, 0..) |output, index| {5713 for (outputs, 0..) |output, index| {
5622 const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);5714 const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
5623 const constraint = mem.sliceTo(extra_bytes, 0);5715 const constraint = mem.sliceTo(extra_bytes, 0);
...@@ -5626,22 +5718,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5626,22 +5718,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5626 // for the string, we still use the next u32 for the null terminator.5718 // for the string, we still use the next u32 for the null terminator.
5627 extra_i += (constraint.len + name.len + (2 + 3)) / 4;5719 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
56285720
5629 if (index > 0) try writer.writeByte(',');5721 if (index > 0) try w.writeByte(',');
5630 try writer.writeByte(' ');5722 try w.writeByte(' ');
5631 if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});5723 if (!mem.eql(u8, name, "_")) try w.print("[{s}]", .{name});
5632 const is_reg = constraint[1] == '{';5724 const is_reg = constraint[1] == '{';
5633 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)});5725 try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)});
5634 if (is_reg) {5726 if (is_reg) {
5635 try f.writeCValue(writer, .{ .local = locals_index }, .Other);5727 try f.writeCValue(w, .{ .local = locals_index }, .Other);
5636 locals_index += 1;5728 locals_index += 1;
5637 } else if (output == .none) {5729 } else if (output == .none) {
5638 try f.writeCValue(writer, inst_local, .FunctionArgument);5730 try f.writeCValue(w, inst_local, .FunctionArgument);
5639 } else {5731 } else {
5640 try f.writeCValueDeref(writer, try f.resolveInst(output));5732 try f.writeCValueDeref(w, try f.resolveInst(output));
5641 }5733 }
5642 try writer.writeByte(')');5734 try w.writeByte(')');
5643 }5735 }
5644 try writer.writeByte(':');5736 try w.writeByte(':');
5645 for (inputs, 0..) |input, index| {5737 for (inputs, 0..) |input, index| {
5646 const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);5738 const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
5647 const constraint = mem.sliceTo(extra_bytes, 0);5739 const constraint = mem.sliceTo(extra_bytes, 0);
...@@ -5650,21 +5742,21 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5650,21 +5742,21 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5650 // for the string, we still use the next u32 for the null terminator.5742 // for the string, we still use the next u32 for the null terminator.
5651 extra_i += (constraint.len + name.len + (2 + 3)) / 4;5743 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
56525744
5653 if (index > 0) try writer.writeByte(',');5745 if (index > 0) try w.writeByte(',');
5654 try writer.writeByte(' ');5746 try w.writeByte(' ');
5655 if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});5747 if (!mem.eql(u8, name, "_")) try w.print("[{s}]", .{name});
56565748
5657 const is_reg = constraint[0] == '{';5749 const is_reg = constraint[0] == '{';
5658 const input_val = try f.resolveInst(input);5750 const input_val = try f.resolveInst(input);
5659 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});5751 try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});
5660 try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: {5752 try f.writeCValue(w, if (asmInputNeedsLocal(f, constraint, input_val)) local: {
5661 const input_local_idx = locals_index;5753 const input_local_idx = locals_index;
5662 locals_index += 1;5754 locals_index += 1;
5663 break :local .{ .local = input_local_idx };5755 break :local .{ .local = input_local_idx };
5664 } else input_val, .Other);5756 } else input_val, .Other);
5665 try writer.writeByte(')');5757 try w.writeByte(')');
5666 }5758 }
5667 try writer.writeByte(':');5759 try w.writeByte(':');
5668 for (0..clobbers_len) |clobber_i| {5760 for (0..clobbers_len) |clobber_i| {
5669 const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0);5761 const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0);
5670 // This equation accounts for the fact that even if we have exactly 4 bytes5762 // This equation accounts for the fact that even if we have exactly 4 bytes
...@@ -5673,10 +5765,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5673,10 +5765,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
56735765
5674 if (clobber.len == 0) continue;5766 if (clobber.len == 0) continue;
56755767
5676 if (clobber_i > 0) try writer.writeByte(',');5768 if (clobber_i > 0) try w.writeByte(',');
5677 try writer.print(" {s}", .{fmtStringLiteral(clobber, null)});5769 try w.print(" {f}", .{fmtStringLiteral(clobber, null)});
5678 }5770 }
5679 try writer.writeAll(");\n");5771 try w.writeAll(");");
5772 try f.object.newline();
56805773
5681 extra_i = constraints_extra_begin;5774 extra_i = constraints_extra_begin;
5682 locals_index = locals_begin;5775 locals_index = locals_begin;
...@@ -5690,14 +5783,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5690,14 +5783,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
56905783
5691 const is_reg = constraint[1] == '{';5784 const is_reg = constraint[1] == '{';
5692 if (is_reg) {5785 if (is_reg) {
5693 try f.writeCValueDeref(writer, if (output == .none)5786 try f.writeCValueDeref(w, if (output == .none)
5694 .{ .local_ref = inst_local.new_local }5787 .{ .local_ref = inst_local.new_local }
5695 else5788 else
5696 try f.resolveInst(output));5789 try f.resolveInst(output));
5697 try writer.writeAll(" = ");5790 try w.writeAll(" = ");
5698 try f.writeCValue(writer, .{ .local = locals_index }, .Other);5791 try f.writeCValue(w, .{ .local = locals_index }, .Other);
5699 locals_index += 1;5792 locals_index += 1;
5700 try writer.writeAll(";\n");5793 try w.writeByte(';');
5794 try f.object.newline();
5701 }5795 }
5702 }5796 }
57035797
...@@ -5727,14 +5821,14 @@ fn airIsNull(...@@ -5727,14 +5821,14 @@ fn airIsNull(
5727 const ctype_pool = &f.object.dg.ctype_pool;5821 const ctype_pool = &f.object.dg.ctype_pool;
5728 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5822 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
57295823
5730 const writer = f.object.writer();5824 const w = &f.object.code.writer;
5731 const operand = try f.resolveInst(un_op);5825 const operand = try f.resolveInst(un_op);
5732 try reap(f, inst, &.{un_op});5826 try reap(f, inst, &.{un_op});
57335827
5734 const local = try f.allocLocal(inst, .bool);5828 const local = try f.allocLocal(inst, .bool);
5735 const a = try Assignment.start(f, writer, .bool);5829 const a = try Assignment.start(f, w, .bool);
5736 try f.writeCValue(writer, local, .Other);5830 try f.writeCValue(w, local, .Other);
5737 try a.assign(f, writer);5831 try a.assign(f, w);
57385832
5739 const operand_ty = f.typeOf(un_op);5833 const operand_ty = f.typeOf(un_op);
5740 const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;5834 const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
...@@ -5742,9 +5836,9 @@ fn airIsNull(...@@ -5742,9 +5836,9 @@ fn airIsNull(
5742 const rhs = switch (opt_ctype.info(ctype_pool)) {5836 const rhs = switch (opt_ctype.info(ctype_pool)) {
5743 .basic, .pointer => rhs: {5837 .basic, .pointer => rhs: {
5744 if (is_ptr)5838 if (is_ptr)
5745 try f.writeCValueDeref(writer, operand)5839 try f.writeCValueDeref(w, operand)
5746 else5840 else
5747 try f.writeCValue(writer, operand, .Other);5841 try f.writeCValue(w, operand, .Other);
5748 break :rhs if (opt_ctype.isBool())5842 break :rhs if (opt_ctype.isBool())
5749 "true"5843 "true"
5750 else if (opt_ctype.isInteger())5844 else if (opt_ctype.isInteger())
...@@ -5756,24 +5850,24 @@ fn airIsNull(...@@ -5756,24 +5850,24 @@ fn airIsNull(
5756 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {5850 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
5757 .is_null, .payload => rhs: {5851 .is_null, .payload => rhs: {
5758 if (is_ptr)5852 if (is_ptr)
5759 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" })5853 try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" })
5760 else5854 else
5761 try f.writeCValueMember(writer, operand, .{ .identifier = "is_null" });5855 try f.writeCValueMember(w, operand, .{ .identifier = "is_null" });
5762 break :rhs "true";5856 break :rhs "true";
5763 },5857 },
5764 .ptr, .len => rhs: {5858 .ptr, .len => rhs: {
5765 if (is_ptr)5859 if (is_ptr)
5766 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "ptr" })5860 try f.writeCValueDerefMember(w, operand, .{ .identifier = "ptr" })
5767 else5861 else
5768 try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" });5862 try f.writeCValueMember(w, operand, .{ .identifier = "ptr" });
5769 break :rhs "NULL";5863 break :rhs "NULL";
5770 },5864 },
5771 else => unreachable,5865 else => unreachable,
5772 },5866 },
5773 };5867 };
5774 try writer.writeAll(compareOperatorC(operator));5868 try w.writeAll(compareOperatorC(operator));
5775 try writer.writeAll(rhs);5869 try w.writeAll(rhs);
5776 try a.end(f, writer);5870 try a.end(f, w);
5777 return local;5871 return local;
5778}5872}
57795873
...@@ -5795,16 +5889,16 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue...@@ -5795,16 +5889,16 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue
5795 .aligned, .array, .vector, .fwd_decl, .function => unreachable,5889 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5796 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {5890 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
5797 .is_null, .payload => {5891 .is_null, .payload => {
5798 const writer = f.object.writer();5892 const w = &f.object.code.writer;
5799 const local = try f.allocLocal(inst, inst_ty);5893 const local = try f.allocLocal(inst, inst_ty);
5800 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));5894 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
5801 try f.writeCValue(writer, local, .Other);5895 try f.writeCValue(w, local, .Other);
5802 try a.assign(f, writer);5896 try a.assign(f, w);
5803 if (is_ptr) {5897 if (is_ptr) {
5804 try writer.writeByte('&');5898 try w.writeByte('&');
5805 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });5899 try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
5806 } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });5900 } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" });
5807 try a.end(f, writer);5901 try a.end(f, w);
5808 return local;5902 return local;
5809 },5903 },
5810 .ptr, .len => return f.moveCValue(inst, inst_ty, operand),5904 .ptr, .len => return f.moveCValue(inst, inst_ty, operand),
...@@ -5817,7 +5911,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5817,7 +5911,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5817 const pt = f.object.dg.pt;5911 const pt = f.object.dg.pt;
5818 const zcu = pt.zcu;5912 const zcu = pt.zcu;
5819 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5913 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5820 const writer = f.object.writer();5914 const w = &f.object.code.writer;
5821 const operand = try f.resolveInst(ty_op.operand);5915 const operand = try f.resolveInst(ty_op.operand);
5822 try reap(f, inst, &.{ty_op.operand});5916 try reap(f, inst, &.{ty_op.operand});
5823 const operand_ty = f.typeOf(ty_op.operand);5917 const operand_ty = f.typeOf(ty_op.operand);
...@@ -5826,40 +5920,40 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5826,40 +5920,40 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5826 const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete);5920 const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete);
5827 switch (opt_ctype.info(&f.object.dg.ctype_pool)) {5921 switch (opt_ctype.info(&f.object.dg.ctype_pool)) {
5828 .basic => {5922 .basic => {
5829 const a = try Assignment.start(f, writer, opt_ctype);5923 const a = try Assignment.start(f, w, opt_ctype);
5830 try f.writeCValueDeref(writer, operand);5924 try f.writeCValueDeref(w, operand);
5831 try a.assign(f, writer);5925 try a.assign(f, w);
5832 try f.object.dg.renderValue(writer, Value.false, .Other);5926 try f.object.dg.renderValue(w, Value.false, .Other);
5833 try a.end(f, writer);5927 try a.end(f, w);
5834 return .none;5928 return .none;
5835 },5929 },
5836 .pointer => {5930 .pointer => {
5837 if (f.liveness.isUnused(inst)) return .none;5931 if (f.liveness.isUnused(inst)) return .none;
5838 const local = try f.allocLocal(inst, inst_ty);5932 const local = try f.allocLocal(inst, inst_ty);
5839 const a = try Assignment.start(f, writer, opt_ctype);5933 const a = try Assignment.start(f, w, opt_ctype);
5840 try f.writeCValue(writer, local, .Other);5934 try f.writeCValue(w, local, .Other);
5841 try a.assign(f, writer);5935 try a.assign(f, w);
5842 try f.writeCValue(writer, operand, .Other);5936 try f.writeCValue(w, operand, .Other);
5843 try a.end(f, writer);5937 try a.end(f, w);
5844 return local;5938 return local;
5845 },5939 },
5846 .aligned, .array, .vector, .fwd_decl, .function => unreachable,5940 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5847 .aggregate => {5941 .aggregate => {
5848 {5942 {
5849 const a = try Assignment.start(f, writer, opt_ctype);5943 const a = try Assignment.start(f, w, opt_ctype);
5850 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" });5944 try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" });
5851 try a.assign(f, writer);5945 try a.assign(f, w);
5852 try f.object.dg.renderValue(writer, Value.false, .Other);5946 try f.object.dg.renderValue(w, Value.false, .Other);
5853 try a.end(f, writer);5947 try a.end(f, w);
5854 }5948 }
5855 if (f.liveness.isUnused(inst)) return .none;5949 if (f.liveness.isUnused(inst)) return .none;
5856 const local = try f.allocLocal(inst, inst_ty);5950 const local = try f.allocLocal(inst, inst_ty);
5857 const a = try Assignment.start(f, writer, opt_ctype);5951 const a = try Assignment.start(f, w, opt_ctype);
5858 try f.writeCValue(writer, local, .Other);5952 try f.writeCValue(w, local, .Other);
5859 try a.assign(f, writer);5953 try a.assign(f, w);
5860 try writer.writeByte('&');5954 try w.writeByte('&');
5861 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });5955 try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
5862 try a.end(f, writer);5956 try a.end(f, w);
5863 return local;5957 return local;
5864 },5958 },
5865 }5959 }
...@@ -5967,42 +6061,43 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5967,42 +6061,43 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5967 const field_ptr_val = try f.resolveInst(extra.field_ptr);6061 const field_ptr_val = try f.resolveInst(extra.field_ptr);
5968 try reap(f, inst, &.{extra.field_ptr});6062 try reap(f, inst, &.{extra.field_ptr});
59696063
5970 const writer = f.object.writer();6064 const w = &f.object.code.writer;
5971 const local = try f.allocLocal(inst, container_ptr_ty);6065 const local = try f.allocLocal(inst, container_ptr_ty);
5972 try f.writeCValue(writer, local, .Other);6066 try f.writeCValue(w, local, .Other);
5973 try writer.writeAll(" = (");6067 try w.writeAll(" = (");
5974 try f.renderType(writer, container_ptr_ty);6068 try f.renderType(w, container_ptr_ty);
5975 try writer.writeByte(')');6069 try w.writeByte(')');
59766070
5977 switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, pt)) {6071 switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, pt)) {
5978 .begin => try f.writeCValue(writer, field_ptr_val, .Other),6072 .begin => try f.writeCValue(w, field_ptr_val, .Other),
5979 .field => |field| {6073 .field => |field| {
5980 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);6074 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
59816075
5982 try writer.writeAll("((");6076 try w.writeAll("((");
5983 try f.renderType(writer, u8_ptr_ty);6077 try f.renderType(w, u8_ptr_ty);
5984 try writer.writeByte(')');6078 try w.writeByte(')');
5985 try f.writeCValue(writer, field_ptr_val, .Other);6079 try f.writeCValue(w, field_ptr_val, .Other);
5986 try writer.writeAll(" - offsetof(");6080 try w.writeAll(" - offsetof(");
5987 try f.renderType(writer, container_ty);6081 try f.renderType(w, container_ty);
5988 try writer.writeAll(", ");6082 try w.writeAll(", ");
5989 try f.writeCValue(writer, field, .Other);6083 try f.writeCValue(w, field, .Other);
5990 try writer.writeAll("))");6084 try w.writeAll("))");
5991 },6085 },
5992 .byte_offset => |byte_offset| {6086 .byte_offset => |byte_offset| {
5993 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);6087 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
59946088
5995 try writer.writeAll("((");6089 try w.writeAll("((");
5996 try f.renderType(writer, u8_ptr_ty);6090 try f.renderType(w, u8_ptr_ty);
5997 try writer.writeByte(')');6091 try w.writeByte(')');
5998 try f.writeCValue(writer, field_ptr_val, .Other);6092 try f.writeCValue(w, field_ptr_val, .Other);
5999 try writer.print(" - {})", .{6093 try w.print(" - {f})", .{
6000 try f.fmtIntLiteral(try pt.intValue(.usize, byte_offset)),6094 try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)),
6001 });6095 });
6002 },6096 },
6003 }6097 }
60046098
6005 try writer.writeAll(";\n");6099 try w.writeByte(';');
6100 try f.object.newline();
6006 return local;6101 return local;
6007}6102}
60086103
...@@ -6021,33 +6116,34 @@ fn fieldPtr(...@@ -6021,33 +6116,34 @@ fn fieldPtr(
6021 // Ensure complete type definition is visible before accessing fields.6116 // Ensure complete type definition is visible before accessing fields.
6022 _ = try f.ctypeFromType(container_ty, .complete);6117 _ = try f.ctypeFromType(container_ty, .complete);
60236118
6024 const writer = f.object.writer();6119 const w = &f.object.code.writer;
6025 const local = try f.allocLocal(inst, field_ptr_ty);6120 const local = try f.allocLocal(inst, field_ptr_ty);
6026 try f.writeCValue(writer, local, .Other);6121 try f.writeCValue(w, local, .Other);
6027 try writer.writeAll(" = (");6122 try w.writeAll(" = (");
6028 try f.renderType(writer, field_ptr_ty);6123 try f.renderType(w, field_ptr_ty);
6029 try writer.writeByte(')');6124 try w.writeByte(')');
60306125
6031 switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, pt)) {6126 switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, pt)) {
6032 .begin => try f.writeCValue(writer, container_ptr_val, .Other),6127 .begin => try f.writeCValue(w, container_ptr_val, .Other),
6033 .field => |field| {6128 .field => |field| {
6034 try writer.writeByte('&');6129 try w.writeByte('&');
6035 try f.writeCValueDerefMember(writer, container_ptr_val, field);6130 try f.writeCValueDerefMember(w, container_ptr_val, field);
6036 },6131 },
6037 .byte_offset => |byte_offset| {6132 .byte_offset => |byte_offset| {
6038 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);6133 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
60396134
6040 try writer.writeAll("((");6135 try w.writeAll("((");
6041 try f.renderType(writer, u8_ptr_ty);6136 try f.renderType(w, u8_ptr_ty);
6042 try writer.writeByte(')');6137 try w.writeByte(')');
6043 try f.writeCValue(writer, container_ptr_val, .Other);6138 try f.writeCValue(w, container_ptr_val, .Other);
6044 try writer.print(" + {})", .{6139 try w.print(" + {f})", .{
6045 try f.fmtIntLiteral(try pt.intValue(.usize, byte_offset)),6140 try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)),
6046 });6141 });
6047 },6142 },
6048 }6143 }
60496144
6050 try writer.writeAll(";\n");6145 try w.writeByte(';');
6146 try f.object.newline();
6051 return local;6147 return local;
6052}6148}
60536149
...@@ -6067,7 +6163,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6067,7 +6163,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6067 const struct_byval = try f.resolveInst(extra.struct_operand);6163 const struct_byval = try f.resolveInst(extra.struct_operand);
6068 try reap(f, inst, &.{extra.struct_operand});6164 try reap(f, inst, &.{extra.struct_operand});
6069 const struct_ty = f.typeOf(extra.struct_operand);6165 const struct_ty = f.typeOf(extra.struct_operand);
6070 const writer = f.object.writer();6166 const w = &f.object.code.writer;
60716167
6072 // Ensure complete type definition is visible before accessing fields.6168 // Ensure complete type definition is visible before accessing fields.
6073 _ = try f.ctypeFromType(struct_ty, .complete);6169 _ = try f.ctypeFromType(struct_ty, .complete);
...@@ -6094,42 +6190,44 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6094,42 +6190,44 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6094 const field_int_ty = try pt.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu))));6190 const field_int_ty = try pt.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu))));
60956191
6096 const temp_local = try f.allocLocal(inst, field_int_ty);6192 const temp_local = try f.allocLocal(inst, field_int_ty);
6097 try f.writeCValue(writer, temp_local, .Other);6193 try f.writeCValue(w, temp_local, .Other);
6098 try writer.writeAll(" = zig_wrap_");6194 try w.writeAll(" = zig_wrap_");
6099 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);6195 try f.object.dg.renderTypeForBuiltinFnName(w, field_int_ty);
6100 try writer.writeAll("((");6196 try w.writeAll("((");
6101 try f.renderType(writer, field_int_ty);6197 try f.renderType(w, field_int_ty);
6102 try writer.writeByte(')');6198 try w.writeByte(')');
6103 const cant_cast = int_info.bits > 64;6199 const cant_cast = int_info.bits > 64;
6104 if (cant_cast) {6200 if (cant_cast) {
6105 if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});6201 if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
6106 try writer.writeAll("zig_lo_");6202 try w.writeAll("zig_lo_");
6107 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);6203 try f.object.dg.renderTypeForBuiltinFnName(w, struct_ty);
6108 try writer.writeByte('(');6204 try w.writeByte('(');
6109 }6205 }
6110 if (bit_offset > 0) {6206 if (bit_offset > 0) {
6111 try writer.writeAll("zig_shr_");6207 try w.writeAll("zig_shr_");
6112 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);6208 try f.object.dg.renderTypeForBuiltinFnName(w, struct_ty);
6113 try writer.writeByte('(');6209 try w.writeByte('(');
6114 }6210 }
6115 try f.writeCValue(writer, struct_byval, .Other);6211 try f.writeCValue(w, struct_byval, .Other);
6116 if (bit_offset > 0) try writer.print(", {})", .{6212 if (bit_offset > 0) try w.print(", {f})", .{
6117 try f.fmtIntLiteral(try pt.intValue(bit_offset_ty, bit_offset)),6213 try f.fmtIntLiteralDec(try pt.intValue(bit_offset_ty, bit_offset)),
6118 });6214 });
6119 if (cant_cast) try writer.writeByte(')');6215 if (cant_cast) try w.writeByte(')');
6120 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);6216 try f.object.dg.renderBuiltinInfo(w, field_int_ty, .bits);
6121 try writer.writeAll(");\n");6217 try w.writeAll(");");
6218 try f.object.newline();
6122 if (inst_ty.eql(field_int_ty, zcu)) return temp_local;6219 if (inst_ty.eql(field_int_ty, zcu)) return temp_local;
61236220
6124 const local = try f.allocLocal(inst, inst_ty);6221 const local = try f.allocLocal(inst, inst_ty);
6125 if (local.new_local != temp_local.new_local) {6222 if (local.new_local != temp_local.new_local) {
6126 try writer.writeAll("memcpy(");6223 try w.writeAll("memcpy(");
6127 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);6224 try f.writeCValue(w, .{ .local_ref = local.new_local }, .FunctionArgument);
6128 try writer.writeAll(", ");6225 try w.writeAll(", ");
6129 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);6226 try f.writeCValue(w, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
6130 try writer.writeAll(", sizeof(");6227 try w.writeAll(", sizeof(");
6131 try f.renderType(writer, inst_ty);6228 try f.renderType(w, inst_ty);
6132 try writer.writeAll("));\n");6229 try w.writeAll("));");
6230 try f.object.newline();
6133 }6231 }
6134 try freeLocal(f, inst, temp_local.new_local, null);6232 try freeLocal(f, inst, temp_local.new_local, null);
6135 return local;6233 return local;
...@@ -6150,10 +6248,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6150,10 +6248,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6150 .@"packed" => {6248 .@"packed" => {
6151 const operand_lval = if (struct_byval == .constant) blk: {6249 const operand_lval = if (struct_byval == .constant) blk: {
6152 const operand_local = try f.allocLocal(inst, struct_ty);6250 const operand_local = try f.allocLocal(inst, struct_ty);
6153 try f.writeCValue(writer, operand_local, .Other);6251 try f.writeCValue(w, operand_local, .Other);
6154 try writer.writeAll(" = ");6252 try w.writeAll(" = ");
6155 try f.writeCValue(writer, struct_byval, .Other);6253 try f.writeCValue(w, struct_byval, .Other);
6156 try writer.writeAll(";\n");6254 try w.writeByte(';');
6255 try f.object.newline();
6157 break :blk operand_local;6256 break :blk operand_local;
6158 } else struct_byval;6257 } else struct_byval;
6159 const local = try f.allocLocal(inst, inst_ty);6258 const local = try f.allocLocal(inst, inst_ty);
...@@ -6164,13 +6263,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6164,13 +6263,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6164 },6263 },
6165 else => true,6264 else => true,
6166 }) {6265 }) {
6167 try writer.writeAll("memcpy(&");6266 try w.writeAll("memcpy(&");
6168 try f.writeCValue(writer, local, .Other);6267 try f.writeCValue(w, local, .Other);
6169 try writer.writeAll(", &");6268 try w.writeAll(", &");
6170 try f.writeCValue(writer, operand_lval, .Other);6269 try f.writeCValue(w, operand_lval, .Other);
6171 try writer.writeAll(", sizeof(");6270 try w.writeAll(", sizeof(");
6172 try f.renderType(writer, inst_ty);6271 try f.renderType(w, inst_ty);
6173 try writer.writeAll("));\n");6272 try w.writeAll("));");
6273 try f.object.newline();
6174 }6274 }
6175 try f.freeCValue(inst, operand_lval);6275 try f.freeCValue(inst, operand_lval);
6176 return local;6276 return local;
...@@ -6181,11 +6281,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6181,11 +6281,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6181 };6281 };
61826282
6183 const local = try f.allocLocal(inst, inst_ty);6283 const local = try f.allocLocal(inst, inst_ty);
6184 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));6284 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
6185 try f.writeCValue(writer, local, .Other);6285 try f.writeCValue(w, local, .Other);
6186 try a.assign(f, writer);6286 try a.assign(f, w);
6187 try f.writeCValueMember(writer, struct_byval, field_name);6287 try f.writeCValueMember(w, struct_byval, field_name);
6188 try a.end(f, writer);6288 try a.end(f, w);
6189 return local;6289 return local;
6190}6290}
61916291
...@@ -6212,21 +6312,22 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6212,21 +6312,22 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6212 return local;6312 return local;
6213 }6313 }
62146314
6215 const writer = f.object.writer();6315 const w = &f.object.code.writer;
6216 try f.writeCValue(writer, local, .Other);6316 try f.writeCValue(w, local, .Other);
6217 try writer.writeAll(" = ");6317 try w.writeAll(" = ");
62186318
6219 if (!payload_ty.hasRuntimeBits(zcu))6319 if (!payload_ty.hasRuntimeBits(zcu))
6220 try f.writeCValue(writer, operand, .Other)6320 try f.writeCValue(w, operand, .Other)
6221 else if (error_ty.errorSetIsEmpty(zcu))6321 else if (error_ty.errorSetIsEmpty(zcu))
6222 try writer.print("{}", .{6322 try w.print("{f}", .{
6223 try f.fmtIntLiteral(try pt.intValue(try pt.errorIntType(), 0)),6323 try f.fmtIntLiteralDec(try pt.intValue(try pt.errorIntType(), 0)),
6224 })6324 })
6225 else if (operand_is_ptr)6325 else if (operand_is_ptr)
6226 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })6326 try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })
6227 else6327 else
6228 try f.writeCValueMember(writer, operand, .{ .identifier = "error" });6328 try f.writeCValueMember(w, operand, .{ .identifier = "error" });
6229 try writer.writeAll(";\n");6329 try w.writeByte(';');
6330 try f.object.newline();
6230 return local;6331 return local;
6231}6332}
62326333
...@@ -6241,29 +6342,30 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -6241,29 +6342,30 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
6241 const operand_ty = f.typeOf(ty_op.operand);6342 const operand_ty = f.typeOf(ty_op.operand);
6242 const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;6343 const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
62436344
6244 const writer = f.object.writer();6345 const w = &f.object.code.writer;
6245 if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {6346 if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {
6246 if (!is_ptr) return .none;6347 if (!is_ptr) return .none;
62476348
6248 const local = try f.allocLocal(inst, inst_ty);6349 const local = try f.allocLocal(inst, inst_ty);
6249 try f.writeCValue(writer, local, .Other);6350 try f.writeCValue(w, local, .Other);
6250 try writer.writeAll(" = (");6351 try w.writeAll(" = (");
6251 try f.renderType(writer, inst_ty);6352 try f.renderType(w, inst_ty);
6252 try writer.writeByte(')');6353 try w.writeByte(')');
6253 try f.writeCValue(writer, operand, .Other);6354 try f.writeCValue(w, operand, .Other);
6254 try writer.writeAll(";\n");6355 try w.writeByte(';');
6356 try f.object.newline();
6255 return local;6357 return local;
6256 }6358 }
62576359
6258 const local = try f.allocLocal(inst, inst_ty);6360 const local = try f.allocLocal(inst, inst_ty);
6259 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));6361 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
6260 try f.writeCValue(writer, local, .Other);6362 try f.writeCValue(w, local, .Other);
6261 try a.assign(f, writer);6363 try a.assign(f, w);
6262 if (is_ptr) {6364 if (is_ptr) {
6263 try writer.writeByte('&');6365 try w.writeByte('&');
6264 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });6366 try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
6265 } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });6367 } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" });
6266 try a.end(f, writer);6368 try a.end(f, w);
6267 return local;6369 return local;
6268}6370}
62696371
...@@ -6282,21 +6384,21 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6282,21 +6384,21 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
6282 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {6384 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
6283 .is_null, .payload => {6385 .is_null, .payload => {
6284 const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete);6386 const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete);
6285 const writer = f.object.writer();6387 const w = &f.object.code.writer;
6286 const local = try f.allocLocal(inst, inst_ty);6388 const local = try f.allocLocal(inst, inst_ty);
6287 {6389 {
6288 const a = try Assignment.start(f, writer, .bool);6390 const a = try Assignment.start(f, w, .bool);
6289 try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });6391 try f.writeCValueMember(w, local, .{ .identifier = "is_null" });
6290 try a.assign(f, writer);6392 try a.assign(f, w);
6291 try writer.writeAll("false");6393 try w.writeAll("false");
6292 try a.end(f, writer);6394 try a.end(f, w);
6293 }6395 }
6294 {6396 {
6295 const a = try Assignment.start(f, writer, operand_ctype);6397 const a = try Assignment.start(f, w, operand_ctype);
6296 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });6398 try f.writeCValueMember(w, local, .{ .identifier = "payload" });
6297 try a.assign(f, writer);6399 try a.assign(f, w);
6298 try f.writeCValue(writer, operand, .Other);6400 try f.writeCValue(w, operand, .Other);
6299 try a.end(f, writer);6401 try a.end(f, w);
6300 }6402 }
6301 return local;6403 return local;
6302 },6404 },
...@@ -6318,7 +6420,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6318,7 +6420,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6318 const err = try f.resolveInst(ty_op.operand);6420 const err = try f.resolveInst(ty_op.operand);
6319 try reap(f, inst, &.{ty_op.operand});6421 try reap(f, inst, &.{ty_op.operand});
63206422
6321 const writer = f.object.writer();6423 const w = &f.object.code.writer;
6322 const local = try f.allocLocal(inst, inst_ty);6424 const local = try f.allocLocal(inst, inst_ty);
63236425
6324 if (repr_is_err and err == .local and err.local == local.new_local) {6426 if (repr_is_err and err == .local and err.local == local.new_local) {
...@@ -6327,21 +6429,21 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6327,21 +6429,21 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6327 }6429 }
63286430
6329 if (!repr_is_err) {6431 if (!repr_is_err) {
6330 const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));6432 const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
6331 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });6433 try f.writeCValueMember(w, local, .{ .identifier = "payload" });
6332 try a.assign(f, writer);6434 try a.assign(f, w);
6333 try f.object.dg.renderUndefValue(writer, payload_ty, .Other);6435 try f.object.dg.renderUndefValue(w, payload_ty, .Other);
6334 try a.end(f, writer);6436 try a.end(f, w);
6335 }6437 }
6336 {6438 {
6337 const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete));6439 const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete));
6338 if (repr_is_err)6440 if (repr_is_err)
6339 try f.writeCValue(writer, local, .Other)6441 try f.writeCValue(w, local, .Other)
6340 else6442 else
6341 try f.writeCValueMember(writer, local, .{ .identifier = "error" });6443 try f.writeCValueMember(w, local, .{ .identifier = "error" });
6342 try a.assign(f, writer);6444 try a.assign(f, w);
6343 try f.writeCValue(writer, err, .Other);6445 try f.writeCValue(w, err, .Other);
6344 try a.end(f, writer);6446 try a.end(f, w);
6345 }6447 }
6346 return local;6448 return local;
6347}6449}
...@@ -6349,7 +6451,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6349,7 +6451,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6349fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {6451fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
6350 const pt = f.object.dg.pt;6452 const pt = f.object.dg.pt;
6351 const zcu = pt.zcu;6453 const zcu = pt.zcu;
6352 const writer = f.object.writer();6454 const w = &f.object.code.writer;
6353 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6455 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6354 const inst_ty = f.typeOfIndex(inst);6456 const inst_ty = f.typeOfIndex(inst);
6355 const operand = try f.resolveInst(ty_op.operand);6457 const operand = try f.resolveInst(ty_op.operand);
...@@ -6363,31 +6465,31 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6363,31 +6465,31 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
63636465
6364 // First, set the non-error value.6466 // First, set the non-error value.
6365 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {6467 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
6366 const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete));6468 const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete));
6367 try f.writeCValueDeref(writer, operand);6469 try f.writeCValueDeref(w, operand);
6368 try a.assign(f, writer);6470 try a.assign(f, w);
6369 try writer.print("{}", .{try f.fmtIntLiteral(no_err)});6471 try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)});
6370 try a.end(f, writer);6472 try a.end(f, w);
6371 return .none;6473 return .none;
6372 }6474 }
6373 {6475 {
6374 const a = try Assignment.start(f, writer, try f.ctypeFromType(err_int_ty, .complete));6476 const a = try Assignment.start(f, w, try f.ctypeFromType(err_int_ty, .complete));
6375 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" });6477 try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" });
6376 try a.assign(f, writer);6478 try a.assign(f, w);
6377 try writer.print("{}", .{try f.fmtIntLiteral(no_err)});6479 try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)});
6378 try a.end(f, writer);6480 try a.end(f, w);
6379 }6481 }
63806482
6381 // Then return the payload pointer (only if it is used)6483 // Then return the payload pointer (only if it is used)
6382 if (f.liveness.isUnused(inst)) return .none;6484 if (f.liveness.isUnused(inst)) return .none;
63836485
6384 const local = try f.allocLocal(inst, inst_ty);6486 const local = try f.allocLocal(inst, inst_ty);
6385 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));6487 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
6386 try f.writeCValue(writer, local, .Other);6488 try f.writeCValue(w, local, .Other);
6387 try a.assign(f, writer);6489 try a.assign(f, w);
6388 try writer.writeByte('&');6490 try w.writeByte('&');
6389 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });6491 try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
6390 try a.end(f, writer);6492 try a.end(f, w);
6391 return local;6493 return local;
6392}6494}
63936495
...@@ -6418,24 +6520,24 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6418,24 +6520,24 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
6418 const err_ty = inst_ty.errorUnionSet(zcu);6520 const err_ty = inst_ty.errorUnionSet(zcu);
6419 try reap(f, inst, &.{ty_op.operand});6521 try reap(f, inst, &.{ty_op.operand});
64206522
6421 const writer = f.object.writer();6523 const w = &f.object.code.writer;
6422 const local = try f.allocLocal(inst, inst_ty);6524 const local = try f.allocLocal(inst, inst_ty);
6423 if (!repr_is_err) {6525 if (!repr_is_err) {
6424 const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));6526 const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
6425 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });6527 try f.writeCValueMember(w, local, .{ .identifier = "payload" });
6426 try a.assign(f, writer);6528 try a.assign(f, w);
6427 try f.writeCValue(writer, payload, .Other);6529 try f.writeCValue(w, payload, .Other);
6428 try a.end(f, writer);6530 try a.end(f, w);
6429 }6531 }
6430 {6532 {
6431 const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete));6533 const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete));
6432 if (repr_is_err)6534 if (repr_is_err)
6433 try f.writeCValue(writer, local, .Other)6535 try f.writeCValue(w, local, .Other)
6434 else6536 else
6435 try f.writeCValueMember(writer, local, .{ .identifier = "error" });6537 try f.writeCValueMember(w, local, .{ .identifier = "error" });
6436 try a.assign(f, writer);6538 try a.assign(f, w);
6437 try f.object.dg.renderValue(writer, try pt.intValue(try pt.errorIntType(), 0), .Other);6539 try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other);
6438 try a.end(f, writer);6540 try a.end(f, w);
6439 }6541 }
6440 return local;6542 return local;
6441}6543}
...@@ -6445,7 +6547,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -6445,7 +6547,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
6445 const zcu = pt.zcu;6547 const zcu = pt.zcu;
6446 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;6548 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
64476549
6448 const writer = f.object.writer();6550 const w = &f.object.code.writer;
6449 const operand = try f.resolveInst(un_op);6551 const operand = try f.resolveInst(un_op);
6450 try reap(f, inst, &.{un_op});6552 try reap(f, inst, &.{un_op});
6451 const operand_ty = f.typeOf(un_op);6553 const operand_ty = f.typeOf(un_op);
...@@ -6454,25 +6556,25 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -6454,25 +6556,25 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
6454 const payload_ty = err_union_ty.errorUnionPayload(zcu);6556 const payload_ty = err_union_ty.errorUnionPayload(zcu);
6455 const error_ty = err_union_ty.errorUnionSet(zcu);6557 const error_ty = err_union_ty.errorUnionSet(zcu);
64566558
6457 const a = try Assignment.start(f, writer, .bool);6559 const a = try Assignment.start(f, w, .bool);
6458 try f.writeCValue(writer, local, .Other);6560 try f.writeCValue(w, local, .Other);
6459 try a.assign(f, writer);6561 try a.assign(f, w);
6460 const err_int_ty = try pt.errorIntType();6562 const err_int_ty = try pt.errorIntType();
6461 if (!error_ty.errorSetIsEmpty(zcu))6563 if (!error_ty.errorSetIsEmpty(zcu))
6462 if (payload_ty.hasRuntimeBits(zcu))6564 if (payload_ty.hasRuntimeBits(zcu))
6463 if (is_ptr)6565 if (is_ptr)
6464 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })6566 try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })
6465 else6567 else
6466 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })6568 try f.writeCValueMember(w, operand, .{ .identifier = "error" })
6467 else6569 else
6468 try f.writeCValue(writer, operand, .Other)6570 try f.writeCValue(w, operand, .Other)
6469 else6571 else
6470 try f.object.dg.renderValue(writer, try pt.intValue(err_int_ty, 0), .Other);6572 try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other);
6471 try writer.writeByte(' ');6573 try w.writeByte(' ');
6472 try writer.writeAll(operator);6574 try w.writeAll(operator);
6473 try writer.writeByte(' ');6575 try w.writeByte(' ');
6474 try f.object.dg.renderValue(writer, try pt.intValue(err_int_ty, 0), .Other);6576 try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other);
6475 try a.end(f, writer);6577 try a.end(f, w);
6476 return local;6578 return local;
6477}6579}
64786580
...@@ -6486,45 +6588,45 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6486,45 +6588,45 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
6486 try reap(f, inst, &.{ty_op.operand});6588 try reap(f, inst, &.{ty_op.operand});
6487 const inst_ty = f.typeOfIndex(inst);6589 const inst_ty = f.typeOfIndex(inst);
6488 const ptr_ty = inst_ty.slicePtrFieldType(zcu);6590 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
6489 const writer = f.object.writer();6591 const w = &f.object.code.writer;
6490 const local = try f.allocLocal(inst, inst_ty);6592 const local = try f.allocLocal(inst, inst_ty);
6491 const operand_ty = f.typeOf(ty_op.operand);6593 const operand_ty = f.typeOf(ty_op.operand);
6492 const array_ty = operand_ty.childType(zcu);6594 const array_ty = operand_ty.childType(zcu);
64936595
6494 {6596 {
6495 const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete));6597 const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));
6496 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });6598 try f.writeCValueMember(w, local, .{ .identifier = "ptr" });
6497 try a.assign(f, writer);6599 try a.assign(f, w);
6498 if (operand == .undef) {6600 if (operand == .undef) {
6499 try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Other);6601 try f.writeCValue(w, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Other);
6500 } else {6602 } else {
6501 const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete);6603 const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete);
6502 const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype;6604 const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype;
6503 const elem_ty = array_ty.childType(zcu);6605 const elem_ty = array_ty.childType(zcu);
6504 const elem_ctype = try f.ctypeFromType(elem_ty, .complete);6606 const elem_ctype = try f.ctypeFromType(elem_ty, .complete);
6505 if (!ptr_child_ctype.eql(elem_ctype)) {6607 if (!ptr_child_ctype.eql(elem_ctype)) {
6506 try writer.writeByte('(');6608 try w.writeByte('(');
6507 try f.renderCType(writer, ptr_ctype);6609 try f.renderCType(w, ptr_ctype);
6508 try writer.writeByte(')');6610 try w.writeByte(')');
6509 }6611 }
6510 const operand_ctype = try f.ctypeFromType(operand_ty, .complete);6612 const operand_ctype = try f.ctypeFromType(operand_ty, .complete);
6511 const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype;6613 const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype;
6512 if (operand_child_ctype.info(ctype_pool) == .array) {6614 if (operand_child_ctype.info(ctype_pool) == .array) {
6513 try writer.writeByte('&');6615 try w.writeByte('&');
6514 try f.writeCValueDeref(writer, operand);6616 try f.writeCValueDeref(w, operand);
6515 try writer.print("[{}]", .{try f.fmtIntLiteral(.zero_usize)});6617 try w.print("[{f}]", .{try f.fmtIntLiteralDec(.zero_usize)});
6516 } else try f.writeCValue(writer, operand, .Other);6618 } else try f.writeCValue(w, operand, .Other);
6517 }6619 }
6518 try a.end(f, writer);6620 try a.end(f, w);
6519 }6621 }
6520 {6622 {
6521 const a = try Assignment.start(f, writer, .usize);6623 const a = try Assignment.start(f, w, .usize);
6522 try f.writeCValueMember(writer, local, .{ .identifier = "len" });6624 try f.writeCValueMember(w, local, .{ .identifier = "len" });
6523 try a.assign(f, writer);6625 try a.assign(f, w);
6524 try writer.print("{}", .{6626 try w.print("{f}", .{
6525 try f.fmtIntLiteral(try pt.intValue(.usize, array_ty.arrayLen(zcu))),6627 try f.fmtIntLiteralDec(try pt.intValue(.usize, array_ty.arrayLen(zcu))),
6526 });6628 });
6527 try a.end(f, writer);6629 try a.end(f, w);
6528 }6630 }
65296631
6530 return local;6632 return local;
...@@ -6551,32 +6653,32 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6551,32 +6653,32 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
6551 else6653 else
6552 unreachable;6654 unreachable;
65536655
6554 const writer = f.object.writer();6656 const w = &f.object.code.writer;
6555 const local = try f.allocLocal(inst, inst_ty);6657 const local = try f.allocLocal(inst, inst_ty);
6556 const v = try Vectorize.start(f, inst, writer, operand_ty);6658 const v = try Vectorize.start(f, inst, w, operand_ty);
6557 const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));6659 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
6558 try f.writeCValue(writer, local, .Other);6660 try f.writeCValue(w, local, .Other);
6559 try v.elem(f, writer);6661 try v.elem(f, w);
6560 try a.assign(f, writer);6662 try a.assign(f, w);
6561 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {6663 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
6562 try writer.writeAll("zig_wrap_");6664 try w.writeAll("zig_wrap_");
6563 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);6665 try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
6564 try writer.writeByte('(');6666 try w.writeByte('(');
6565 }6667 }
6566 try writer.writeAll("zig_");6668 try w.writeAll("zig_");
6567 try writer.writeAll(operation);6669 try w.writeAll(operation);
6568 try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));6670 try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));
6569 try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));6671 try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));
6570 try writer.writeByte('(');6672 try w.writeByte('(');
6571 try f.writeCValue(writer, operand, .FunctionArgument);6673 try f.writeCValue(w, operand, .FunctionArgument);
6572 try v.elem(f, writer);6674 try v.elem(f, w);
6573 try writer.writeByte(')');6675 try w.writeByte(')');
6574 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {6676 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
6575 try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits);6677 try f.object.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits);
6576 try writer.writeByte(')');6678 try w.writeByte(')');
6577 }6679 }
6578 try a.end(f, writer);6680 try a.end(f, w);
6579 try v.end(f, inst, writer);6681 try v.end(f, inst, w);
65806682
6581 return local;6683 return local;
6582}6684}
...@@ -6601,27 +6703,28 @@ fn airUnBuiltinCall(...@@ -6601,27 +6703,28 @@ fn airUnBuiltinCall(
6601 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6703 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6602 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;6704 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
66036705
6604 const writer = f.object.writer();6706 const w = &f.object.code.writer;
6605 const local = try f.allocLocal(inst, inst_ty);6707 const local = try f.allocLocal(inst, inst_ty);
6606 const v = try Vectorize.start(f, inst, writer, operand_ty);6708 const v = try Vectorize.start(f, inst, w, operand_ty);
6607 if (!ref_ret) {6709 if (!ref_ret) {
6608 try f.writeCValue(writer, local, .Other);6710 try f.writeCValue(w, local, .Other);
6609 try v.elem(f, writer);6711 try v.elem(f, w);
6610 try writer.writeAll(" = ");6712 try w.writeAll(" = ");
6611 }6713 }
6612 try writer.print("zig_{s}_", .{operation});6714 try w.print("zig_{s}_", .{operation});
6613 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);6715 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
6614 try writer.writeByte('(');6716 try w.writeByte('(');
6615 if (ref_ret) {6717 if (ref_ret) {
6616 try f.writeCValue(writer, local, .FunctionArgument);6718 try f.writeCValue(w, local, .FunctionArgument);
6617 try v.elem(f, writer);6719 try v.elem(f, w);
6618 try writer.writeAll(", ");6720 try w.writeAll(", ");
6619 }6721 }
6620 try f.writeCValue(writer, operand, .FunctionArgument);6722 try f.writeCValue(w, operand, .FunctionArgument);
6621 try v.elem(f, writer);6723 try v.elem(f, w);
6622 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);6724 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
6623 try writer.writeAll(");\n");6725 try w.writeAll(");");
6624 try v.end(f, inst, writer);6726 try f.object.newline();
6727 try v.end(f, inst, w);
66256728
6626 return local;6729 return local;
6627}6730}
...@@ -6651,31 +6754,31 @@ fn airBinBuiltinCall(...@@ -6651,31 +6754,31 @@ fn airBinBuiltinCall(
6651 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6754 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6652 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;6755 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
66536756
6654 const writer = f.object.writer();6757 const w = &f.object.code.writer;
6655 const local = try f.allocLocal(inst, inst_ty);6758 const local = try f.allocLocal(inst, inst_ty);
6656 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });6759 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
6657 const v = try Vectorize.start(f, inst, writer, operand_ty);6760 const v = try Vectorize.start(f, inst, w, operand_ty);
6658 if (!ref_ret) {6761 if (!ref_ret) {
6659 try f.writeCValue(writer, local, .Other);6762 try f.writeCValue(w, local, .Other);
6660 try v.elem(f, writer);6763 try v.elem(f, w);
6661 try writer.writeAll(" = ");6764 try w.writeAll(" = ");
6662 }6765 }
6663 try writer.print("zig_{s}_", .{operation});6766 try w.print("zig_{s}_", .{operation});
6664 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);6767 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
6665 try writer.writeByte('(');6768 try w.writeByte('(');
6666 if (ref_ret) {6769 if (ref_ret) {
6667 try f.writeCValue(writer, local, .FunctionArgument);6770 try f.writeCValue(w, local, .FunctionArgument);
6668 try v.elem(f, writer);6771 try v.elem(f, w);
6669 try writer.writeAll(", ");6772 try w.writeAll(", ");
6670 }6773 }
6671 try f.writeCValue(writer, lhs, .FunctionArgument);6774 try f.writeCValue(w, lhs, .FunctionArgument);
6672 try v.elem(f, writer);6775 try v.elem(f, w);
6673 try writer.writeAll(", ");6776 try w.writeAll(", ");
6674 try f.writeCValue(writer, rhs, .FunctionArgument);6777 try f.writeCValue(w, rhs, .FunctionArgument);
6675 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer);6778 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
6676 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);6779 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
6677 try writer.writeAll(");\n");6780 try w.writeAll(");\n");
6678 try v.end(f, inst, writer);6781 try v.end(f, inst, w);
66796782
6680 return local;6783 return local;
6681}6784}
...@@ -6702,38 +6805,39 @@ fn airCmpBuiltinCall(...@@ -6702,38 +6805,39 @@ fn airCmpBuiltinCall(
6702 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6805 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6703 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;6806 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
67046807
6705 const writer = f.object.writer();6808 const w = &f.object.code.writer;
6706 const local = try f.allocLocal(inst, inst_ty);6809 const local = try f.allocLocal(inst, inst_ty);
6707 const v = try Vectorize.start(f, inst, writer, operand_ty);6810 const v = try Vectorize.start(f, inst, w, operand_ty);
6708 if (!ref_ret) {6811 if (!ref_ret) {
6709 try f.writeCValue(writer, local, .Other);6812 try f.writeCValue(w, local, .Other);
6710 try v.elem(f, writer);6813 try v.elem(f, w);
6711 try writer.writeAll(" = ");6814 try w.writeAll(" = ");
6712 }6815 }
6713 try writer.print("zig_{s}_", .{switch (operation) {6816 try w.print("zig_{s}_", .{switch (operation) {
6714 else => @tagName(operation),6817 else => @tagName(operation),
6715 .operator => compareOperatorAbbrev(operator),6818 .operator => compareOperatorAbbrev(operator),
6716 }});6819 }});
6717 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);6820 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
6718 try writer.writeByte('(');6821 try w.writeByte('(');
6719 if (ref_ret) {6822 if (ref_ret) {
6720 try f.writeCValue(writer, local, .FunctionArgument);6823 try f.writeCValue(w, local, .FunctionArgument);
6721 try v.elem(f, writer);6824 try v.elem(f, w);
6722 try writer.writeAll(", ");6825 try w.writeAll(", ");
6723 }6826 }
6724 try f.writeCValue(writer, lhs, .FunctionArgument);6827 try f.writeCValue(w, lhs, .FunctionArgument);
6725 try v.elem(f, writer);6828 try v.elem(f, w);
6726 try writer.writeAll(", ");6829 try w.writeAll(", ");
6727 try f.writeCValue(writer, rhs, .FunctionArgument);6830 try f.writeCValue(w, rhs, .FunctionArgument);
6728 try v.elem(f, writer);6831 try v.elem(f, w);
6729 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);6832 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
6730 try writer.writeByte(')');6833 try w.writeByte(')');
6731 if (!ref_ret) try writer.print("{s}{}", .{6834 if (!ref_ret) try w.print("{s}{f}", .{
6732 compareOperatorC(operator),6835 compareOperatorC(operator),
6733 try f.fmtIntLiteral(try pt.intValue(.i32, 0)),6836 try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)),
6734 });6837 });
6735 try writer.writeAll(";\n");6838 try w.writeByte(';');
6736 try v.end(f, inst, writer);6839 try f.object.newline();
6840 try v.end(f, inst, w);
67376841
6738 return local;6842 return local;
6739}6843}
...@@ -6751,7 +6855,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6751,7 +6855,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6751 const ty = ptr_ty.childType(zcu);6855 const ty = ptr_ty.childType(zcu);
6752 const ctype = try f.ctypeFromType(ty, .complete);6856 const ctype = try f.ctypeFromType(ty, .complete);
67536857
6754 const writer = f.object.writer();6858 const w = &f.object.code.writer;
6755 const new_value_mat = try Materialize.start(f, inst, ty, new_value);6859 const new_value_mat = try Materialize.start(f, inst, ty, new_value);
6756 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });6860 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
67576861
...@@ -6763,76 +6867,78 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6763,76 +6867,78 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6763 const local = try f.allocLocal(inst, inst_ty);6867 const local = try f.allocLocal(inst, inst_ty);
6764 if (inst_ty.isPtrLikeOptional(zcu)) {6868 if (inst_ty.isPtrLikeOptional(zcu)) {
6765 {6869 {
6766 const a = try Assignment.start(f, writer, ctype);6870 const a = try Assignment.start(f, w, ctype);
6767 try f.writeCValue(writer, local, .Other);6871 try f.writeCValue(w, local, .Other);
6768 try a.assign(f, writer);6872 try a.assign(f, w);
6769 try f.writeCValue(writer, expected_value, .Other);6873 try f.writeCValue(w, expected_value, .Other);
6770 try a.end(f, writer);6874 try a.end(f, w);
6771 }6875 }
67726876
6773 try writer.writeAll("if (");6877 try w.writeAll("if (");
6774 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});6878 try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
6775 try f.renderType(writer, ty);6879 try f.renderType(w, ty);
6776 try writer.writeByte(')');6880 try w.writeByte(')');
6777 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");6881 if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
6778 try writer.writeAll(" *)");6882 try w.writeAll(" *)");
6779 try f.writeCValue(writer, ptr, .Other);6883 try f.writeCValue(w, ptr, .Other);
6780 try writer.writeAll(", ");6884 try w.writeAll(", ");
6781 try f.writeCValue(writer, local, .FunctionArgument);6885 try f.writeCValue(w, local, .FunctionArgument);
6782 try writer.writeAll(", ");6886 try w.writeAll(", ");
6783 try new_value_mat.mat(f, writer);6887 try new_value_mat.mat(f, w);
6784 try writer.writeAll(", ");6888 try w.writeAll(", ");
6785 try writeMemoryOrder(writer, extra.successOrder());6889 try writeMemoryOrder(w, extra.successOrder());
6786 try writer.writeAll(", ");6890 try w.writeAll(", ");
6787 try writeMemoryOrder(writer, extra.failureOrder());6891 try writeMemoryOrder(w, extra.failureOrder());
6788 try writer.writeAll(", ");6892 try w.writeAll(", ");
6789 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);6893 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6790 try writer.writeAll(", ");6894 try w.writeAll(", ");
6791 try f.renderType(writer, repr_ty);6895 try f.renderType(w, repr_ty);
6792 try writer.writeByte(')');6896 try w.writeByte(')');
6793 try writer.writeAll(") {\n");6897 try w.writeAll(") {");
6794 f.object.indent_writer.pushIndent();6898 f.object.indent();
6899 try f.object.newline();
6795 {6900 {
6796 const a = try Assignment.start(f, writer, ctype);6901 const a = try Assignment.start(f, w, ctype);
6797 try f.writeCValue(writer, local, .Other);6902 try f.writeCValue(w, local, .Other);
6798 try a.assign(f, writer);6903 try a.assign(f, w);
6799 try writer.writeAll("NULL");6904 try w.writeAll("NULL");
6800 try a.end(f, writer);6905 try a.end(f, w);
6801 }6906 }
6802 f.object.indent_writer.popIndent();6907 try f.object.outdent();
6803 try writer.writeAll("}\n");6908 try w.writeByte('}');
6909 try f.object.newline();
6804 } else {6910 } else {
6805 {6911 {
6806 const a = try Assignment.start(f, writer, ctype);6912 const a = try Assignment.start(f, w, ctype);
6807 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });6913 try f.writeCValueMember(w, local, .{ .identifier = "payload" });
6808 try a.assign(f, writer);6914 try a.assign(f, w);
6809 try f.writeCValue(writer, expected_value, .Other);6915 try f.writeCValue(w, expected_value, .Other);
6810 try a.end(f, writer);6916 try a.end(f, w);
6811 }6917 }
6812 {6918 {
6813 const a = try Assignment.start(f, writer, .bool);6919 const a = try Assignment.start(f, w, .bool);
6814 try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });6920 try f.writeCValueMember(w, local, .{ .identifier = "is_null" });
6815 try a.assign(f, writer);6921 try a.assign(f, w);
6816 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});6922 try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
6817 try f.renderType(writer, ty);6923 try f.renderType(w, ty);
6818 try writer.writeByte(')');6924 try w.writeByte(')');
6819 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");6925 if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
6820 try writer.writeAll(" *)");6926 try w.writeAll(" *)");
6821 try f.writeCValue(writer, ptr, .Other);6927 try f.writeCValue(w, ptr, .Other);
6822 try writer.writeAll(", ");6928 try w.writeAll(", ");
6823 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });6929 try f.writeCValueMember(w, local, .{ .identifier = "payload" });
6824 try writer.writeAll(", ");6930 try w.writeAll(", ");
6825 try new_value_mat.mat(f, writer);6931 try new_value_mat.mat(f, w);
6826 try writer.writeAll(", ");6932 try w.writeAll(", ");
6827 try writeMemoryOrder(writer, extra.successOrder());6933 try writeMemoryOrder(w, extra.successOrder());
6828 try writer.writeAll(", ");6934 try w.writeAll(", ");
6829 try writeMemoryOrder(writer, extra.failureOrder());6935 try writeMemoryOrder(w, extra.failureOrder());
6830 try writer.writeAll(", ");6936 try w.writeAll(", ");
6831 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);6937 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6832 try writer.writeAll(", ");6938 try w.writeAll(", ");
6833 try f.renderType(writer, repr_ty);6939 try f.renderType(w, repr_ty);
6834 try writer.writeByte(')');6940 try w.writeByte(')');
6835 try a.end(f, writer);6941 try a.end(f, w);
6836 }6942 }
6837 }6943 }
6838 try new_value_mat.end(f, inst);6944 try new_value_mat.end(f, inst);
...@@ -6856,7 +6962,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6856,7 +6962,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6856 const ptr = try f.resolveInst(pl_op.operand);6962 const ptr = try f.resolveInst(pl_op.operand);
6857 const operand = try f.resolveInst(extra.operand);6963 const operand = try f.resolveInst(extra.operand);
68586964
6859 const writer = f.object.writer();6965 const w = &f.object.code.writer;
6860 const operand_mat = try Materialize.start(f, inst, ty, operand);6966 const operand_mat = try Materialize.start(f, inst, ty, operand);
6861 try reap(f, inst, &.{ pl_op.operand, extra.operand });6967 try reap(f, inst, &.{ pl_op.operand, extra.operand });
68626968
...@@ -6866,31 +6972,32 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6866,31 +6972,32 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6866 const repr_ty = if (is_float) pt.intType(.unsigned, repr_bits) catch unreachable else ty;6972 const repr_ty = if (is_float) pt.intType(.unsigned, repr_bits) catch unreachable else ty;
68676973
6868 const local = try f.allocLocal(inst, inst_ty);6974 const local = try f.allocLocal(inst, inst_ty);
6869 try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});6975 try w.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
6870 if (is_float) try writer.writeAll("_float") else if (is_128) try writer.writeAll("_int128");6976 if (is_float) try w.writeAll("_float") else if (is_128) try w.writeAll("_int128");
6871 try writer.writeByte('(');6977 try w.writeByte('(');
6872 try f.writeCValue(writer, local, .Other);6978 try f.writeCValue(w, local, .Other);
6873 try writer.writeAll(", (");6979 try w.writeAll(", (");
6874 const use_atomic = switch (extra.op()) {6980 const use_atomic = switch (extra.op()) {
6875 else => true,6981 else => true,
6876 // These are missing from stdatomic.h, so no atomic types unless a fallback is used.6982 // These are missing from stdatomic.h, so no atomic types unless a fallback is used.
6877 .Nand, .Min, .Max => is_float or is_128,6983 .Nand, .Min, .Max => is_float or is_128,
6878 };6984 };
6879 if (use_atomic) try writer.writeAll("zig_atomic(");6985 if (use_atomic) try w.writeAll("zig_atomic(");
6880 try f.renderType(writer, ty);6986 try f.renderType(w, ty);
6881 if (use_atomic) try writer.writeByte(')');6987 if (use_atomic) try w.writeByte(')');
6882 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");6988 if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
6883 try writer.writeAll(" *)");6989 try w.writeAll(" *)");
6884 try f.writeCValue(writer, ptr, .Other);6990 try f.writeCValue(w, ptr, .Other);
6885 try writer.writeAll(", ");6991 try w.writeAll(", ");
6886 try operand_mat.mat(f, writer);6992 try operand_mat.mat(f, w);
6887 try writer.writeAll(", ");6993 try w.writeAll(", ");
6888 try writeMemoryOrder(writer, extra.ordering());6994 try writeMemoryOrder(w, extra.ordering());
6889 try writer.writeAll(", ");6995 try w.writeAll(", ");
6890 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);6996 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6891 try writer.writeAll(", ");6997 try w.writeAll(", ");
6892 try f.renderType(writer, repr_ty);6998 try f.renderType(w, repr_ty);
6893 try writer.writeAll(");\n");6999 try w.writeAll(");");
7000 try f.object.newline();
6894 try operand_mat.end(f, inst);7001 try operand_mat.end(f, inst);
68957002
6896 if (f.liveness.isUnused(inst)) {7003 if (f.liveness.isUnused(inst)) {
...@@ -6916,24 +7023,25 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6916,24 +7023,25 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6916 ty;7023 ty;
69177024
6918 const inst_ty = f.typeOfIndex(inst);7025 const inst_ty = f.typeOfIndex(inst);
6919 const writer = f.object.writer();7026 const w = &f.object.code.writer;
6920 const local = try f.allocLocal(inst, inst_ty);7027 const local = try f.allocLocal(inst, inst_ty);
69217028
6922 try writer.writeAll("zig_atomic_load(");7029 try w.writeAll("zig_atomic_load(");
6923 try f.writeCValue(writer, local, .Other);7030 try f.writeCValue(w, local, .Other);
6924 try writer.writeAll(", (zig_atomic(");7031 try w.writeAll(", (zig_atomic(");
6925 try f.renderType(writer, ty);7032 try f.renderType(w, ty);
6926 try writer.writeByte(')');7033 try w.writeByte(')');
6927 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");7034 if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
6928 try writer.writeAll(" *)");7035 try w.writeAll(" *)");
6929 try f.writeCValue(writer, ptr, .Other);7036 try f.writeCValue(w, ptr, .Other);
6930 try writer.writeAll(", ");7037 try w.writeAll(", ");
6931 try writeMemoryOrder(writer, atomic_load.order);7038 try writeMemoryOrder(w, atomic_load.order);
6932 try writer.writeAll(", ");7039 try w.writeAll(", ");
6933 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);7040 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6934 try writer.writeAll(", ");7041 try w.writeAll(", ");
6935 try f.renderType(writer, repr_ty);7042 try f.renderType(w, repr_ty);
6936 try writer.writeAll(");\n");7043 try w.writeAll(");");
7044 try f.object.newline();
69377045
6938 return local;7046 return local;
6939}7047}
...@@ -6947,7 +7055,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -6947,7 +7055,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
6947 const ptr = try f.resolveInst(bin_op.lhs);7055 const ptr = try f.resolveInst(bin_op.lhs);
6948 const element = try f.resolveInst(bin_op.rhs);7056 const element = try f.resolveInst(bin_op.rhs);
69497057
6950 const writer = f.object.writer();7058 const w = &f.object.code.writer;
6951 const element_mat = try Materialize.start(f, inst, ty, element);7059 const element_mat = try Materialize.start(f, inst, ty, element);
6952 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });7060 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
69537061
...@@ -6956,31 +7064,32 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -6956,31 +7064,32 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
6956 else7064 else
6957 ty;7065 ty;
69587066
6959 try writer.writeAll("zig_atomic_store((zig_atomic(");7067 try w.writeAll("zig_atomic_store((zig_atomic(");
6960 try f.renderType(writer, ty);7068 try f.renderType(w, ty);
6961 try writer.writeByte(')');7069 try w.writeByte(')');
6962 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");7070 if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
6963 try writer.writeAll(" *)");7071 try w.writeAll(" *)");
6964 try f.writeCValue(writer, ptr, .Other);7072 try f.writeCValue(w, ptr, .Other);
6965 try writer.writeAll(", ");7073 try w.writeAll(", ");
6966 try element_mat.mat(f, writer);7074 try element_mat.mat(f, w);
6967 try writer.print(", {s}, ", .{order});7075 try w.print(", {s}, ", .{order});
6968 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);7076 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6969 try writer.writeAll(", ");7077 try w.writeAll(", ");
6970 try f.renderType(writer, repr_ty);7078 try f.renderType(w, repr_ty);
6971 try writer.writeAll(");\n");7079 try w.writeAll(");");
7080 try f.object.newline();
6972 try element_mat.end(f, inst);7081 try element_mat.end(f, inst);
69737082
6974 return .none;7083 return .none;
6975}7084}
69767085
6977fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {7086fn writeSliceOrPtr(f: *Function, w: *Writer, ptr: CValue, ptr_ty: Type) !void {
6978 const pt = f.object.dg.pt;7087 const pt = f.object.dg.pt;
6979 const zcu = pt.zcu;7088 const zcu = pt.zcu;
6980 if (ptr_ty.isSlice(zcu)) {7089 if (ptr_ty.isSlice(zcu)) {
6981 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });7090 try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" });
6982 } else {7091 } else {
6983 try f.writeCValue(writer, ptr, .FunctionArgument);7092 try f.writeCValue(w, ptr, .FunctionArgument);
6984 }7093 }
6985}7094}
69867095
...@@ -6994,7 +7103,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6994,7 +7103,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6994 const elem_ty = f.typeOf(bin_op.rhs);7103 const elem_ty = f.typeOf(bin_op.rhs);
6995 const elem_abi_size = elem_ty.abiSize(zcu);7104 const elem_abi_size = elem_ty.abiSize(zcu);
6996 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(zcu) else false;7105 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(zcu) else false;
6997 const writer = f.object.writer();7106 const w = &f.object.code.writer;
69987107
6999 if (val_is_undef) {7108 if (val_is_undef) {
7000 if (!safety) {7109 if (!safety) {
...@@ -7002,24 +7111,25 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7002,24 +7111,25 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
7002 return .none;7111 return .none;
7003 }7112 }
70047113
7005 try writer.writeAll("memset(");7114 try w.writeAll("memset(");
7006 switch (dest_ty.ptrSize(zcu)) {7115 switch (dest_ty.ptrSize(zcu)) {
7007 .slice => {7116 .slice => {
7008 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });7117 try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" });
7009 try writer.writeAll(", 0xaa, ");7118 try w.writeAll(", 0xaa, ");
7010 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });7119 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
7011 if (elem_abi_size > 1) {7120 if (elem_abi_size > 1) {
7012 try writer.print(" * {d});\n", .{elem_abi_size});7121 try w.print(" * {d}", .{elem_abi_size});
7013 } else {
7014 try writer.writeAll(");\n");
7015 }7122 }
7123 try w.writeAll(");");
7124 try f.object.newline();
7016 },7125 },
7017 .one => {7126 .one => {
7018 const array_ty = dest_ty.childType(zcu);7127 const array_ty = dest_ty.childType(zcu);
7019 const len = array_ty.arrayLen(zcu) * elem_abi_size;7128 const len = array_ty.arrayLen(zcu) * elem_abi_size;
70207129
7021 try f.writeCValue(writer, dest_slice, .FunctionArgument);7130 try f.writeCValue(w, dest_slice, .FunctionArgument);
7022 try writer.print(", 0xaa, {d});\n", .{len});7131 try w.print(", 0xaa, {d});", .{len});
7132 try f.object.newline();
7023 },7133 },
7024 .many, .c => unreachable,7134 .many, .c => unreachable,
7025 }7135 }
...@@ -7040,38 +7150,38 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7040,38 +7150,38 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
70407150
7041 const index = try f.allocLocal(inst, .usize);7151 const index = try f.allocLocal(inst, .usize);
70427152
7043 try writer.writeAll("for (");7153 try w.writeAll("for (");
7044 try f.writeCValue(writer, index, .Other);7154 try f.writeCValue(w, index, .Other);
7045 try writer.writeAll(" = ");7155 try w.writeAll(" = ");
7046 try f.object.dg.renderValue(writer, .zero_usize, .Other);7156 try f.object.dg.renderValue(w, .zero_usize, .Other);
7047 try writer.writeAll("; ");7157 try w.writeAll("; ");
7048 try f.writeCValue(writer, index, .Other);7158 try f.writeCValue(w, index, .Other);
7049 try writer.writeAll(" != ");7159 try w.writeAll(" != ");
7050 switch (dest_ty.ptrSize(zcu)) {7160 switch (dest_ty.ptrSize(zcu)) {
7051 .slice => {7161 .slice => {
7052 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });7162 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
7053 },7163 },
7054 .one => {7164 .one => {
7055 const array_ty = dest_ty.childType(zcu);7165 const array_ty = dest_ty.childType(zcu);
7056 try writer.print("{d}", .{array_ty.arrayLen(zcu)});7166 try w.print("{d}", .{array_ty.arrayLen(zcu)});
7057 },7167 },
7058 .many, .c => unreachable,7168 .many, .c => unreachable,
7059 }7169 }
7060 try writer.writeAll("; ++");7170 try w.writeAll("; ++");
7061 try f.writeCValue(writer, index, .Other);7171 try f.writeCValue(w, index, .Other);
7062 try writer.writeAll(") ");7172 try w.writeAll(") ");
70637173
7064 const a = try Assignment.start(f, writer, try f.ctypeFromType(elem_ty, .complete));7174 const a = try Assignment.start(f, w, try f.ctypeFromType(elem_ty, .complete));
7065 try writer.writeAll("((");7175 try w.writeAll("((");
7066 try f.renderType(writer, elem_ptr_ty);7176 try f.renderType(w, elem_ptr_ty);
7067 try writer.writeByte(')');7177 try w.writeByte(')');
7068 try writeSliceOrPtr(f, writer, dest_slice, dest_ty);7178 try writeSliceOrPtr(f, w, dest_slice, dest_ty);
7069 try writer.writeAll(")[");7179 try w.writeAll(")[");
7070 try f.writeCValue(writer, index, .Other);7180 try f.writeCValue(w, index, .Other);
7071 try writer.writeByte(']');7181 try w.writeByte(']');
7072 try a.assign(f, writer);7182 try a.assign(f, w);
7073 try f.writeCValue(writer, value, .Other);7183 try f.writeCValue(w, value, .Other);
7074 try a.end(f, writer);7184 try a.end(f, w);
70757185
7076 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });7186 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
7077 try freeLocal(f, inst, index.new_local, null);7187 try freeLocal(f, inst, index.new_local, null);
...@@ -7081,24 +7191,26 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7081,24 +7191,26 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
70817191
7082 const bitcasted = try bitcast(f, .u8, value, elem_ty);7192 const bitcasted = try bitcast(f, .u8, value, elem_ty);
70837193
7084 try writer.writeAll("memset(");7194 try w.writeAll("memset(");
7085 switch (dest_ty.ptrSize(zcu)) {7195 switch (dest_ty.ptrSize(zcu)) {
7086 .slice => {7196 .slice => {
7087 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });7197 try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" });
7088 try writer.writeAll(", ");7198 try w.writeAll(", ");
7089 try f.writeCValue(writer, bitcasted, .FunctionArgument);7199 try f.writeCValue(w, bitcasted, .FunctionArgument);
7090 try writer.writeAll(", ");7200 try w.writeAll(", ");
7091 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });7201 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
7092 try writer.writeAll(");\n");7202 try w.writeAll(");");
7203 try f.object.newline();
7093 },7204 },
7094 .one => {7205 .one => {
7095 const array_ty = dest_ty.childType(zcu);7206 const array_ty = dest_ty.childType(zcu);
7096 const len = array_ty.arrayLen(zcu) * elem_abi_size;7207 const len = array_ty.arrayLen(zcu) * elem_abi_size;
70977208
7098 try f.writeCValue(writer, dest_slice, .FunctionArgument);7209 try f.writeCValue(w, dest_slice, .FunctionArgument);
7099 try writer.writeAll(", ");7210 try w.writeAll(", ");
7100 try f.writeCValue(writer, bitcasted, .FunctionArgument);7211 try f.writeCValue(w, bitcasted, .FunctionArgument);
7101 try writer.print(", {d});\n", .{len});7212 try w.print(", {d});", .{len});
7213 try f.object.newline();
7102 },7214 },
7103 .many, .c => unreachable,7215 .many, .c => unreachable,
7104 }7216 }
...@@ -7115,36 +7227,38 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV...@@ -7115,36 +7227,38 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
7115 const src_ptr = try f.resolveInst(bin_op.rhs);7227 const src_ptr = try f.resolveInst(bin_op.rhs);
7116 const dest_ty = f.typeOf(bin_op.lhs);7228 const dest_ty = f.typeOf(bin_op.lhs);
7117 const src_ty = f.typeOf(bin_op.rhs);7229 const src_ty = f.typeOf(bin_op.rhs);
7118 const writer = f.object.writer();7230 const w = &f.object.code.writer;
71197231
7120 if (dest_ty.ptrSize(zcu) != .one) {7232 if (dest_ty.ptrSize(zcu) != .one) {
7121 try writer.writeAll("if (");7233 try w.writeAll("if (");
7122 try writeArrayLen(f, writer, dest_ptr, dest_ty);7234 try writeArrayLen(f, dest_ptr, dest_ty);
7123 try writer.writeAll(" != 0) ");7235 try w.writeAll(" != 0) ");
7124 }7236 }
7125 try writer.writeAll(function_paren);7237 try w.writeAll(function_paren);
7126 try writeSliceOrPtr(f, writer, dest_ptr, dest_ty);7238 try writeSliceOrPtr(f, w, dest_ptr, dest_ty);
7127 try writer.writeAll(", ");7239 try w.writeAll(", ");
7128 try writeSliceOrPtr(f, writer, src_ptr, src_ty);7240 try writeSliceOrPtr(f, w, src_ptr, src_ty);
7129 try writer.writeAll(", ");7241 try w.writeAll(", ");
7130 try writeArrayLen(f, writer, dest_ptr, dest_ty);7242 try writeArrayLen(f, dest_ptr, dest_ty);
7131 try writer.writeAll(" * sizeof(");7243 try w.writeAll(" * sizeof(");
7132 try f.renderType(writer, dest_ty.elemType2(zcu));7244 try f.renderType(w, dest_ty.elemType2(zcu));
7133 try writer.writeAll("));\n");7245 try w.writeAll("));");
7246 try f.object.newline();
71347247
7135 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });7248 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
7136 return .none;7249 return .none;
7137}7250}
71387251
7139fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void {7252fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void {
7140 const pt = f.object.dg.pt;7253 const pt = f.object.dg.pt;
7141 const zcu = pt.zcu;7254 const zcu = pt.zcu;
7255 const w = &f.object.code.writer;
7142 switch (dest_ty.ptrSize(zcu)) {7256 switch (dest_ty.ptrSize(zcu)) {
7143 .one => try writer.print("{}", .{7257 .one => try w.print("{f}", .{
7144 try f.fmtIntLiteral(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),7258 try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),
7145 }),7259 }),
7146 .many, .c => unreachable,7260 .many, .c => unreachable,
7147 .slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }),7261 .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }),
7148 }7262 }
7149}7263}
71507264
...@@ -7161,12 +7275,12 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7161,12 +7275,12 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
7161 if (layout.tag_size == 0) return .none;7275 if (layout.tag_size == 0) return .none;
7162 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;7276 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
71637277
7164 const writer = f.object.writer();7278 const w = &f.object.code.writer;
7165 const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete));7279 const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));
7166 try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" });7280 try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" });
7167 try a.assign(f, writer);7281 try a.assign(f, w);
7168 try f.writeCValue(writer, new_tag, .Other);7282 try f.writeCValue(w, new_tag, .Other);
7169 try a.end(f, writer);7283 try a.end(f, w);
7170 return .none;7284 return .none;
7171}7285}
71727286
...@@ -7183,13 +7297,13 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7183,13 +7297,13 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
7183 if (layout.tag_size == 0) return .none;7297 if (layout.tag_size == 0) return .none;
71847298
7185 const inst_ty = f.typeOfIndex(inst);7299 const inst_ty = f.typeOfIndex(inst);
7186 const writer = f.object.writer();7300 const w = &f.object.code.writer;
7187 const local = try f.allocLocal(inst, inst_ty);7301 const local = try f.allocLocal(inst, inst_ty);
7188 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));7302 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
7189 try f.writeCValue(writer, local, .Other);7303 try f.writeCValue(w, local, .Other);
7190 try a.assign(f, writer);7304 try a.assign(f, w);
7191 try f.writeCValueMember(writer, operand, .{ .identifier = "tag" });7305 try f.writeCValueMember(w, operand, .{ .identifier = "tag" });
7192 try a.end(f, writer);7306 try a.end(f, w);
7193 return local;7307 return local;
7194}7308}
71957309
...@@ -7201,14 +7315,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7201,14 +7315,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
7201 const operand = try f.resolveInst(un_op);7315 const operand = try f.resolveInst(un_op);
7202 try reap(f, inst, &.{un_op});7316 try reap(f, inst, &.{un_op});
72037317
7204 const writer = f.object.writer();7318 const w = &f.object.code.writer;
7205 const local = try f.allocLocal(inst, inst_ty);7319 const local = try f.allocLocal(inst, inst_ty);
7206 try f.writeCValue(writer, local, .Other);7320 try f.writeCValue(w, local, .Other);
7207 try writer.print(" = {s}(", .{7321 try w.print(" = {s}(", .{
7208 try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }),7322 try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }),
7209 });7323 });
7210 try f.writeCValue(writer, operand, .Other);7324 try f.writeCValue(w, operand, .Other);
7211 try writer.writeAll(");\n");7325 try w.writeAll(");");
7326 try f.object.newline();
72127327
7213 return local;7328 return local;
7214}7329}
...@@ -7216,16 +7331,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7216,16 +7331,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
7216fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {7331fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
7217 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;7332 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
72187333
7219 const writer = f.object.writer();7334 const w = &f.object.code.writer;
7220 const inst_ty = f.typeOfIndex(inst);7335 const inst_ty = f.typeOfIndex(inst);
7221 const operand = try f.resolveInst(un_op);7336 const operand = try f.resolveInst(un_op);
7222 try reap(f, inst, &.{un_op});7337 try reap(f, inst, &.{un_op});
7223 const local = try f.allocLocal(inst, inst_ty);7338 const local = try f.allocLocal(inst, inst_ty);
7224 try f.writeCValue(writer, local, .Other);7339 try f.writeCValue(w, local, .Other);
72257340
7226 try writer.writeAll(" = zig_errorName[");7341 try w.writeAll(" = zig_errorName[");
7227 try f.writeCValue(writer, operand, .Other);7342 try f.writeCValue(w, operand, .Other);
7228 try writer.writeAll(" - 1];\n");7343 try w.writeAll(" - 1];");
7344 try f.object.newline();
7229 return local;7345 return local;
7230}7346}
72317347
...@@ -7240,16 +7356,16 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7240,16 +7356,16 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
7240 const inst_ty = f.typeOfIndex(inst);7356 const inst_ty = f.typeOfIndex(inst);
7241 const inst_scalar_ty = inst_ty.scalarType(zcu);7357 const inst_scalar_ty = inst_ty.scalarType(zcu);
72427358
7243 const writer = f.object.writer();7359 const w = &f.object.code.writer;
7244 const local = try f.allocLocal(inst, inst_ty);7360 const local = try f.allocLocal(inst, inst_ty);
7245 const v = try Vectorize.start(f, inst, writer, inst_ty);7361 const v = try Vectorize.start(f, inst, w, inst_ty);
7246 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete));7362 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));
7247 try f.writeCValue(writer, local, .Other);7363 try f.writeCValue(w, local, .Other);
7248 try v.elem(f, writer);7364 try v.elem(f, w);
7249 try a.assign(f, writer);7365 try a.assign(f, w);
7250 try f.writeCValue(writer, operand, .Other);7366 try f.writeCValue(w, operand, .Other);
7251 try a.end(f, writer);7367 try a.end(f, w);
7252 try v.end(f, inst, writer);7368 try v.end(f, inst, w);
72537369
7254 return local;7370 return local;
7255}7371}
...@@ -7265,22 +7381,23 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7265,22 +7381,23 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
72657381
7266 const inst_ty = f.typeOfIndex(inst);7382 const inst_ty = f.typeOfIndex(inst);
72677383
7268 const writer = f.object.writer();7384 const w = &f.object.code.writer;
7269 const local = try f.allocLocal(inst, inst_ty);7385 const local = try f.allocLocal(inst, inst_ty);
7270 const v = try Vectorize.start(f, inst, writer, inst_ty);7386 const v = try Vectorize.start(f, inst, w, inst_ty);
7271 try f.writeCValue(writer, local, .Other);7387 try f.writeCValue(w, local, .Other);
7272 try v.elem(f, writer);7388 try v.elem(f, w);
7273 try writer.writeAll(" = ");7389 try w.writeAll(" = ");
7274 try f.writeCValue(writer, pred, .Other);7390 try f.writeCValue(w, pred, .Other);
7275 try v.elem(f, writer);7391 try v.elem(f, w);
7276 try writer.writeAll(" ? ");7392 try w.writeAll(" ? ");
7277 try f.writeCValue(writer, lhs, .Other);7393 try f.writeCValue(w, lhs, .Other);
7278 try v.elem(f, writer);7394 try v.elem(f, w);
7279 try writer.writeAll(" : ");7395 try w.writeAll(" : ");
7280 try f.writeCValue(writer, rhs, .Other);7396 try f.writeCValue(w, rhs, .Other);
7281 try v.elem(f, writer);7397 try v.elem(f, w);
7282 try writer.writeAll(";\n");7398 try w.writeByte(';');
7283 try v.end(f, inst, writer);7399 try f.object.newline();
7400 try v.end(f, inst, w);
72847401
7285 return local;7402 return local;
7286}7403}
...@@ -7294,24 +7411,24 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7294,24 +7411,24 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
7294 const operand = try f.resolveInst(unwrapped.operand);7411 const operand = try f.resolveInst(unwrapped.operand);
7295 const inst_ty = unwrapped.result_ty;7412 const inst_ty = unwrapped.result_ty;
72967413
7297 const writer = f.object.writer();7414 const w = &f.object.code.writer;
7298 const local = try f.allocLocal(inst, inst_ty);7415 const local = try f.allocLocal(inst, inst_ty);
7299 try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand7416 try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand
7300 for (mask, 0..) |mask_elem, out_idx| {7417 for (mask, 0..) |mask_elem, out_idx| {
7301 try f.writeCValue(writer, local, .Other);7418 try f.writeCValue(w, local, .Other);
7302 try writer.writeByte('[');7419 try w.writeByte('[');
7303 try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other);7420 try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other);
7304 try writer.writeAll("] = ");7421 try w.writeAll("] = ");
7305 switch (mask_elem.unwrap()) {7422 switch (mask_elem.unwrap()) {
7306 .elem => |src_idx| {7423 .elem => |src_idx| {
7307 try f.writeCValue(writer, operand, .Other);7424 try f.writeCValue(w, operand, .Other);
7308 try writer.writeByte('[');7425 try w.writeByte('[');
7309 try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);7426 try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other);
7310 try writer.writeByte(']');7427 try w.writeByte(']');
7311 },7428 },
7312 .value => |val| try f.object.dg.renderValue(writer, .fromInterned(val), .Other),7429 .value => |val| try f.object.dg.renderValue(w, .fromInterned(val), .Other),
7313 }7430 }
7314 try writer.writeAll(";\n");7431 try w.writeAll(";\n");
7315 }7432 }
73167433
7317 return local;7434 return local;
...@@ -7328,30 +7445,31 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7328,30 +7445,31 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
7328 const inst_ty = unwrapped.result_ty;7445 const inst_ty = unwrapped.result_ty;
7329 const elem_ty = inst_ty.childType(zcu);7446 const elem_ty = inst_ty.childType(zcu);
73307447
7331 const writer = f.object.writer();7448 const w = &f.object.code.writer;
7332 const local = try f.allocLocal(inst, inst_ty);7449 const local = try f.allocLocal(inst, inst_ty);
7333 try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands7450 try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands
7334 for (mask, 0..) |mask_elem, out_idx| {7451 for (mask, 0..) |mask_elem, out_idx| {
7335 try f.writeCValue(writer, local, .Other);7452 try f.writeCValue(w, local, .Other);
7336 try writer.writeByte('[');7453 try w.writeByte('[');
7337 try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other);7454 try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other);
7338 try writer.writeAll("] = ");7455 try w.writeAll("] = ");
7339 switch (mask_elem.unwrap()) {7456 switch (mask_elem.unwrap()) {
7340 .a_elem => |src_idx| {7457 .a_elem => |src_idx| {
7341 try f.writeCValue(writer, operand_a, .Other);7458 try f.writeCValue(w, operand_a, .Other);
7342 try writer.writeByte('[');7459 try w.writeByte('[');
7343 try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);7460 try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other);
7344 try writer.writeByte(']');7461 try w.writeByte(']');
7345 },7462 },
7346 .b_elem => |src_idx| {7463 .b_elem => |src_idx| {
7347 try f.writeCValue(writer, operand_b, .Other);7464 try f.writeCValue(w, operand_b, .Other);
7348 try writer.writeByte('[');7465 try w.writeByte('[');
7349 try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);7466 try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other);
7350 try writer.writeByte(']');7467 try w.writeByte(']');
7351 },7468 },
7352 .undef => try f.object.dg.renderUndefValue(writer, elem_ty, .Other),7469 .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other),
7353 }7470 }
7354 try writer.writeAll(";\n");7471 try w.writeByte(';');
7472 try f.object.newline();
7355 }7473 }
73567474
7357 return local;7475 return local;
...@@ -7366,7 +7484,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7366,7 +7484,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7366 const operand = try f.resolveInst(reduce.operand);7484 const operand = try f.resolveInst(reduce.operand);
7367 try reap(f, inst, &.{reduce.operand});7485 try reap(f, inst, &.{reduce.operand});
7368 const operand_ty = f.typeOf(reduce.operand);7486 const operand_ty = f.typeOf(reduce.operand);
7369 const writer = f.object.writer();7487 const w = &f.object.code.writer;
73707488
7371 const use_operator = scalar_ty.bitSize(zcu) <= 64;7489 const use_operator = scalar_ty.bitSize(zcu) <= 64;
7372 const op: union(enum) {7490 const op: union(enum) {
...@@ -7413,10 +7531,10 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7413,10 +7531,10 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7413 // }7531 // }
74147532
7415 const accum = try f.allocLocal(inst, scalar_ty);7533 const accum = try f.allocLocal(inst, scalar_ty);
7416 try f.writeCValue(writer, accum, .Other);7534 try f.writeCValue(w, accum, .Other);
7417 try writer.writeAll(" = ");7535 try w.writeAll(" = ");
74187536
7419 try f.object.dg.renderValue(writer, switch (reduce.operation) {7537 try f.object.dg.renderValue(w, switch (reduce.operation) {
7420 .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {7538 .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
7421 .bool => Value.false,7539 .bool => Value.false,
7422 .int => try pt.intValue(scalar_ty, 0),7540 .int => try pt.intValue(scalar_ty, 0),
...@@ -7453,42 +7571,44 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7453,42 +7571,44 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7453 else => unreachable,7571 else => unreachable,
7454 },7572 },
7455 }, .Other);7573 }, .Other);
7456 try writer.writeAll(";\n");7574 try w.writeByte(';');
7575 try f.object.newline();
74577576
7458 const v = try Vectorize.start(f, inst, writer, operand_ty);7577 const v = try Vectorize.start(f, inst, w, operand_ty);
7459 try f.writeCValue(writer, accum, .Other);7578 try f.writeCValue(w, accum, .Other);
7460 switch (op) {7579 switch (op) {
7461 .builtin => |func| {7580 .builtin => |func| {
7462 try writer.print(" = zig_{s}_", .{func.operation});7581 try w.print(" = zig_{s}_", .{func.operation});
7463 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);7582 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
7464 try writer.writeByte('(');7583 try w.writeByte('(');
7465 try f.writeCValue(writer, accum, .FunctionArgument);7584 try f.writeCValue(w, accum, .FunctionArgument);
7466 try writer.writeAll(", ");7585 try w.writeAll(", ");
7467 try f.writeCValue(writer, operand, .Other);7586 try f.writeCValue(w, operand, .Other);
7468 try v.elem(f, writer);7587 try v.elem(f, w);
7469 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, func.info);7588 try f.object.dg.renderBuiltinInfo(w, scalar_ty, func.info);
7470 try writer.writeByte(')');7589 try w.writeByte(')');
7471 },7590 },
7472 .infix => |ass| {7591 .infix => |ass| {
7473 try writer.writeAll(ass);7592 try w.writeAll(ass);
7474 try f.writeCValue(writer, operand, .Other);7593 try f.writeCValue(w, operand, .Other);
7475 try v.elem(f, writer);7594 try v.elem(f, w);
7476 },7595 },
7477 .ternary => |cmp| {7596 .ternary => |cmp| {
7478 try writer.writeAll(" = ");7597 try w.writeAll(" = ");
7479 try f.writeCValue(writer, accum, .Other);7598 try f.writeCValue(w, accum, .Other);
7480 try writer.writeAll(cmp);7599 try w.writeAll(cmp);
7481 try f.writeCValue(writer, operand, .Other);7600 try f.writeCValue(w, operand, .Other);
7482 try v.elem(f, writer);7601 try v.elem(f, w);
7483 try writer.writeAll(" ? ");7602 try w.writeAll(" ? ");
7484 try f.writeCValue(writer, accum, .Other);7603 try f.writeCValue(w, accum, .Other);
7485 try writer.writeAll(" : ");7604 try w.writeAll(" : ");
7486 try f.writeCValue(writer, operand, .Other);7605 try f.writeCValue(w, operand, .Other);
7487 try v.elem(f, writer);7606 try v.elem(f, w);
7488 },7607 },
7489 }7608 }
7490 try writer.writeAll(";\n");7609 try w.writeByte(';');
7491 try v.end(f, inst, writer);7610 try f.object.newline();
7611 try v.end(f, inst, w);
74927612
7493 return accum;7613 return accum;
7494}7614}
...@@ -7514,7 +7634,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7514,7 +7634,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7514 }7634 }
7515 }7635 }
75167636
7517 const writer = f.object.writer();7637 const w = &f.object.code.writer;
7518 const local = try f.allocLocal(inst, inst_ty);7638 const local = try f.allocLocal(inst, inst_ty);
7519 switch (ip.indexToKey(inst_ty.toIntern())) {7639 switch (ip.indexToKey(inst_ty.toIntern())) {
7520 inline .array_type, .vector_type => |info, tag| {7640 inline .array_type, .vector_type => |info, tag| {
...@@ -7522,20 +7642,20 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7522,20 +7642,20 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7522 .ctype = try f.ctypeFromType(.fromInterned(info.child), .complete),7642 .ctype = try f.ctypeFromType(.fromInterned(info.child), .complete),
7523 };7643 };
7524 for (resolved_elements, 0..) |element, i| {7644 for (resolved_elements, 0..) |element, i| {
7525 try a.restart(f, writer);7645 try a.restart(f, w);
7526 try f.writeCValue(writer, local, .Other);7646 try f.writeCValue(w, local, .Other);
7527 try writer.print("[{d}]", .{i});7647 try w.print("[{d}]", .{i});
7528 try a.assign(f, writer);7648 try a.assign(f, w);
7529 try f.writeCValue(writer, element, .Other);7649 try f.writeCValue(w, element, .Other);
7530 try a.end(f, writer);7650 try a.end(f, w);
7531 }7651 }
7532 if (tag == .array_type and info.sentinel != .none) {7652 if (tag == .array_type and info.sentinel != .none) {
7533 try a.restart(f, writer);7653 try a.restart(f, w);
7534 try f.writeCValue(writer, local, .Other);7654 try f.writeCValue(w, local, .Other);
7535 try writer.print("[{d}]", .{info.len});7655 try w.print("[{d}]", .{info.len});
7536 try a.assign(f, writer);7656 try a.assign(f, w);
7537 try f.object.dg.renderValue(writer, Value.fromInterned(info.sentinel), .Other);7657 try f.object.dg.renderValue(w, Value.fromInterned(info.sentinel), .Other);
7538 try a.end(f, writer);7658 try a.end(f, w);
7539 }7659 }
7540 },7660 },
7541 .struct_type => {7661 .struct_type => {
...@@ -7547,19 +7667,19 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7547,19 +7667,19 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7547 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);7667 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
7548 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;7668 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
75497669
7550 const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));7670 const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete));
7551 try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|7671 try f.writeCValueMember(w, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
7552 .{ .identifier = field_name.toSlice(ip) }7672 .{ .identifier = field_name.toSlice(ip) }
7553 else7673 else
7554 .{ .field = field_index });7674 .{ .field = field_index });
7555 try a.assign(f, writer);7675 try a.assign(f, w);
7556 try f.writeCValue(writer, resolved_elements[field_index], .Other);7676 try f.writeCValue(w, resolved_elements[field_index], .Other);
7557 try a.end(f, writer);7677 try a.end(f, w);
7558 }7678 }
7559 },7679 },
7560 .@"packed" => {7680 .@"packed" => {
7561 try f.writeCValue(writer, local, .Other);7681 try f.writeCValue(w, local, .Other);
7562 try writer.writeAll(" = ");7682 try w.writeAll(" = ");
75637683
7564 const backing_int_ty: Type = .fromInterned(loaded_struct.backingIntTypeUnordered(ip));7684 const backing_int_ty: Type = .fromInterned(loaded_struct.backingIntTypeUnordered(ip));
7565 const int_info = backing_int_ty.intInfo(zcu);7685 const int_info = backing_int_ty.intInfo(zcu);
...@@ -7575,9 +7695,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7575,9 +7695,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7575 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;7695 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
75767696
7577 if (!empty) {7697 if (!empty) {
7578 try writer.writeAll("zig_or_");7698 try w.writeAll("zig_or_");
7579 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);7699 try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty);
7580 try writer.writeByte('(');7700 try w.writeByte('(');
7581 }7701 }
7582 empty = false;7702 empty = false;
7583 }7703 }
...@@ -7587,57 +7707,58 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7587,57 +7707,58 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7587 const field_ty = inst_ty.fieldType(field_index, zcu);7707 const field_ty = inst_ty.fieldType(field_index, zcu);
7588 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;7708 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
75897709
7590 if (!empty) try writer.writeAll(", ");7710 if (!empty) try w.writeAll(", ");
7591 // TODO: Skip this entire shift if val is 0?7711 // TODO: Skip this entire shift if val is 0?
7592 try writer.writeAll("zig_shlw_");7712 try w.writeAll("zig_shlw_");
7593 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);7713 try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty);
7594 try writer.writeByte('(');7714 try w.writeByte('(');
75957715
7596 if (field_ty.isAbiInt(zcu)) {7716 if (field_ty.isAbiInt(zcu)) {
7597 try writer.writeAll("zig_and_");7717 try w.writeAll("zig_and_");
7598 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);7718 try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty);
7599 try writer.writeByte('(');7719 try w.writeByte('(');
7600 }7720 }
76017721
7602 if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) {7722 if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) {
7603 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);7723 try f.renderIntCast(w, inst_ty, element, .{}, field_ty, .FunctionArgument);
7604 } else {7724 } else {
7605 try writer.writeByte('(');7725 try w.writeByte('(');
7606 try f.renderType(writer, inst_ty);7726 try f.renderType(w, inst_ty);
7607 try writer.writeByte(')');7727 try w.writeByte(')');
7608 if (field_ty.isPtrAtRuntime(zcu)) {7728 if (field_ty.isPtrAtRuntime(zcu)) {
7609 try writer.writeByte('(');7729 try w.writeByte('(');
7610 try f.renderType(writer, switch (int_info.signedness) {7730 try f.renderType(w, switch (int_info.signedness) {
7611 .unsigned => .usize,7731 .unsigned => .usize,
7612 .signed => .isize,7732 .signed => .isize,
7613 });7733 });
7614 try writer.writeByte(')');7734 try w.writeByte(')');
7615 }7735 }
7616 try f.writeCValue(writer, element, .Other);7736 try f.writeCValue(w, element, .Other);
7617 }7737 }
76187738
7619 if (field_ty.isAbiInt(zcu)) {7739 if (field_ty.isAbiInt(zcu)) {
7620 try writer.writeAll(", ");7740 try w.writeAll(", ");
7621 const field_int_info = field_ty.intInfo(zcu);7741 const field_int_info = field_ty.intInfo(zcu);
7622 const field_mask = if (int_info.signedness == .signed and int_info.bits == field_int_info.bits)7742 const field_mask = if (int_info.signedness == .signed and int_info.bits == field_int_info.bits)
7623 try pt.intValue(backing_int_ty, -1)7743 try pt.intValue(backing_int_ty, -1)
7624 else7744 else
7625 try (try pt.intType(.unsigned, field_int_info.bits)).maxIntScalar(pt, backing_int_ty);7745 try (try pt.intType(.unsigned, field_int_info.bits)).maxIntScalar(pt, backing_int_ty);
7626 try f.object.dg.renderValue(writer, field_mask, .FunctionArgument);7746 try f.object.dg.renderValue(w, field_mask, .FunctionArgument);
7627 try writer.writeByte(')');7747 try w.writeByte(')');
7628 }7748 }
76297749
7630 try writer.print(", {}", .{7750 try w.print(", {f}", .{
7631 try f.fmtIntLiteral(try pt.intValue(bit_offset_ty, bit_offset)),7751 try f.fmtIntLiteralDec(try pt.intValue(bit_offset_ty, bit_offset)),
7632 });7752 });
7633 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);7753 try f.object.dg.renderBuiltinInfo(w, inst_ty, .bits);
7634 try writer.writeByte(')');7754 try w.writeByte(')');
7635 if (!empty) try writer.writeByte(')');7755 if (!empty) try w.writeByte(')');
76367756
7637 bit_offset += field_ty.bitSize(zcu);7757 bit_offset += field_ty.bitSize(zcu);
7638 empty = false;7758 empty = false;
7639 }7759 }
7640 try writer.writeAll(";\n");7760 try w.writeByte(';');
7761 try f.object.newline();
7641 },7762 },
7642 }7763 }
7643 },7764 },
...@@ -7646,11 +7767,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7646,11 +7767,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7646 const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]);7767 const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]);
7647 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;7768 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
76487769
7649 const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));7770 const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete));
7650 try f.writeCValueMember(writer, local, .{ .field = field_index });7771 try f.writeCValueMember(w, local, .{ .field = field_index });
7651 try a.assign(f, writer);7772 try a.assign(f, w);
7652 try f.writeCValue(writer, resolved_elements[field_index], .Other);7773 try f.writeCValue(w, resolved_elements[field_index], .Other);
7653 try a.end(f, writer);7774 try a.end(f, w);
7654 },7775 },
7655 else => unreachable,7776 else => unreachable,
7656 }7777 }
...@@ -7672,7 +7793,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7672,7 +7793,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
7672 const payload = try f.resolveInst(extra.init);7793 const payload = try f.resolveInst(extra.init);
7673 try reap(f, inst, &.{extra.init});7794 try reap(f, inst, &.{extra.init});
76747795
7675 const writer = f.object.writer();7796 const w = &f.object.code.writer;
7676 const local = try f.allocLocal(inst, union_ty);7797 const local = try f.allocLocal(inst, union_ty);
7677 if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload);7798 if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload);
76787799
...@@ -7682,20 +7803,20 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7682,20 +7803,20 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
7682 const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;7803 const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
7683 const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);7804 const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);
76847805
7685 const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete));7806 const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));
7686 try f.writeCValueMember(writer, local, .{ .identifier = "tag" });7807 try f.writeCValueMember(w, local, .{ .identifier = "tag" });
7687 try a.assign(f, writer);7808 try a.assign(f, w);
7688 try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, pt))});7809 try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))});
7689 try a.end(f, writer);7810 try a.end(f, w);
7690 }7811 }
7691 break :field .{ .payload_identifier = field_name.toSlice(ip) };7812 break :field .{ .payload_identifier = field_name.toSlice(ip) };
7692 } else .{ .identifier = field_name.toSlice(ip) };7813 } else .{ .identifier = field_name.toSlice(ip) };
76937814
7694 const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));7815 const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
7695 try f.writeCValueMember(writer, local, field);7816 try f.writeCValueMember(w, local, field);
7696 try a.assign(f, writer);7817 try a.assign(f, w);
7697 try f.writeCValue(writer, payload, .Other);7818 try f.writeCValue(w, payload, .Other);
7698 try a.end(f, writer);7819 try a.end(f, w);
7699 return local;7820 return local;
7700}7821}
77017822
...@@ -7708,15 +7829,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7708,15 +7829,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
7708 const ptr = try f.resolveInst(prefetch.ptr);7829 const ptr = try f.resolveInst(prefetch.ptr);
7709 try reap(f, inst, &.{prefetch.ptr});7830 try reap(f, inst, &.{prefetch.ptr});
77107831
7711 const writer = f.object.writer();7832 const w = &f.object.code.writer;
7712 switch (prefetch.cache) {7833 switch (prefetch.cache) {
7713 .data => {7834 .data => {
7714 try writer.writeAll("zig_prefetch(");7835 try w.writeAll("zig_prefetch(");
7715 if (ptr_ty.isSlice(zcu))7836 if (ptr_ty.isSlice(zcu))
7716 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" })7837 try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" })
7717 else7838 else
7718 try f.writeCValue(writer, ptr, .FunctionArgument);7839 try f.writeCValue(w, ptr, .FunctionArgument);
7719 try writer.print(", {d}, {d});\n", .{ @intFromEnum(prefetch.rw), prefetch.locality });7840 try w.print(", {d}, {d});", .{ @intFromEnum(prefetch.rw), prefetch.locality });
7841 try f.object.newline();
7720 },7842 },
7721 // The available prefetch intrinsics do not accept a cache argument; only7843 // The available prefetch intrinsics do not accept a cache argument; only
7722 // address, rw, and locality.7844 // address, rw, and locality.
...@@ -7729,13 +7851,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7729,13 +7851,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
7729fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {7851fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
7730 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;7852 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
77317853
7732 const writer = f.object.writer();7854 const w = &f.object.code.writer;
7733 const inst_ty = f.typeOfIndex(inst);7855 const inst_ty = f.typeOfIndex(inst);
7734 const local = try f.allocLocal(inst, inst_ty);7856 const local = try f.allocLocal(inst, inst_ty);
7735 try f.writeCValue(writer, local, .Other);7857 try f.writeCValue(w, local, .Other);
77367858
7737 try writer.writeAll(" = ");7859 try w.writeAll(" = ");
7738 try writer.print("zig_wasm_memory_size({d});\n", .{pl_op.payload});7860 try w.print("zig_wasm_memory_size({d});", .{pl_op.payload});
7861 try f.object.newline();
77397862
7740 return local;7863 return local;
7741}7864}
...@@ -7743,17 +7866,18 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7743,17 +7866,18 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
7743fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {7866fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
7744 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;7867 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
77457868
7746 const writer = f.object.writer();7869 const w = &f.object.code.writer;
7747 const inst_ty = f.typeOfIndex(inst);7870 const inst_ty = f.typeOfIndex(inst);
7748 const operand = try f.resolveInst(pl_op.operand);7871 const operand = try f.resolveInst(pl_op.operand);
7749 try reap(f, inst, &.{pl_op.operand});7872 try reap(f, inst, &.{pl_op.operand});
7750 const local = try f.allocLocal(inst, inst_ty);7873 const local = try f.allocLocal(inst, inst_ty);
7751 try f.writeCValue(writer, local, .Other);7874 try f.writeCValue(w, local, .Other);
77527875
7753 try writer.writeAll(" = ");7876 try w.writeAll(" = ");
7754 try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});7877 try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
7755 try f.writeCValue(writer, operand, .FunctionArgument);7878 try f.writeCValue(w, operand, .FunctionArgument);
7756 try writer.writeAll(");\n");7879 try w.writeAll(");");
7880 try f.object.newline();
7757 return local;7881 return local;
7758}7882}
77597883
...@@ -7771,36 +7895,38 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7771,36 +7895,38 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7771 const inst_ty = f.typeOfIndex(inst);7895 const inst_ty = f.typeOfIndex(inst);
7772 const inst_scalar_ty = inst_ty.scalarType(zcu);7896 const inst_scalar_ty = inst_ty.scalarType(zcu);
77737897
7774 const writer = f.object.writer();7898 const w = &f.object.code.writer;
7775 const local = try f.allocLocal(inst, inst_ty);7899 const local = try f.allocLocal(inst, inst_ty);
7776 const v = try Vectorize.start(f, inst, writer, inst_ty);7900 const v = try Vectorize.start(f, inst, w, inst_ty);
7777 try f.writeCValue(writer, local, .Other);7901 try f.writeCValue(w, local, .Other);
7778 try v.elem(f, writer);7902 try v.elem(f, w);
7779 try writer.writeAll(" = zig_fma_");7903 try w.writeAll(" = zig_fma_");
7780 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);7904 try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
7781 try writer.writeByte('(');7905 try w.writeByte('(');
7782 try f.writeCValue(writer, mulend1, .FunctionArgument);7906 try f.writeCValue(w, mulend1, .FunctionArgument);
7783 try v.elem(f, writer);7907 try v.elem(f, w);
7784 try writer.writeAll(", ");7908 try w.writeAll(", ");
7785 try f.writeCValue(writer, mulend2, .FunctionArgument);7909 try f.writeCValue(w, mulend2, .FunctionArgument);
7786 try v.elem(f, writer);7910 try v.elem(f, w);
7787 try writer.writeAll(", ");7911 try w.writeAll(", ");
7788 try f.writeCValue(writer, addend, .FunctionArgument);7912 try f.writeCValue(w, addend, .FunctionArgument);
7789 try v.elem(f, writer);7913 try v.elem(f, w);
7790 try writer.writeAll(");\n");7914 try w.writeAll(");");
7791 try v.end(f, inst, writer);7915 try f.object.newline();
7916 try v.end(f, inst, w);
77927917
7793 return local;7918 return local;
7794}7919}
77957920
7796fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue {7921fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue {
7797 const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;7922 const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;
7798 const writer = f.object.writer();7923 const w = &f.object.code.writer;
7799 const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty));7924 const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty));
7800 try f.writeCValue(writer, local, .Other);7925 try f.writeCValue(w, local, .Other);
7801 try writer.writeAll(" = ");7926 try w.writeAll(" = ");
7802 try f.object.dg.renderNav(writer, ty_nav.nav, .Other);7927 try f.object.dg.renderNav(w, ty_nav.nav, .Other);
7803 try writer.writeAll(";\n");7928 try w.writeByte(';');
7929 try f.object.newline();
7804 return local;7930 return local;
7805}7931}
78067932
...@@ -7812,15 +7938,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7812,15 +7938,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7812 const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function;7938 const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function;
7813 assert(function_info.varargs);7939 assert(function_info.varargs);
78147940
7815 const writer = f.object.writer();7941 const w = &f.object.code.writer;
7816 const local = try f.allocLocal(inst, inst_ty);7942 const local = try f.allocLocal(inst, inst_ty);
7817 try writer.writeAll("va_start(*(va_list *)&");7943 try w.writeAll("va_start(*(va_list *)&");
7818 try f.writeCValue(writer, local, .Other);7944 try f.writeCValue(w, local, .Other);
7819 if (function_info.param_ctypes.len > 0) {7945 if (function_info.param_ctypes.len > 0) {
7820 try writer.writeAll(", ");7946 try w.writeAll(", ");
7821 try f.writeCValue(writer, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);7947 try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);
7822 }7948 }
7823 try writer.writeAll(");\n");7949 try w.writeAll(");");
7950 try f.object.newline();
7824 return local;7951 return local;
7825}7952}
78267953
...@@ -7831,14 +7958,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7831,14 +7958,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
7831 const va_list = try f.resolveInst(ty_op.operand);7958 const va_list = try f.resolveInst(ty_op.operand);
7832 try reap(f, inst, &.{ty_op.operand});7959 try reap(f, inst, &.{ty_op.operand});
78337960
7834 const writer = f.object.writer();7961 const w = &f.object.code.writer;
7835 const local = try f.allocLocal(inst, inst_ty);7962 const local = try f.allocLocal(inst, inst_ty);
7836 try f.writeCValue(writer, local, .Other);7963 try f.writeCValue(w, local, .Other);
7837 try writer.writeAll(" = va_arg(*(va_list *)");7964 try w.writeAll(" = va_arg(*(va_list *)");
7838 try f.writeCValue(writer, va_list, .Other);7965 try f.writeCValue(w, va_list, .Other);
7839 try writer.writeAll(", ");7966 try w.writeAll(", ");
7840 try f.renderType(writer, ty_op.ty.toType());7967 try f.renderType(w, ty_op.ty.toType());
7841 try writer.writeAll(");\n");7968 try w.writeAll(");");
7969 try f.object.newline();
7842 return local;7970 return local;
7843}7971}
78447972
...@@ -7848,10 +7976,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7848,10 +7976,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
7848 const va_list = try f.resolveInst(un_op);7976 const va_list = try f.resolveInst(un_op);
7849 try reap(f, inst, &.{un_op});7977 try reap(f, inst, &.{un_op});
78507978
7851 const writer = f.object.writer();7979 const w = &f.object.code.writer;
7852 try writer.writeAll("va_end(*(va_list *)");7980 try w.writeAll("va_end(*(va_list *)");
7853 try f.writeCValue(writer, va_list, .Other);7981 try f.writeCValue(w, va_list, .Other);
7854 try writer.writeAll(");\n");7982 try w.writeAll(");");
7983 try f.object.newline();
7855 return .none;7984 return .none;
7856}7985}
78577986
...@@ -7862,13 +7991,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7862,13 +7991,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
7862 const va_list = try f.resolveInst(ty_op.operand);7991 const va_list = try f.resolveInst(ty_op.operand);
7863 try reap(f, inst, &.{ty_op.operand});7992 try reap(f, inst, &.{ty_op.operand});
78647993
7865 const writer = f.object.writer();7994 const w = &f.object.code.writer;
7866 const local = try f.allocLocal(inst, inst_ty);7995 const local = try f.allocLocal(inst, inst_ty);
7867 try writer.writeAll("va_copy(*(va_list *)&");7996 try w.writeAll("va_copy(*(va_list *)&");
7868 try f.writeCValue(writer, local, .Other);7997 try f.writeCValue(w, local, .Other);
7869 try writer.writeAll(", *(va_list *)");7998 try w.writeAll(", *(va_list *)");
7870 try f.writeCValue(writer, va_list, .Other);7999 try f.writeCValue(w, va_list, .Other);
7871 try writer.writeAll(");\n");8000 try w.writeAll(");");
8001 try f.object.newline();
7872 return local;8002 return local;
7873}8003}
78748004
...@@ -7883,7 +8013,7 @@ fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {...@@ -7883,7 +8013,7 @@ fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
7883 };8013 };
7884}8014}
78858015
7886fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void {8016fn writeMemoryOrder(w: *Writer, order: std.builtin.AtomicOrder) !void {
7887 return w.writeAll(toMemoryOrder(order));8017 return w.writeAll(toMemoryOrder(order));
7888}8018}
78898019
...@@ -7970,93 +8100,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {...@@ -7970,93 +8100,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {
7970 };8100 };
7971}8101}
79728102
7973const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error);
7974
7975fn arrayListWriter(list: *std.ArrayList(u8)) ArrayListWriter {
7976 return .{ .context = .{
7977 .context = list,
7978 .writeFn = struct {
7979 fn write(context: *const anyopaque, bytes: []const u8) anyerror!usize {
7980 const l: *std.ArrayList(u8) = @alignCast(@constCast(@ptrCast(context)));
7981 return l.writer().write(bytes);
7982 }
7983 }.write,
7984 } };
7985}
7986
7987fn IndentWriter(comptime UnderlyingWriter: type) type {
7988 return struct {
7989 const Self = @This();
7990 pub const Error = UnderlyingWriter.Error;
7991 pub const Writer = ErrorOnlyGenericWriter(Error);
7992
7993 pub const indent_delta = 1;
7994
7995 underlying_writer: UnderlyingWriter,
7996 indent_count: usize = 0,
7997 current_line_empty: bool = true,
7998
7999 pub fn writer(self: *Self) Writer {
8000 return .{ .context = .{
8001 .context = self,
8002 .writeFn = writeAny,
8003 } };
8004 }
8005
8006 pub fn write(self: *Self, bytes: []const u8) Error!usize {
8007 if (bytes.len == 0) return 0;
8008
8009 const current_indent = self.indent_count * Self.indent_delta;
8010 if (self.current_line_empty and current_indent > 0) {
8011 try self.underlying_writer.writeByteNTimes(' ', current_indent);
8012 }
8013 self.current_line_empty = false;
8014
8015 return self.writeNoIndent(bytes);
8016 }
8017
8018 fn writeAny(context: *const anyopaque, bytes: []const u8) anyerror!usize {
8019 const self: *Self = @alignCast(@constCast(@ptrCast(context)));
8020 return self.write(bytes);
8021 }
8022
8023 pub fn insertNewline(self: *Self) Error!void {
8024 _ = try self.writeNoIndent("\n");
8025 }
8026
8027 pub fn pushIndent(self: *Self) void {
8028 self.indent_count += 1;
8029 }
8030
8031 pub fn popIndent(self: *Self) void {
8032 assert(self.indent_count != 0);
8033 self.indent_count -= 1;
8034 }
8035
8036 fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
8037 if (bytes.len == 0) return 0;
8038
8039 try self.underlying_writer.writeAll(bytes);
8040 if (bytes[bytes.len - 1] == '\n') {
8041 self.current_line_empty = true;
8042 }
8043 return bytes.len;
8044 }
8045 };
8046}
8047
8048/// A wrapper around `std.io.AnyWriter` that maintains a generic error set while
8049/// erasing the rest of the implementation. This is intended to avoid duplicate
8050/// generic instantiations for writer types which share the same error set, while
8051/// maintaining ease of error handling.
8052fn ErrorOnlyGenericWriter(comptime Error: type) type {
8053 return std.io.GenericWriter(std.io.AnyWriter, Error, struct {
8054 fn write(context: std.io.AnyWriter, bytes: []const u8) Error!usize {
8055 return @errorCast(context.write(bytes));
8056 }
8057 }.write);
8058}
8059
8060fn toCIntBits(zig_bits: u32) ?u32 {8103fn toCIntBits(zig_bits: u32) ?u32 {
8061 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {8104 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {
8062 if (zig_bits <= c_bits) {8105 if (zig_bits <= c_bits) {
...@@ -8111,7 +8154,12 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 {...@@ -8111,7 +8154,12 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 {
8111 };8154 };
8112}8155}
81138156
8114fn StringLiteral(comptime WriterType: type) type {8157const StringLiteral = struct {
8158 len: usize,
8159 cur_len: usize,
8160 w: *Writer,
8161 first: bool,
8162
8115 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,8163 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
8116 // regardless of the length of the string literal initializing it. Array initializer syntax is8164 // regardless of the length of the string literal initializing it. Array initializer syntax is
8117 // used instead.8165 // used instead.
...@@ -8123,99 +8171,116 @@ fn StringLiteral(comptime WriterType: type) type {...@@ -8123,99 +8171,116 @@ fn StringLiteral(comptime WriterType: type) type {
8123 const max_char_len = 4;8171 const max_char_len = 4;
8124 const max_literal_len = @min(16380 - max_char_len, 4095);8172 const max_literal_len = @min(16380 - max_char_len, 4095);
81258173
8126 return struct {8174 fn init(w: *Writer, len: usize) StringLiteral {
8127 len: u64,8175 return .{
8128 cur_len: u64 = 0,8176 .cur_len = 0,
8129 counting_writer: std.io.CountingWriter(WriterType),8177 .len = len,
81308178 .w = w,
8131 pub const Error = WriterType.Error;8179 .first = true,
81328180 };
8133 const Self = @This();8181 }
81348182
8135 pub fn start(self: *Self) Error!void {8183 pub fn start(sl: *StringLiteral) Writer.Error!void {
8136 const writer = self.counting_writer.writer();8184 if (sl.len <= max_string_initializer_len) {
8137 if (self.len <= max_string_initializer_len) {8185 try sl.w.writeByte('\"');
8138 try writer.writeByte('\"');8186 } else {
8139 } else {8187 try sl.w.writeByte('{');
8140 try writer.writeByte('{');
8141 }
8142 }8188 }
8189 }
81438190
8144 pub fn end(self: *Self) Error!void {8191 pub fn end(sl: *StringLiteral) Writer.Error!void {
8145 const writer = self.counting_writer.writer();8192 if (sl.len <= max_string_initializer_len) {
8146 if (self.len <= max_string_initializer_len) {8193 try sl.w.writeByte('\"');
8147 try writer.writeByte('\"');8194 } else {
8148 } else {8195 try sl.w.writeByte('}');
8149 try writer.writeByte('}');
8150 }
8151 }8196 }
8197 }
81528198
8153 fn writeStringLiteralChar(writer: anytype, c: u8) !void {8199 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) Writer.Error!usize {
8154 switch (c) {8200 const w = sl.w;
8155 7 => try writer.writeAll("\\a"),8201 switch (c) {
8156 8 => try writer.writeAll("\\b"),8202 7 => {
8157 '\t' => try writer.writeAll("\\t"),8203 try w.writeAll("\\a");
8158 '\n' => try writer.writeAll("\\n"),8204 return 2;
8159 11 => try writer.writeAll("\\v"),8205 },
8160 12 => try writer.writeAll("\\f"),8206 8 => {
8161 '\r' => try writer.writeAll("\\r"),8207 try w.writeAll("\\b");
8162 '"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}),8208 return 2;
8163 else => switch (c) {8209 },
8164 ' '...'~' => try writer.writeByte(c),8210 '\t' => {
8165 else => try writer.print("\\{o:0>3}", .{c}),8211 try w.writeAll("\\t");
8166 },8212 return 2;
8167 }8213 },
8214 '\n' => {
8215 try w.writeAll("\\n");
8216 return 2;
8217 },
8218 11 => {
8219 try w.writeAll("\\v");
8220 return 2;
8221 },
8222 12 => {
8223 try w.writeAll("\\f");
8224 return 2;
8225 },
8226 '\r' => {
8227 try w.writeAll("\\r");
8228 return 2;
8229 },
8230 '"', '\'', '?', '\\' => {
8231 try w.print("\\{c}", .{c});
8232 return 2;
8233 },
8234 ' '...'!', '#'...'&', '('...'>', '@'...'[', ']'...'~' => {
8235 try w.writeByte(c);
8236 return 1;
8237 },
8238 else => {
8239 var buf: [4]u8 = undefined;
8240 const printed = std.fmt.bufPrint(&buf, "\\{o:0>3}", .{c}) catch unreachable;
8241 try w.writeAll(printed);
8242 return printed.len;
8243 },
8168 }8244 }
8245 }
81698246
8170 pub fn writeChar(self: *Self, c: u8) Error!void {8247 pub fn writeChar(sl: *StringLiteral, c: u8) Writer.Error!void {
8171 const writer = self.counting_writer.writer();8248 if (sl.len <= max_string_initializer_len) {
8172 if (self.len <= max_string_initializer_len) {8249 if (sl.cur_len == 0 and !sl.first) try sl.w.writeAll("\"\"");
8173 if (self.cur_len == 0 and self.counting_writer.bytes_written > 1)
8174 try writer.writeAll("\"\"");
8175
8176 const len = self.counting_writer.bytes_written;
8177 try writeStringLiteralChar(writer, c);
81788250
8179 const char_length = self.counting_writer.bytes_written - len;8251 const char_len = try sl.writeStringLiteralChar(c);
8180 assert(char_length <= max_char_len);8252 assert(char_len <= max_char_len);
8181 self.cur_len += char_length;8253 sl.cur_len += char_len;
81828254
8183 if (self.cur_len >= max_literal_len) self.cur_len = 0;8255 if (sl.cur_len >= max_literal_len) {
8184 } else {8256 sl.cur_len = 0;
8185 if (self.counting_writer.bytes_written > 1) try writer.writeByte(',');8257 sl.first = false;
8186 try writer.print("'\\x{x}'", .{c});
8187 }8258 }
8259 } else {
8260 if (!sl.first) try sl.w.writeByte(',');
8261 var buf: [6]u8 = undefined;
8262 const printed = std.fmt.bufPrint(&buf, "'\\x{x}'", .{c}) catch unreachable;
8263 try sl.w.writeAll(printed);
8264 sl.cur_len += printed.len;
8265 sl.first = false;
8188 }8266 }
8189 };8267 }
8190}8268};
8191
8192fn stringLiteral(
8193 child_stream: anytype,
8194 len: u64,
8195) StringLiteral(@TypeOf(child_stream)) {
8196 return .{
8197 .len = len,
8198 .counting_writer = std.io.countingWriter(child_stream),
8199 };
8200}
82018269
8202const FormatStringContext = struct { str: []const u8, sentinel: ?u8 };8270const FormatStringContext = struct {
8203fn formatStringLiteral(8271 str: []const u8,
8204 data: FormatStringContext,8272 sentinel: ?u8,
8205 comptime fmt: []const u8,8273};
8206 _: std.fmt.FormatOptions,
8207 writer: anytype,
8208) @TypeOf(writer).Error!void {
8209 if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt);
82108274
8211 var literal = stringLiteral(writer, data.str.len + @intFromBool(data.sentinel != null));8275fn formatStringLiteral(data: FormatStringContext, w: *std.io.Writer) std.io.Writer.Error!void {
8276 var literal: StringLiteral = .init(w, data.str.len + @intFromBool(data.sentinel != null));
8212 try literal.start();8277 try literal.start();
8213 for (data.str) |c| try literal.writeChar(c);8278 for (data.str) |c| try literal.writeChar(c);
8214 if (data.sentinel) |sentinel| if (sentinel != 0) try literal.writeChar(sentinel);8279 if (data.sentinel) |sentinel| if (sentinel != 0) try literal.writeChar(sentinel);
8215 try literal.end();8280 try literal.end();
8216}8281}
82178282
8218fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(formatStringLiteral) {8283fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(FormatStringContext, formatStringLiteral) {
8219 return .{ .data = .{ .str = str, .sentinel = sentinel } };8284 return .{ .data = .{ .str = str, .sentinel = sentinel } };
8220}8285}
82218286
...@@ -8231,13 +8296,10 @@ const FormatIntLiteralContext = struct {...@@ -8231,13 +8296,10 @@ const FormatIntLiteralContext = struct {
8231 kind: CType.Kind,8296 kind: CType.Kind,
8232 ctype: CType,8297 ctype: CType,
8233 val: Value,8298 val: Value,
8299 base: u8,
8300 case: std.fmt.Case,
8234};8301};
8235fn formatIntLiteral(8302fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Writer.Error!void {
8236 data: FormatIntLiteralContext,
8237 comptime fmt: []const u8,
8238 options: std.fmt.FormatOptions,
8239 writer: anytype,
8240) @TypeOf(writer).Error!void {
8241 const pt = data.dg.pt;8303 const pt = data.dg.pt;
8242 const zcu = pt.zcu;8304 const zcu = pt.zcu;
8243 const target = &data.dg.mod.resolved_target.result;8305 const target = &data.dg.mod.resolved_target.result;
...@@ -8262,7 +8324,7 @@ fn formatIntLiteral(...@@ -8262,7 +8324,7 @@ fn formatIntLiteral(
82628324
8263 var int_buf: Value.BigIntSpace = undefined;8325 var int_buf: Value.BigIntSpace = undefined;
8264 const int = if (data.val.isUndefDeep(zcu)) blk: {8326 const int = if (data.val.isUndefDeep(zcu)) blk: {
8265 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));8327 undef_limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)) catch return error.WriteFailed;
8266 @memset(undef_limbs, undefPattern(BigIntLimb));8328 @memset(undef_limbs, undefPattern(BigIntLimb));
82678329
8268 var undef_int = BigInt.Mutable{8330 var undef_int = BigInt.Mutable{
...@@ -8280,7 +8342,7 @@ fn formatIntLiteral(...@@ -8280,7 +8342,7 @@ fn formatIntLiteral(
8280 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();8342 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
82818343
8282 var wrap = BigInt.Mutable{8344 var wrap = BigInt.Mutable{
8283 .limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)),8345 .limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)) catch return error.WriteFailed,
8284 .len = undefined,8346 .len = undefined,
8285 .positive = undefined,8347 .positive = undefined,
8286 };8348 };
...@@ -8317,46 +8379,29 @@ fn formatIntLiteral(...@@ -8317,46 +8379,29 @@ fn formatIntLiteral(
8317 if (c_limb_info.count == 1) {8379 if (c_limb_info.count == 1) {
8318 if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or8380 if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or
8319 data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits))8381 data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits))
8320 return writer.print("{s}_{s}", .{8382 return w.print("{s}_{s}", .{
8321 data.ctype.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{8383 data.ctype.getStandardDefineAbbrev() orelse return w.print("zig_{s}Int_{c}{d}", .{
8322 if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits,8384 if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits,
8323 }),8385 }),
8324 if (int.positive) "MAX" else "MIN",8386 if (int.positive) "MAX" else "MIN",
8325 });8387 });
83268388
8327 if (!int.positive) try writer.writeByte('-');8389 if (!int.positive) try w.writeByte('-');
8328 try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool);8390 try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool);
83298391
8330 const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) {8392 switch (data.base) {
8331 0 => .{ .base = 10 },8393 2 => try w.writeAll("0b"),
8332 1 => switch (fmt[0]) {8394 8 => try w.writeByte('0'),
8333 'b' => style: {8395 10 => {},
8334 try writer.writeAll("0b");8396 16 => try w.writeAll("0x"),
8335 break :style .{ .base = 2 };8397 else => unreachable,
8336 },8398 }
8337 'o' => style: {8399 const string = int.abs().toStringAlloc(allocator, data.base, data.case) catch
8338 try writer.writeByte('0');8400 return error.WriteFailed;
8339 break :style .{ .base = 8 };
8340 },
8341 'd' => .{ .base = 10 },
8342 'x', 'X' => |base| style: {
8343 try writer.writeAll("0x");
8344 break :style .{ .base = 16, .case = switch (base) {
8345 'x' => .lower,
8346 'X' => .upper,
8347 else => unreachable,
8348 } };
8349 },
8350 else => @compileError("Invalid fmt: " ++ fmt),
8351 },
8352 else => @compileError("Invalid fmt: " ++ fmt),
8353 };
8354
8355 const string = try int.abs().toStringAlloc(allocator, style.base, style.case);
8356 defer allocator.free(string);8401 defer allocator.free(string);
8357 try writer.writeAll(string);8402 try w.writeAll(string);
8358 } else {8403 } else {
8359 try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool);8404 try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool);
8360 wrap.truncate(int, .unsigned, c_bits);8405 wrap.truncate(int, .unsigned, c_bits);
8361 @memset(wrap.limbs[wrap.len..], 0);8406 @memset(wrap.limbs[wrap.len..], 0);
8362 wrap.len = wrap.limbs.len;8407 wrap.len = wrap.limbs.len;
...@@ -8399,17 +8444,20 @@ fn formatIntLiteral(...@@ -8399,17 +8444,20 @@ fn formatIntLiteral(
8399 c_limb_ctype = c_limb_info.ctype;8444 c_limb_ctype = c_limb_info.ctype;
8400 }8445 }
84018446
8402 if (limb_offset > 0) try writer.writeAll(", ");8447 if (limb_offset > 0) try w.writeAll(", ");
8403 try formatIntLiteral(.{8448 try formatIntLiteral(.{
8404 .dg = data.dg,8449 .dg = data.dg,
8405 .int_info = c_limb_int_info,8450 .int_info = c_limb_int_info,
8406 .kind = data.kind,8451 .kind = data.kind,
8407 .ctype = c_limb_ctype,8452 .ctype = c_limb_ctype,
8408 .val = try pt.intValue_big(.comptime_int, c_limb_mut.toConst()),8453 .val = pt.intValue_big(.comptime_int, c_limb_mut.toConst()) catch
8409 }, fmt, options, writer);8454 return error.WriteFailed,
8455 .base = data.base,
8456 .case = data.case,
8457 }, w);
8410 }8458 }
8411 }8459 }
8412 try data.ctype.renderLiteralSuffix(writer, ctype_pool);8460 try data.ctype.renderLiteralSuffix(w, ctype_pool);
8413}8461}
84148462
8415const Materialize = struct {8463const Materialize = struct {
...@@ -8423,8 +8471,8 @@ const Materialize = struct {...@@ -8423,8 +8471,8 @@ const Materialize = struct {
8423 } };8471 } };
8424 }8472 }
84258473
8426 pub fn mat(self: Materialize, f: *Function, writer: anytype) !void {8474 pub fn mat(self: Materialize, f: *Function, w: *Writer) !void {
8427 try f.writeCValue(writer, self.local, .Other);8475 try f.writeCValue(w, self.local, .Other);
8428 }8476 }
84298477
8430 pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void {8478 pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void {
...@@ -8435,36 +8483,37 @@ const Materialize = struct {...@@ -8435,36 +8483,37 @@ const Materialize = struct {
8435const Assignment = struct {8483const Assignment = struct {
8436 ctype: CType,8484 ctype: CType,
84378485
8438 pub fn start(f: *Function, writer: anytype, ctype: CType) !Assignment {8486 pub fn start(f: *Function, w: *Writer, ctype: CType) !Assignment {
8439 const self: Assignment = .{ .ctype = ctype };8487 const self: Assignment = .{ .ctype = ctype };
8440 try self.restart(f, writer);8488 try self.restart(f, w);
8441 return self;8489 return self;
8442 }8490 }
84438491
8444 pub fn restart(self: Assignment, f: *Function, writer: anytype) !void {8492 pub fn restart(self: Assignment, f: *Function, w: *Writer) !void {
8445 switch (self.strategy(f)) {8493 switch (self.strategy(f)) {
8446 .assign => {},8494 .assign => {},
8447 .memcpy => try writer.writeAll("memcpy("),8495 .memcpy => try w.writeAll("memcpy("),
8448 }8496 }
8449 }8497 }
84508498
8451 pub fn assign(self: Assignment, f: *Function, writer: anytype) !void {8499 pub fn assign(self: Assignment, f: *Function, w: *Writer) !void {
8452 switch (self.strategy(f)) {8500 switch (self.strategy(f)) {
8453 .assign => try writer.writeAll(" = "),8501 .assign => try w.writeAll(" = "),
8454 .memcpy => try writer.writeAll(", "),8502 .memcpy => try w.writeAll(", "),
8455 }8503 }
8456 }8504 }
84578505
8458 pub fn end(self: Assignment, f: *Function, writer: anytype) !void {8506 pub fn end(self: Assignment, f: *Function, w: *Writer) !void {
8459 switch (self.strategy(f)) {8507 switch (self.strategy(f)) {
8460 .assign => {},8508 .assign => {},
8461 .memcpy => {8509 .memcpy => {
8462 try writer.writeAll(", sizeof(");8510 try w.writeAll(", sizeof(");
8463 try f.renderCType(writer, self.ctype);8511 try f.renderCType(w, self.ctype);
8464 try writer.writeAll("))");8512 try w.writeAll("))");
8465 },8513 },
8466 }8514 }
8467 try writer.writeAll(";\n");8515 try w.writeByte(';');
8516 try f.object.newline();
8468 }8517 }
84698518
8470 fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {8519 fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {
...@@ -8478,37 +8527,39 @@ const Assignment = struct {...@@ -8478,37 +8527,39 @@ const Assignment = struct {
8478const Vectorize = struct {8527const Vectorize = struct {
8479 index: CValue = .none,8528 index: CValue = .none,
84808529
8481 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {8530 pub fn start(f: *Function, inst: Air.Inst.Index, w: *Writer, ty: Type) !Vectorize {
8482 const pt = f.object.dg.pt;8531 const pt = f.object.dg.pt;
8483 const zcu = pt.zcu;8532 const zcu = pt.zcu;
8484 return if (ty.zigTypeTag(zcu) == .vector) index: {8533 return if (ty.zigTypeTag(zcu) == .vector) index: {
8485 const local = try f.allocLocal(inst, .usize);8534 const local = try f.allocLocal(inst, .usize);
84868535
8487 try writer.writeAll("for (");8536 try w.writeAll("for (");
8488 try f.writeCValue(writer, local, .Other);8537 try f.writeCValue(w, local, .Other);
8489 try writer.print(" = {d}; ", .{try f.fmtIntLiteral(.zero_usize)});8538 try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)});
8490 try f.writeCValue(writer, local, .Other);8539 try f.writeCValue(w, local, .Other);
8491 try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, ty.vectorLen(zcu)))});8540 try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))});
8492 try f.writeCValue(writer, local, .Other);8541 try f.writeCValue(w, local, .Other);
8493 try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(.one_usize)});8542 try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)});
8494 f.object.indent_writer.pushIndent();8543 f.object.indent();
8544 try f.object.newline();
84958545
8496 break :index .{ .index = local };8546 break :index .{ .index = local };
8497 } else .{};8547 } else .{};
8498 }8548 }
84998549
8500 pub fn elem(self: Vectorize, f: *Function, writer: anytype) !void {8550 pub fn elem(self: Vectorize, f: *Function, w: *Writer) !void {
8501 if (self.index != .none) {8551 if (self.index != .none) {
8502 try writer.writeByte('[');8552 try w.writeByte('[');
8503 try f.writeCValue(writer, self.index, .Other);8553 try f.writeCValue(w, self.index, .Other);
8504 try writer.writeByte(']');8554 try w.writeByte(']');
8505 }8555 }
8506 }8556 }
85078557
8508 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, writer: anytype) !void {8558 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void {
8509 if (self.index != .none) {8559 if (self.index != .none) {
8510 f.object.indent_writer.popIndent();8560 try f.object.outdent();
8511 try writer.writeAll("}\n");8561 try w.writeByte('}');
8562 try f.object.newline();
8512 try freeLocal(f, inst, self.index.new_local, null);8563 try freeLocal(f, inst, self.index.new_local, null);
8513 }8564 }
8514 }8565 }
src/codegen/c/Type.zig+21-25
...@@ -209,7 +209,7 @@ pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {...@@ -209,7 +209,7 @@ pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {
209 };209 };
210}210}
211211
212pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *const Pool) @TypeOf(writer).Error!void {212pub fn renderLiteralPrefix(ctype: CType, w: *Writer, kind: Kind, pool: *const Pool) Writer.Error!void {
213 switch (ctype.info(pool)) {213 switch (ctype.info(pool)) {
214 .basic => |basic_info| switch (basic_info) {214 .basic => |basic_info| switch (basic_info) {
215 .void => unreachable,215 .void => unreachable,
...@@ -224,7 +224,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con...@@ -224,7 +224,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
224 .uintptr_t,224 .uintptr_t,
225 .intptr_t,225 .intptr_t,
226 => switch (kind) {226 => switch (kind) {
227 else => try writer.print("({s})", .{@tagName(basic_info)}),227 else => try w.print("({s})", .{@tagName(basic_info)}),
228 .global => {},228 .global => {},
229 },229 },
230 .int,230 .int,
...@@ -246,7 +246,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con...@@ -246,7 +246,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
246 .int32_t,246 .int32_t,
247 .uint64_t,247 .uint64_t,
248 .int64_t,248 .int64_t,
249 => try writer.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}),249 => try w.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}),
250 .zig_u128,250 .zig_u128,
251 .zig_i128,251 .zig_i128,
252 .zig_f16,252 .zig_f16,
...@@ -255,7 +255,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con...@@ -255,7 +255,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
255 .zig_f80,255 .zig_f80,
256 .zig_f128,256 .zig_f128,
257 .zig_c_longdouble,257 .zig_c_longdouble,
258 => try writer.print("zig_{s}_{s}(", .{258 => try w.print("zig_{s}_{s}(", .{
259 switch (kind) {259 switch (kind) {
260 else => "make",260 else => "make",
261 .global => "init",261 .global => "init",
...@@ -265,12 +265,12 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con...@@ -265,12 +265,12 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
265 .va_list => unreachable,265 .va_list => unreachable,
266 _ => unreachable,266 _ => unreachable,
267 },267 },
268 .array, .vector => try writer.writeByte('{'),268 .array, .vector => try w.writeByte('{'),
269 else => unreachable,269 else => unreachable,
270 }270 }
271}271}
272272
273pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @TypeOf(writer).Error!void {273pub fn renderLiteralSuffix(ctype: CType, w: *Writer, pool: *const Pool) Writer.Error!void {
274 switch (ctype.info(pool)) {274 switch (ctype.info(pool)) {
275 .basic => |basic_info| switch (basic_info) {275 .basic => |basic_info| switch (basic_info) {
276 .void => unreachable,276 .void => unreachable,
...@@ -280,20 +280,20 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty...@@ -280,20 +280,20 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty
280 .short,280 .short,
281 .int,281 .int,
282 => {},282 => {},
283 .long => try writer.writeByte('l'),283 .long => try w.writeByte('l'),
284 .@"long long" => try writer.writeAll("ll"),284 .@"long long" => try w.writeAll("ll"),
285 .@"unsigned char",285 .@"unsigned char",
286 .@"unsigned short",286 .@"unsigned short",
287 .@"unsigned int",287 .@"unsigned int",
288 => try writer.writeByte('u'),288 => try w.writeByte('u'),
289 .@"unsigned long",289 .@"unsigned long",
290 .size_t,290 .size_t,
291 .uintptr_t,291 .uintptr_t,
292 => try writer.writeAll("ul"),292 => try w.writeAll("ul"),
293 .@"unsigned long long" => try writer.writeAll("ull"),293 .@"unsigned long long" => try w.writeAll("ull"),
294 .float => try writer.writeByte('f'),294 .float => try w.writeByte('f'),
295 .double => {},295 .double => {},
296 .@"long double" => try writer.writeByte('l'),296 .@"long double" => try w.writeByte('l'),
297 .bool,297 .bool,
298 .ptrdiff_t,298 .ptrdiff_t,
299 .intptr_t,299 .intptr_t,
...@@ -314,11 +314,11 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty...@@ -314,11 +314,11 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty
314 .zig_f80,314 .zig_f80,
315 .zig_f128,315 .zig_f128,
316 .zig_c_longdouble,316 .zig_c_longdouble,
317 => try writer.writeByte(')'),317 => try w.writeByte(')'),
318 .va_list => unreachable,318 .va_list => unreachable,
319 _ => unreachable,319 _ => unreachable,
320 },320 },
321 .array, .vector => try writer.writeByte('}'),321 .array, .vector => try w.writeByte('}'),
322 else => unreachable,322 else => unreachable,
323 }323 }
324}324}
...@@ -938,19 +938,13 @@ pub const Pool = struct {...@@ -938,19 +938,13 @@ pub const Pool = struct {
938 index: String.Index,938 index: String.Index,
939939
940 const FormatData = struct { string: String, pool: *const Pool };940 const FormatData = struct { string: String, pool: *const Pool };
941 fn format(941 fn format(data: FormatData, writer: *Writer) Writer.Error!void {
942 data: FormatData,
943 comptime fmt_str: []const u8,
944 _: std.fmt.FormatOptions,
945 writer: anytype,
946 ) @TypeOf(writer).Error!void {
947 if (fmt_str.len > 0) @compileError("invalid format string '" ++ fmt_str ++ "'");
948 if (data.string.toSlice(data.pool)) |slice|942 if (data.string.toSlice(data.pool)) |slice|
949 try writer.writeAll(slice)943 try writer.writeAll(slice)
950 else944 else
951 try writer.print("f{d}", .{@intFromEnum(data.string.index)});945 try writer.print("f{d}", .{@intFromEnum(data.string.index)});
952 }946 }
953 pub fn fmt(str: String, pool: *const Pool) std.fmt.Formatter(format) {947 pub fn fmt(str: String, pool: *const Pool) std.fmt.Formatter(FormatData, format) {
954 return .{ .data = .{ .string = str, .pool = pool } };948 return .{ .data = .{ .string = str, .pool = pool } };
955 }949 }
956950
...@@ -2890,7 +2884,7 @@ pub const Pool = struct {...@@ -2890,7 +2884,7 @@ pub const Pool = struct {
2890 comptime fmt_str: []const u8,2884 comptime fmt_str: []const u8,
2891 fmt_args: anytype,2885 fmt_args: anytype,
2892 ) !String {2886 ) !String {
2893 try pool.string_bytes.writer(allocator).print(fmt_str, fmt_args);2887 try pool.string_bytes.print(allocator, fmt_str, fmt_args);
2894 return pool.trailingString(allocator);2888 return pool.trailingString(allocator);
2895 }2889 }
28962890
...@@ -3281,10 +3275,12 @@ pub const AlignAs = packed struct {...@@ -3281,10 +3275,12 @@ pub const AlignAs = packed struct {
3281 }3275 }
3282};3276};
32833277
3278const std = @import("std");
3284const assert = std.debug.assert;3279const assert = std.debug.assert;
3280const Writer = std.io.Writer;
3281
3285const CType = @This();3282const CType = @This();
3286const InternPool = @import("../../InternPool.zig");3283const InternPool = @import("../../InternPool.zig");
3287const Module = @import("../../Package/Module.zig");3284const Module = @import("../../Package/Module.zig");
3288const std = @import("std");
3289const Type = @import("../../Type.zig");3285const Type = @import("../../Type.zig");
3290const Zcu = @import("../../Zcu.zig");3286const Zcu = @import("../../Zcu.zig");
src/codegen/llvm.zig+29-19
...@@ -239,12 +239,12 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8...@@ -239,12 +239,12 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
239 .none,239 .none,
240 .windows,240 .windows,
241 => {},241 => {},
242 .semver => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{242 .semver => |ver| try llvm_triple.print("{d}.{d}.{d}", .{
243 ver.min.major,243 ver.min.major,
244 ver.min.minor,244 ver.min.minor,
245 ver.min.patch,245 ver.min.patch,
246 }),246 }),
247 inline .linux, .hurd => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{247 inline .linux, .hurd => |ver| try llvm_triple.print("{d}.{d}.{d}", .{
248 ver.range.min.major,248 ver.range.min.major,
249 ver.range.min.minor,249 ver.range.min.minor,
250 ver.range.min.patch,250 ver.range.min.patch,
...@@ -295,13 +295,13 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8...@@ -295,13 +295,13 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
295 .windows,295 .windows,
296 => {},296 => {},
297 inline .hurd, .linux => |ver| if (target.abi.isGnu()) {297 inline .hurd, .linux => |ver| if (target.abi.isGnu()) {
298 try llvm_triple.writer().print("{d}.{d}.{d}", .{298 try llvm_triple.print("{d}.{d}.{d}", .{
299 ver.glibc.major,299 ver.glibc.major,
300 ver.glibc.minor,300 ver.glibc.minor,
301 ver.glibc.patch,301 ver.glibc.patch,
302 });302 });
303 } else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {303 } else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {
304 try llvm_triple.writer().print("{d}", .{ver.android});304 try llvm_triple.print("{d}", .{ver.android});
305 },305 },
306 }306 }
307307
...@@ -746,12 +746,18 @@ pub const Object = struct {...@@ -746,12 +746,18 @@ pub const Object = struct {
746 try wip.finish();746 try wip.finish();
747 }747 }
748748
749 fn genModuleLevelAssembly(object: *Object) !void {749 fn genModuleLevelAssembly(object: *Object) Allocator.Error!void {
750 const writer = object.builder.setModuleAsm();750 const b = &object.builder;
751 const gpa = b.gpa;
752 b.module_asm.clearRetainingCapacity();
751 for (object.pt.zcu.global_assembly.values()) |assembly| {753 for (object.pt.zcu.global_assembly.values()) |assembly| {
752 try writer.print("{s}\n", .{assembly});754 try b.module_asm.ensureUnusedCapacity(gpa, assembly.len + 1);
755 b.module_asm.appendSliceAssumeCapacity(assembly);
756 b.module_asm.appendAssumeCapacity('\n');
757 }
758 if (b.module_asm.getLastOrNull()) |last| {
759 if (last != '\n') try b.module_asm.append(gpa, '\n');
753 }760 }
754 try object.builder.finishModuleAsm();
755 }761 }
756762
757 pub const EmitOptions = struct {763 pub const EmitOptions = struct {
...@@ -939,7 +945,9 @@ pub const Object = struct {...@@ -939,7 +945,9 @@ pub const Object = struct {
939 if (std.mem.eql(u8, path, "-")) {945 if (std.mem.eql(u8, path, "-")) {
940 o.builder.dump();946 o.builder.dump();
941 } else {947 } else {
942 _ = try o.builder.printToFile(path);948 o.builder.printToFilePath(std.fs.cwd(), path) catch |err| {
949 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
950 };
943 }951 }
944 }952 }
945953
...@@ -2486,7 +2494,7 @@ pub const Object = struct {...@@ -2486,7 +2494,7 @@ pub const Object = struct {
2486 var union_name_buf: ?[:0]const u8 = null;2494 var union_name_buf: ?[:0]const u8 = null;
2487 defer if (union_name_buf) |buf| gpa.free(buf);2495 defer if (union_name_buf) |buf| gpa.free(buf);
2488 const union_name = if (layout.tag_size == 0) name else name: {2496 const union_name = if (layout.tag_size == 0) name else name: {
2489 union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name});2497 union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0);
2490 break :name union_name_buf.?;2498 break :name union_name_buf.?;
2491 };2499 };
24922500
...@@ -2680,10 +2688,12 @@ pub const Object = struct {...@@ -2680,10 +2688,12 @@ pub const Object = struct {
2680 }2688 }
26812689
2682 fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 {2690 fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 {
2683 var buffer = std.ArrayList(u8).init(o.gpa);2691 var aw: std.io.Writer.Allocating = .init(o.gpa);
2684 errdefer buffer.deinit();2692 defer aw.deinit();
2685 try ty.print(buffer.writer(), o.pt);2693 ty.print(&aw.writer, o.pt) catch |err| switch (err) {
2686 return buffer.toOwnedSliceSentinel(0);2694 error.WriteFailed => return error.OutOfMemory,
2695 };
2696 return aw.toOwnedSliceSentinel(0);
2687 }2697 }
26882698
2689 /// If the llvm function does not exist, create it.2699 /// If the llvm function does not exist, create it.
...@@ -4482,7 +4492,7 @@ pub const Object = struct {...@@ -4482,7 +4492,7 @@ pub const Object = struct {
4482 const target = &zcu.root_mod.resolved_target.result;4492 const target = &zcu.root_mod.resolved_target.result;
4483 const function_index = try o.builder.addFunction(4493 const function_index = try o.builder.addFunction(
4484 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),4494 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
4485 try o.builder.strtabStringFmt("__zig_tag_name_{}", .{enum_type.name.fmt(ip)}),4495 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}),
4486 toLlvmAddressSpace(.generic, target),4496 toLlvmAddressSpace(.generic, target),
4487 );4497 );
44884498
...@@ -4633,7 +4643,7 @@ pub const NavGen = struct {...@@ -4633,7 +4643,7 @@ pub const NavGen = struct {
4633 if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") {4643 if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") {
4634 if (lib_name.toSlice(ip)) |lib_name_slice| {4644 if (lib_name.toSlice(ip)) |lib_name_slice| {
4635 if (!std.mem.eql(u8, lib_name_slice, "c")) {4645 if (!std.mem.eql(u8, lib_name_slice, "c")) {
4636 break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice });4646 break :decl_name try o.builder.strtabStringFmt("{f}|{s}", .{ nav.name.fmt(ip), lib_name_slice });
4637 }4647 }
4638 }4648 }
4639 }4649 }
...@@ -7472,7 +7482,7 @@ pub const FuncGen = struct {...@@ -7472,7 +7482,7 @@ pub const FuncGen = struct {
7472 llvm_param_types[llvm_param_i] = llvm_elem_ty;7482 llvm_param_types[llvm_param_i] = llvm_elem_ty;
7473 }7483 }
74747484
7475 try llvm_constraints.writer(self.gpa).print(",{d}", .{output_index});7485 try llvm_constraints.print(self.gpa, ",{d}", .{output_index});
74767486
7477 // In the case of indirect inputs, LLVM requires the callsite to have7487 // In the case of indirect inputs, LLVM requires the callsite to have
7478 // an elementtype(<ty>) attribute.7488 // an elementtype(<ty>) attribute.
...@@ -7573,7 +7583,7 @@ pub const FuncGen = struct {...@@ -7573,7 +7583,7 @@ pub const FuncGen = struct {
7573 // we should validate the assembly in Sema; by now it is too late7583 // we should validate the assembly in Sema; by now it is too late
7574 return self.todo("unknown input or output name: '{s}'", .{name});7584 return self.todo("unknown input or output name: '{s}'", .{name});
7575 };7585 };
7576 try rendered_template.writer().print("{d}", .{index});7586 try rendered_template.print("{d}", .{index});
7577 if (byte == ':') {7587 if (byte == ':') {
7578 try rendered_template.append(':');7588 try rendered_template.append(':');
7579 modifier_start = i + 1;7589 modifier_start = i + 1;
...@@ -10370,7 +10380,7 @@ pub const FuncGen = struct {...@@ -10370,7 +10380,7 @@ pub const FuncGen = struct {
10370 const target = &zcu.root_mod.resolved_target.result;10380 const target = &zcu.root_mod.resolved_target.result;
10371 const function_index = try o.builder.addFunction(10381 const function_index = try o.builder.addFunction(
10372 try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),10382 try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
10373 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{enum_type.name.fmt(ip)}),10383 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),
10374 toLlvmAddressSpace(.generic, target),10384 toLlvmAddressSpace(.generic, target),
10375 );10385 );
1037610386
src/codegen/spirv.zig+10-8
...@@ -817,7 +817,7 @@ const NavGen = struct {...@@ -817,7 +817,7 @@ const NavGen = struct {
817 const result_ty_id = try self.resolveType(ty, repr);817 const result_ty_id = try self.resolveType(ty, repr);
818 const ip = &zcu.intern_pool;818 const ip = &zcu.intern_pool;
819819
820 log.debug("lowering constant: ty = {}, val = {}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });820 log.debug("lowering constant: ty = {f}, val = {f}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });
821 if (val.isUndefDeep(zcu)) {821 if (val.isUndefDeep(zcu)) {
822 return self.spv.constUndef(result_ty_id);822 return self.spv.constUndef(result_ty_id);
823 }823 }
...@@ -1147,7 +1147,7 @@ const NavGen = struct {...@@ -1147,7 +1147,7 @@ const NavGen = struct {
1147 return result_ptr_id;1147 return result_ptr_id;
1148 }1148 }
11491149
1150 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{1150 return self.fail("cannot perform pointer cast: '{f}' to '{f}'", .{
1151 parent_ptr_ty.fmt(pt),1151 parent_ptr_ty.fmt(pt),
1152 oac.new_ptr_ty.fmt(pt),1152 oac.new_ptr_ty.fmt(pt),
1153 });1153 });
...@@ -1260,10 +1260,12 @@ const NavGen = struct {...@@ -1260,10 +1260,12 @@ const NavGen = struct {
12601260
1261 // Turn a Zig type's name into a cache reference.1261 // Turn a Zig type's name into a cache reference.
1262 fn resolveTypeName(self: *NavGen, ty: Type) ![]const u8 {1262 fn resolveTypeName(self: *NavGen, ty: Type) ![]const u8 {
1263 var name = std.ArrayList(u8).init(self.gpa);1263 var aw: std.io.Writer.Allocating = .init(self.gpa);
1264 defer name.deinit();1264 defer aw.deinit();
1265 try ty.print(name.writer(), self.pt);1265 ty.print(&aw.writer, self.pt) catch |err| switch (err) {
1266 return try name.toOwnedSlice();1266 error.WriteFailed => return error.OutOfMemory,
1267 };
1268 return try aw.toOwnedSlice();
1267 }1269 }
12681270
1269 /// Create an integer type suitable for storing at least 'bits' bits.1271 /// Create an integer type suitable for storing at least 'bits' bits.
...@@ -1462,7 +1464,7 @@ const NavGen = struct {...@@ -1462,7 +1464,7 @@ const NavGen = struct {
1462 const pt = self.pt;1464 const pt = self.pt;
1463 const zcu = pt.zcu;1465 const zcu = pt.zcu;
1464 const ip = &zcu.intern_pool;1466 const ip = &zcu.intern_pool;
1465 log.debug("resolveType: ty = {}", .{ty.fmt(pt)});1467 log.debug("resolveType: ty = {f}", .{ty.fmt(pt)});
1466 const target = self.spv.target;1468 const target = self.spv.target;
14671469
1468 const section = &self.spv.sections.types_globals_constants;1470 const section = &self.spv.sections.types_globals_constants;
...@@ -3068,7 +3070,7 @@ const NavGen = struct {...@@ -3068,7 +3070,7 @@ const NavGen = struct {
3068 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});3070 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
3069 try self.spv.addFunction(spv_decl_index, self.func);3071 try self.spv.addFunction(spv_decl_index, self.func);
30703072
3071 try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{nav.fqn.fmt(ip)});3073 try self.spv.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
30723074
3073 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{3075 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
3074 .id_result_type = ptr_ty_id,3076 .id_result_type = ptr_ty_id,
src/codegen/spirv/spec.zig+3-7
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1//! This file is auto-generated by tools/gen_spirv_spec.zig.1//! This file is auto-generated by tools/gen_spirv_spec.zig.
22
3const std = @import("std");3const std = @import("std");
4const assert = std.debug.assert;
45
5pub const Version = packed struct(Word) {6pub const Version = packed struct(Word) {
6 padding: u8 = 0,7 padding: u8 = 0,
...@@ -18,15 +19,10 @@ pub const IdResult = enum(Word) {...@@ -18,15 +19,10 @@ pub const IdResult = enum(Word) {
18 none,19 none,
19 _,20 _,
2021
21 pub fn format(22 pub fn format(self: IdResult, writer: *std.io.Writer) std.io.Writer.Error!void {
22 self: IdResult,
23 comptime _: []const u8,
24 _: std.fmt.FormatOptions,
25 writer: anytype,
26 ) @TypeOf(writer).Error!void {
27 switch (self) {23 switch (self) {
28 .none => try writer.writeAll("(none)"),24 .none => try writer.writeAll("(none)"),
29 else => try writer.print("%{}", .{@intFromEnum(self)}),25 else => try writer.print("%{d}", .{@intFromEnum(self)}),
30 }26 }
31 }27 }
32};28};
src/crash_report.zig+22-15
...@@ -80,18 +80,19 @@ fn dumpStatusReport() !void {...@@ -80,18 +80,19 @@ 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 = io.getStdErr().writer();83 var stderr_fw = std.fs.File.stderr().writer(&.{});
84 const stderr = &stderr_fw.interface;
84 const block: *Sema.Block = anal.block;85 const block: *Sema.Block = anal.block;
85 const zcu = anal.sema.pt.zcu;86 const zcu = anal.sema.pt.zcu;
8687
87 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {88 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {
88 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));89 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));
89 try stderr.print("Analyzing lost instruction in file '{}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});90 try stderr.print("Analyzing lost instruction in file '{f}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});
90 return;91 return;
91 };92 };
9293
93 try stderr.writeAll("Analyzing ");94 try stderr.writeAll("Analyzing ");
94 try stderr.print("Analyzing '{}'\n", .{file.path.fmt(zcu.comp)});95 try stderr.print("Analyzing '{f}'\n", .{file.path.fmt(zcu.comp)});
9596
96 print_zir.renderInstructionContext(97 print_zir.renderInstructionContext(
97 allocator,98 allocator,
...@@ -107,7 +108,7 @@ fn dumpStatusReport() !void {...@@ -107,7 +108,7 @@ fn dumpStatusReport() !void {
107 };108 };
108 try stderr.print(109 try stderr.print(
109 \\ For full context, use the command110 \\ For full context, use the command
110 \\ zig ast-check -t {}111 \\ zig ast-check -t {f}
111 \\112 \\
112 \\113 \\
113 , .{file.path.fmt(zcu.comp)});114 , .{file.path.fmt(zcu.comp)});
...@@ -116,7 +117,7 @@ fn dumpStatusReport() !void {...@@ -116,7 +117,7 @@ fn dumpStatusReport() !void {
116 while (parent) |curr| {117 while (parent) |curr| {
117 fba.reset();118 fba.reset();
118 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));119 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));
119 try stderr.print(" in {}\n", .{cur_block_file.path.fmt(zcu.comp)});120 try stderr.print(" in {f}\n", .{cur_block_file.path.fmt(zcu.comp)});
120 _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {121 _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {
121 try stderr.writeAll(" > [lost instruction; this should not happen]\n");122 try stderr.writeAll(" > [lost instruction; this should not happen]\n");
122 parent = curr.parent;123 parent = curr.parent;
...@@ -139,7 +140,7 @@ fn dumpStatusReport() !void {...@@ -139,7 +140,7 @@ fn dumpStatusReport() !void {
139 parent = curr.parent;140 parent = curr.parent;
140 }141 }
141142
142 try stderr.writeAll("\n");143 try stderr.writeByte('\n');
143}144}
144145
145var crash_heap: [16 * 4096]u8 = undefined;146var crash_heap: [16 * 4096]u8 = undefined;
...@@ -268,11 +269,12 @@ const StackContext = union(enum) {...@@ -268,11 +269,12 @@ const StackContext = union(enum) {
268 debug.dumpCurrentStackTrace(ct.ret_addr);269 debug.dumpCurrentStackTrace(ct.ret_addr);
269 },270 },
270 .exception => |context| {271 .exception => |context| {
271 debug.dumpStackTraceFromBase(context);272 var stderr_fw = std.fs.File.stderr().writer(&.{});
273 const stderr = &stderr_fw.interface;
274 debug.dumpStackTraceFromBase(context, stderr);
272 },275 },
273 .not_supported => {276 .not_supported => {
274 const stderr = io.getStdErr().writer();277 std.fs.File.stderr().writeAll("Stack trace not supported on this platform.\n") catch {};
275 stderr.writeAll("Stack trace not supported on this platform.\n") catch {};
276 },278 },
277 }279 }
278 }280 }
...@@ -379,7 +381,8 @@ const PanicSwitch = struct {...@@ -379,7 +381,8 @@ const PanicSwitch = struct {
379381
380 state.recover_stage = .release_mutex;382 state.recover_stage = .release_mutex;
381383
382 const stderr = io.getStdErr().writer();384 var stderr_fw = std.fs.File.stderr().writer(&.{});
385 const stderr = &stderr_fw.interface;
383 if (builtin.single_threaded) {386 if (builtin.single_threaded) {
384 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});387 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});
385 } else {388 } else {
...@@ -406,7 +409,8 @@ const PanicSwitch = struct {...@@ -406,7 +409,8 @@ const PanicSwitch = struct {
406 recover(state, trace, stack, msg);409 recover(state, trace, stack, msg);
407410
408 state.recover_stage = .release_mutex;411 state.recover_stage = .release_mutex;
409 const stderr = io.getStdErr().writer();412 var stderr_fw = std.fs.File.stderr().writer(&.{});
413 const stderr = &stderr_fw.interface;
410 stderr.writeAll("\nOriginal Error:\n") catch {};414 stderr.writeAll("\nOriginal Error:\n") catch {};
411 goTo(reportStack, .{state});415 goTo(reportStack, .{state});
412 }416 }
...@@ -477,7 +481,8 @@ const PanicSwitch = struct {...@@ -477,7 +481,8 @@ const PanicSwitch = struct {
477 recover(state, trace, stack, msg);481 recover(state, trace, stack, msg);
478482
479 state.recover_stage = .silent_abort;483 state.recover_stage = .silent_abort;
480 const stderr = io.getStdErr().writer();484 var stderr_fw = std.fs.File.stderr().writer(&.{});
485 const stderr = &stderr_fw.interface;
481 stderr.writeAll("Aborting...\n") catch {};486 stderr.writeAll("Aborting...\n") catch {};
482 goTo(abort, .{});487 goTo(abort, .{});
483 }488 }
...@@ -505,7 +510,8 @@ const PanicSwitch = struct {...@@ -505,7 +510,8 @@ const PanicSwitch = struct {
505 // lower the verbosity, and restore it at the end if we don't panic.510 // lower the verbosity, and restore it at the end if we don't panic.
506 state.recover_verbosity = .message_only;511 state.recover_verbosity = .message_only;
507512
508 const stderr = io.getStdErr().writer();513 var stderr_fw = std.fs.File.stderr().writer(&.{});
514 const stderr = &stderr_fw.interface;
509 stderr.writeAll("\nPanicked during a panic: ") catch {};515 stderr.writeAll("\nPanicked during a panic: ") catch {};
510 stderr.writeAll(msg) catch {};516 stderr.writeAll(msg) catch {};
511 stderr.writeAll("\nInner panic stack:\n") catch {};517 stderr.writeAll("\nInner panic stack:\n") catch {};
...@@ -519,10 +525,11 @@ const PanicSwitch = struct {...@@ -519,10 +525,11 @@ const PanicSwitch = struct {
519 .message_only => {525 .message_only => {
520 state.recover_verbosity = .silent;526 state.recover_verbosity = .silent;
521527
522 const stderr = io.getStdErr().writer();528 var stderr_fw = std.fs.File.stderr().writer(&.{});
529 const stderr = &stderr_fw.interface;
523 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};530 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
524 stderr.writeAll(msg) catch {};531 stderr.writeAll(msg) catch {};
525 stderr.writeAll("\n") catch {};532 stderr.writeByte('\n') catch {};
526533
527 // If we succeed, restore all the way to dumping the stack.534 // If we succeed, restore all the way to dumping the stack.
528 state.recover_verbosity = .message_and_stack;535 state.recover_verbosity = .message_and_stack;
src/deprecated.zig created+431
...@@ -0,0 +1,431 @@
1//! Deprecated. Stop using this API
2
3const std = @import("std");
4const math = std.math;
5const mem = std.mem;
6const Allocator = mem.Allocator;
7const assert = std.debug.assert;
8const testing = std.testing;
9
10pub fn LinearFifo(comptime T: type) type {
11 return struct {
12 allocator: Allocator,
13 buf: []T,
14 head: usize,
15 count: usize,
16
17 const Self = @This();
18
19 pub fn init(allocator: Allocator) Self {
20 return .{
21 .allocator = allocator,
22 .buf = &.{},
23 .head = 0,
24 .count = 0,
25 };
26 }
27
28 pub fn deinit(self: *Self) void {
29 self.allocator.free(self.buf);
30 self.* = undefined;
31 }
32
33 pub fn realign(self: *Self) void {
34 if (self.buf.len - self.head >= self.count) {
35 mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]);
36 self.head = 0;
37 } else {
38 var tmp: [4096 / 2 / @sizeOf(T)]T = undefined;
39
40 while (self.head != 0) {
41 const n = @min(self.head, tmp.len);
42 const m = self.buf.len - n;
43 @memcpy(tmp[0..n], self.buf[0..n]);
44 mem.copyForwards(T, self.buf[0..m], self.buf[n..][0..m]);
45 @memcpy(self.buf[m..][0..n], tmp[0..n]);
46 self.head -= n;
47 }
48 }
49 { // set unused area to undefined
50 const unused = mem.sliceAsBytes(self.buf[self.count..]);
51 @memset(unused, undefined);
52 }
53 }
54
55 /// Reduce allocated capacity to `size`.
56 pub fn shrink(self: *Self, size: usize) void {
57 assert(size >= self.count);
58 self.realign();
59 self.buf = self.allocator.realloc(self.buf, size) catch |e| switch (e) {
60 error.OutOfMemory => return, // no problem, capacity is still correct then.
61 };
62 }
63
64 /// Ensure that the buffer can fit at least `size` items
65 pub fn ensureTotalCapacity(self: *Self, size: usize) !void {
66 if (self.buf.len >= size) return;
67 self.realign();
68 const new_size = math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory;
69 self.buf = try self.allocator.realloc(self.buf, new_size);
70 }
71
72 /// Makes sure at least `size` items are unused
73 pub fn ensureUnusedCapacity(self: *Self, size: usize) error{OutOfMemory}!void {
74 if (self.writableLength() >= size) return;
75
76 return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory);
77 }
78
79 /// Returns number of items currently in fifo
80 pub fn readableLength(self: Self) usize {
81 return self.count;
82 }
83
84 /// Returns a writable slice from the 'read' end of the fifo
85 fn readableSliceMut(self: Self, offset: usize) []T {
86 if (offset > self.count) return &[_]T{};
87
88 var start = self.head + offset;
89 if (start >= self.buf.len) {
90 start -= self.buf.len;
91 return self.buf[start .. start + (self.count - offset)];
92 } else {
93 const end = @min(self.head + self.count, self.buf.len);
94 return self.buf[start..end];
95 }
96 }
97
98 /// Returns a readable slice from `offset`
99 pub fn readableSlice(self: Self, offset: usize) []const T {
100 return self.readableSliceMut(offset);
101 }
102
103 pub fn readableSliceOfLen(self: *Self, len: usize) []const T {
104 assert(len <= self.count);
105 const buf = self.readableSlice(0);
106 if (buf.len >= len) {
107 return buf[0..len];
108 } else {
109 self.realign();
110 return self.readableSlice(0)[0..len];
111 }
112 }
113
114 /// Discard first `count` items in the fifo
115 pub fn discard(self: *Self, count: usize) void {
116 assert(count <= self.count);
117 { // set old range to undefined. Note: may be wrapped around
118 const slice = self.readableSliceMut(0);
119 if (slice.len >= count) {
120 const unused = mem.sliceAsBytes(slice[0..count]);
121 @memset(unused, undefined);
122 } else {
123 const unused = mem.sliceAsBytes(slice[0..]);
124 @memset(unused, undefined);
125 const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]);
126 @memset(unused2, undefined);
127 }
128 }
129 var head = self.head + count;
130 // Note it is safe to do a wrapping subtract as
131 // bitwise & with all 1s is a noop
132 head &= self.buf.len -% 1;
133 self.head = head;
134 self.count -= count;
135 }
136
137 /// Read the next item from the fifo
138 pub fn readItem(self: *Self) ?T {
139 if (self.count == 0) return null;
140
141 const c = self.buf[self.head];
142 self.discard(1);
143 return c;
144 }
145
146 /// Read data from the fifo into `dst`, returns number of items copied.
147 pub fn read(self: *Self, dst: []T) usize {
148 var dst_left = dst;
149
150 while (dst_left.len > 0) {
151 const slice = self.readableSlice(0);
152 if (slice.len == 0) break;
153 const n = @min(slice.len, dst_left.len);
154 @memcpy(dst_left[0..n], slice[0..n]);
155 self.discard(n);
156 dst_left = dst_left[n..];
157 }
158
159 return dst.len - dst_left.len;
160 }
161
162 /// Same as `read` except it returns an error union
163 /// The purpose of this function existing is to match `std.io.Reader` API.
164 fn readFn(self: *Self, dest: []u8) error{}!usize {
165 return self.read(dest);
166 }
167
168 /// Returns number of items available in fifo
169 pub fn writableLength(self: Self) usize {
170 return self.buf.len - self.count;
171 }
172
173 /// Returns the first section of writable buffer.
174 /// Note that this may be of length 0
175 pub fn writableSlice(self: Self, offset: usize) []T {
176 if (offset > self.buf.len) return &[_]T{};
177
178 const tail = self.head + offset + self.count;
179 if (tail < self.buf.len) {
180 return self.buf[tail..];
181 } else {
182 return self.buf[tail - self.buf.len ..][0 .. self.writableLength() - offset];
183 }
184 }
185
186 /// Returns a writable buffer of at least `size` items, allocating memory as needed.
187 /// Use `fifo.update` once you've written data to it.
188 pub fn writableWithSize(self: *Self, size: usize) ![]T {
189 try self.ensureUnusedCapacity(size);
190
191 // try to avoid realigning buffer
192 var slice = self.writableSlice(0);
193 if (slice.len < size) {
194 self.realign();
195 slice = self.writableSlice(0);
196 }
197 return slice;
198 }
199
200 /// Update the tail location of the buffer (usually follows use of writable/writableWithSize)
201 pub fn update(self: *Self, count: usize) void {
202 assert(self.count + count <= self.buf.len);
203 self.count += count;
204 }
205
206 /// Appends the data in `src` to the fifo.
207 /// You must have ensured there is enough space.
208 pub fn writeAssumeCapacity(self: *Self, src: []const T) void {
209 assert(self.writableLength() >= src.len);
210
211 var src_left = src;
212 while (src_left.len > 0) {
213 const writable_slice = self.writableSlice(0);
214 assert(writable_slice.len != 0);
215 const n = @min(writable_slice.len, src_left.len);
216 @memcpy(writable_slice[0..n], src_left[0..n]);
217 self.update(n);
218 src_left = src_left[n..];
219 }
220 }
221
222 /// Write a single item to the fifo
223 pub fn writeItem(self: *Self, item: T) !void {
224 try self.ensureUnusedCapacity(1);
225 return self.writeItemAssumeCapacity(item);
226 }
227
228 pub fn writeItemAssumeCapacity(self: *Self, item: T) void {
229 var tail = self.head + self.count;
230 tail &= self.buf.len - 1;
231 self.buf[tail] = item;
232 self.update(1);
233 }
234
235 /// Appends the data in `src` to the fifo.
236 /// Allocates more memory as necessary
237 pub fn write(self: *Self, src: []const T) !void {
238 try self.ensureUnusedCapacity(src.len);
239
240 return self.writeAssumeCapacity(src);
241 }
242
243 /// Same as `write` except it returns the number of bytes written, which is always the same
244 /// as `bytes.len`. The purpose of this function existing is to match `std.io.Writer` API.
245 fn appendWrite(self: *Self, bytes: []const u8) error{OutOfMemory}!usize {
246 try self.write(bytes);
247 return bytes.len;
248 }
249
250 /// Make `count` items available before the current read location
251 fn rewind(self: *Self, count: usize) void {
252 assert(self.writableLength() >= count);
253
254 var head = self.head + (self.buf.len - count);
255 head &= self.buf.len - 1;
256 self.head = head;
257 self.count += count;
258 }
259
260 /// Place data back into the read stream
261 pub fn unget(self: *Self, src: []const T) !void {
262 try self.ensureUnusedCapacity(src.len);
263
264 self.rewind(src.len);
265
266 const slice = self.readableSliceMut(0);
267 if (src.len < slice.len) {
268 @memcpy(slice[0..src.len], src);
269 } else {
270 @memcpy(slice, src[0..slice.len]);
271 const slice2 = self.readableSliceMut(slice.len);
272 @memcpy(slice2[0 .. src.len - slice.len], src[slice.len..]);
273 }
274 }
275
276 /// Returns the item at `offset`.
277 /// Asserts offset is within bounds.
278 pub fn peekItem(self: Self, offset: usize) T {
279 assert(offset < self.count);
280
281 var index = self.head + offset;
282 index &= self.buf.len - 1;
283 return self.buf[index];
284 }
285
286 pub fn toOwnedSlice(self: *Self) Allocator.Error![]T {
287 if (self.head != 0) self.realign();
288 assert(self.head == 0);
289 assert(self.count <= self.buf.len);
290 const allocator = self.allocator;
291 if (allocator.resize(self.buf, self.count)) {
292 const result = self.buf[0..self.count];
293 self.* = Self.init(allocator);
294 return result;
295 }
296 const new_memory = try allocator.dupe(T, self.buf[0..self.count]);
297 allocator.free(self.buf);
298 self.* = Self.init(allocator);
299 return new_memory;
300 }
301 };
302}
303
304test "LinearFifo(u8, .Dynamic) discard(0) from empty buffer should not error on overflow" {
305 var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
306 defer fifo.deinit();
307
308 // If overflow is not explicitly allowed this will crash in debug / safe mode
309 fifo.discard(0);
310}
311
312test "LinearFifo(u8, .Dynamic)" {
313 var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
314 defer fifo.deinit();
315
316 try fifo.write("HELLO");
317 try testing.expectEqual(@as(usize, 5), fifo.readableLength());
318 try testing.expectEqualSlices(u8, "HELLO", fifo.readableSlice(0));
319
320 {
321 var i: usize = 0;
322 while (i < 5) : (i += 1) {
323 try fifo.write(&[_]u8{fifo.peekItem(i)});
324 }
325 try testing.expectEqual(@as(usize, 10), fifo.readableLength());
326 try testing.expectEqualSlices(u8, "HELLOHELLO", fifo.readableSlice(0));
327 }
328
329 {
330 try testing.expectEqual(@as(u8, 'H'), fifo.readItem().?);
331 try testing.expectEqual(@as(u8, 'E'), fifo.readItem().?);
332 try testing.expectEqual(@as(u8, 'L'), fifo.readItem().?);
333 try testing.expectEqual(@as(u8, 'L'), fifo.readItem().?);
334 try testing.expectEqual(@as(u8, 'O'), fifo.readItem().?);
335 }
336 try testing.expectEqual(@as(usize, 5), fifo.readableLength());
337
338 { // Writes that wrap around
339 try testing.expectEqual(@as(usize, 11), fifo.writableLength());
340 try testing.expectEqual(@as(usize, 6), fifo.writableSlice(0).len);
341 fifo.writeAssumeCapacity("6<chars<11");
342 try testing.expectEqualSlices(u8, "HELLO6<char", fifo.readableSlice(0));
343 try testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(11));
344 try testing.expectEqualSlices(u8, "11", fifo.readableSlice(13));
345 try testing.expectEqualSlices(u8, "", fifo.readableSlice(15));
346 fifo.discard(11);
347 try testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(0));
348 fifo.discard(4);
349 try testing.expectEqual(@as(usize, 0), fifo.readableLength());
350 }
351
352 {
353 const buf = try fifo.writableWithSize(12);
354 try testing.expectEqual(@as(usize, 12), buf.len);
355 var i: u8 = 0;
356 while (i < 10) : (i += 1) {
357 buf[i] = i + 'a';
358 }
359 fifo.update(10);
360 try testing.expectEqualSlices(u8, "abcdefghij", fifo.readableSlice(0));
361 }
362
363 {
364 try fifo.unget("prependedstring");
365 var result: [30]u8 = undefined;
366 try testing.expectEqualSlices(u8, "prependedstringabcdefghij", result[0..fifo.read(&result)]);
367 try fifo.unget("b");
368 try fifo.unget("a");
369 try testing.expectEqualSlices(u8, "ab", result[0..fifo.read(&result)]);
370 }
371
372 fifo.shrink(0);
373
374 {
375 try fifo.writer().print("{s}, {s}!", .{ "Hello", "World" });
376 var result: [30]u8 = undefined;
377 try testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);
378 try testing.expectEqual(@as(usize, 0), fifo.readableLength());
379 }
380
381 {
382 try fifo.writer().writeAll("This is a test");
383 var result: [30]u8 = undefined;
384 try testing.expectEqualSlices(u8, "This", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
385 try testing.expectEqualSlices(u8, "is", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
386 try testing.expectEqualSlices(u8, "a", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
387 try testing.expectEqualSlices(u8, "test", (try fifo.reader().readUntilDelimiterOrEof(&result, ' ')).?);
388 }
389
390 {
391 try fifo.ensureTotalCapacity(1);
392 var in_fbs = std.io.fixedBufferStream("pump test");
393 var out_buf: [50]u8 = undefined;
394 var out_fbs = std.io.fixedBufferStream(&out_buf);
395 try fifo.pump(in_fbs.reader(), out_fbs.writer());
396 try testing.expectEqualSlices(u8, in_fbs.buffer, out_fbs.getWritten());
397 }
398}
399
400test LinearFifo {
401 inline for ([_]type{ u1, u8, u16, u64 }) |T| {
402 const FifoType = LinearFifo(T);
403 var fifo: FifoType = .init(testing.allocator);
404 defer fifo.deinit();
405
406 try fifo.write(&[_]T{ 0, 1, 1, 0, 1 });
407 try testing.expectEqual(@as(usize, 5), fifo.readableLength());
408
409 {
410 try testing.expectEqual(@as(T, 0), fifo.readItem().?);
411 try testing.expectEqual(@as(T, 1), fifo.readItem().?);
412 try testing.expectEqual(@as(T, 1), fifo.readItem().?);
413 try testing.expectEqual(@as(T, 0), fifo.readItem().?);
414 try testing.expectEqual(@as(T, 1), fifo.readItem().?);
415 try testing.expectEqual(@as(usize, 0), fifo.readableLength());
416 }
417
418 {
419 try fifo.writeItem(1);
420 try fifo.writeItem(1);
421 try fifo.writeItem(1);
422 try testing.expectEqual(@as(usize, 3), fifo.readableLength());
423 }
424
425 {
426 var readBuf: [3]T = undefined;
427 const n = fifo.read(&readBuf);
428 try testing.expectEqual(@as(usize, 3), n); // NOTE: It should be the number of items.
429 }
430 }
431}
src/dev.zig+5
...@@ -78,6 +78,7 @@ pub const Env = enum {...@@ -78,6 +78,7 @@ pub const Env = enum {
78 .ast_gen,78 .ast_gen,
79 .sema,79 .sema,
80 .legalize,80 .legalize,
81 .c_compiler,
81 .llvm_backend,82 .llvm_backend,
82 .c_backend,83 .c_backend,
83 .wasm_backend,84 .wasm_backend,
...@@ -127,6 +128,7 @@ pub const Env = enum {...@@ -127,6 +128,7 @@ pub const Env = enum {
127 .clang_command,128 .clang_command,
128 .cc_command,129 .cc_command,
129 .translate_c_command,130 .translate_c_command,
131 .c_compiler,
130 => true,132 => true,
131 else => false,133 else => false,
132 },134 },
...@@ -152,6 +154,7 @@ pub const Env = enum {...@@ -152,6 +154,7 @@ pub const Env = enum {
152 else => Env.ast_gen.supports(feature),154 else => Env.ast_gen.supports(feature),
153 },155 },
154 .cbe => switch (feature) {156 .cbe => switch (feature) {
157 .legalize,
155 .c_backend,158 .c_backend,
156 .c_linker,159 .c_linker,
157 => true,160 => true,
...@@ -248,6 +251,8 @@ pub const Feature = enum {...@@ -248,6 +251,8 @@ pub const Feature = enum {
248 sema,251 sema,
249 legalize,252 legalize,
250253
254 c_compiler,
255
251 llvm_backend,256 llvm_backend,
252 c_backend,257 c_backend,
253 wasm_backend,258 wasm_backend,
src/fmt.zig+13-13
...@@ -1,3 +1,11 @@...@@ -1,3 +1,11 @@
1const std = @import("std");
2const mem = std.mem;
3const fs = std.fs;
4const process = std.process;
5const Allocator = std.mem.Allocator;
6const Color = std.zig.Color;
7const fatal = std.process.fatal;
8
1const usage_fmt =9const usage_fmt =
2 \\Usage: zig fmt [file]...10 \\Usage: zig fmt [file]...
3 \\11 \\
...@@ -52,7 +60,7 @@ pub fn run(...@@ -52,7 +60,7 @@ pub fn run(
52 const arg = args[i];60 const arg = args[i];
53 if (mem.startsWith(u8, arg, "-")) {61 if (mem.startsWith(u8, arg, "-")) {
54 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")) {
55 const stdout = std.io.getStdOut().writer();63 const stdout = std.fs.File.stdout().deprecatedWriter();
56 try stdout.writeAll(usage_fmt);64 try stdout.writeAll(usage_fmt);
57 return process.cleanExit();65 return process.cleanExit();
58 } else if (mem.eql(u8, arg, "--color")) {66 } else if (mem.eql(u8, arg, "--color")) {
...@@ -93,7 +101,7 @@ pub fn run(...@@ -93,7 +101,7 @@ pub fn run(
93 fatal("cannot use --stdin with positional arguments", .{});101 fatal("cannot use --stdin with positional arguments", .{});
94 }102 }
95103
96 const stdin = std.io.getStdIn();104 const stdin: fs.File = .stdin();
97 const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| {105 const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| {
98 fatal("unable to read stdin: {}", .{err});106 fatal("unable to read stdin: {}", .{err});
99 };107 };
...@@ -146,7 +154,7 @@ pub fn run(...@@ -146,7 +154,7 @@ pub fn run(
146 process.exit(code);154 process.exit(code);
147 }155 }
148156
149 return std.io.getStdOut().writeAll(formatted);157 return std.fs.File.stdout().writeAll(formatted);
150 }158 }
151159
152 if (input_files.items.len == 0) {160 if (input_files.items.len == 0) {
...@@ -363,7 +371,7 @@ fn fmtPathFile(...@@ -363,7 +371,7 @@ fn fmtPathFile(
363 return;371 return;
364372
365 if (check_mode) {373 if (check_mode) {
366 const stdout = std.io.getStdOut().writer();374 const stdout = std.fs.File.stdout().deprecatedWriter();
367 try stdout.print("{s}\n", .{file_path});375 try stdout.print("{s}\n", .{file_path});
368 fmt.any_error = true;376 fmt.any_error = true;
369 } else {377 } else {
...@@ -372,15 +380,7 @@ fn fmtPathFile(...@@ -372,15 +380,7 @@ fn fmtPathFile(
372380
373 try af.file.writeAll(fmt.out_buffer.items);381 try af.file.writeAll(fmt.out_buffer.items);
374 try af.finish();382 try af.finish();
375 const stdout = std.io.getStdOut().writer();383 const stdout = std.fs.File.stdout().deprecatedWriter();
376 try stdout.print("{s}\n", .{file_path});384 try stdout.print("{s}\n", .{file_path});
377 }385 }
378}386}
379
380const std = @import("std");
381const mem = std.mem;
382const fs = std.fs;
383const process = std.process;
384const Allocator = std.mem.Allocator;
385const Color = std.zig.Color;
386const fatal = std.process.fatal;
src/libs/freebsd.zig+2-2
...@@ -497,13 +497,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -497,13 +497,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
497 .lt => continue,497 .lt => continue,
498 .gt => {498 .gt => {
499 // TODO Expose via compile error mechanism instead of log.499 // TODO Expose via compile error mechanism instead of log.
500 log.warn("invalid target FreeBSD libc version: {}", .{target_version});500 log.warn("invalid target FreeBSD libc version: {f}", .{target_version});
501 return error.InvalidTargetLibCVersion;501 return error.InvalidTargetLibCVersion;
502 },502 },
503 }503 }
504 } else blk: {504 } else blk: {
505 const latest_index = metadata.all_versions.len - 1;505 const latest_index = metadata.all_versions.len - 1;
506 log.warn("zig cannot build new FreeBSD libc version {}; providing instead {}", .{506 log.warn("zig cannot build new FreeBSD libc version {f}; providing instead {f}", .{
507 target_version, metadata.all_versions[latest_index],507 target_version, metadata.all_versions[latest_index],
508 });508 });
509 break :blk latest_index;509 break :blk latest_index;
src/libs/glibc.zig+2-2
...@@ -736,13 +736,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -736,13 +736,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
736 .lt => continue,736 .lt => continue,
737 .gt => {737 .gt => {
738 // TODO Expose via compile error mechanism instead of log.738 // TODO Expose via compile error mechanism instead of log.
739 log.warn("invalid target glibc version: {}", .{target_version});739 log.warn("invalid target glibc version: {f}", .{target_version});
740 return error.InvalidTargetGLibCVersion;740 return error.InvalidTargetGLibCVersion;
741 },741 },
742 }742 }
743 } else blk: {743 } else blk: {
744 const latest_index = metadata.all_versions.len - 1;744 const latest_index = metadata.all_versions.len - 1;
745 log.warn("zig cannot build new glibc version {}; providing instead {}", .{745 log.warn("zig cannot build new glibc version {f}; providing instead {f}", .{
746 target_version, metadata.all_versions[latest_index],746 target_version, metadata.all_versions[latest_index],
747 });747 });
748 break :blk latest_index;748 break :blk latest_index;
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+3-3
...@@ -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.io.getStdErr().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;
...@@ -326,7 +326,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -326,7 +326,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
326326
327 for (aro_comp.diagnostics.list.items) |diagnostic| {327 for (aro_comp.diagnostics.list.items) |diagnostic| {
328 if (diagnostic.kind == .@"fatal error" or diagnostic.kind == .@"error") {328 if (diagnostic.kind == .@"fatal error" or diagnostic.kind == .@"error") {
329 aro.Diagnostics.render(&aro_comp, std.io.tty.detectConfig(std.io.getStdErr()));329 aro.Diagnostics.render(&aro_comp, std.io.tty.detectConfig(std.fs.File.stderr()));
330 return error.AroPreprocessorFailed;330 return error.AroPreprocessorFailed;
331 }331 }
332 }332 }
...@@ -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/libs/netbsd.zig+2-2
...@@ -442,13 +442,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -442,13 +442,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
442 .lt => continue,442 .lt => continue,
443 .gt => {443 .gt => {
444 // TODO Expose via compile error mechanism instead of log.444 // TODO Expose via compile error mechanism instead of log.
445 log.warn("invalid target NetBSD libc version: {}", .{target_version});445 log.warn("invalid target NetBSD libc version: {f}", .{target_version});
446 return error.InvalidTargetLibCVersion;446 return error.InvalidTargetLibCVersion;
447 },447 },
448 }448 }
449 } else blk: {449 } else blk: {
450 const latest_index = metadata.all_versions.len - 1;450 const latest_index = metadata.all_versions.len - 1;
451 log.warn("zig cannot build new NetBSD libc version {}; providing instead {}", .{451 log.warn("zig cannot build new NetBSD libc version {f}; providing instead {f}", .{
452 target_version, metadata.all_versions[latest_index],452 target_version, metadata.all_versions[latest_index],
453 });453 });
454 break :blk latest_index;454 break :blk latest_index;
src/link.zig+30-28
...@@ -323,7 +323,7 @@ pub const Diags = struct {...@@ -323,7 +323,7 @@ pub const Diags = struct {
323 const main_msg = try m;323 const main_msg = try m;
324 errdefer gpa.free(main_msg);324 errdefer gpa.free(main_msg);
325 try diags.msgs.ensureUnusedCapacity(gpa, 1);325 try diags.msgs.ensureUnusedCapacity(gpa, 1);
326 const note = try std.fmt.allocPrint(gpa, "while parsing {}", .{path});326 const note = try std.fmt.allocPrint(gpa, "while parsing {f}", .{path});
327 errdefer gpa.free(note);327 errdefer gpa.free(note);
328 const notes = try gpa.create([1]Msg);328 const notes = try gpa.create([1]Msg);
329 errdefer gpa.destroy(notes);329 errdefer gpa.destroy(notes);
...@@ -838,8 +838,10 @@ pub const File = struct {...@@ -838,8 +838,10 @@ pub const File = struct {
838 const cached_pp_file_path = the_key.status.success.object_path;838 const cached_pp_file_path = the_key.status.success.object_path;
839 cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| {839 cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| {
840 const diags = &base.comp.link_diags;840 const diags = &base.comp.link_diags;
841 return diags.fail("failed to copy '{'}' to '{'}': {s}", .{841 return diags.fail("failed to copy '{f}' to '{f}': {s}", .{
842 @as(Path, cached_pp_file_path), @as(Path, emit), @errorName(err),842 std.fmt.alt(@as(Path, cached_pp_file_path), .formatEscapeChar),
843 std.fmt.alt(@as(Path, emit), .formatEscapeChar),
844 @errorName(err),
843 });845 });
844 };846 };
845 return;847 return;
...@@ -1351,7 +1353,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1351,7 +1353,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1351 .search_strategy = .paths_first,1353 .search_strategy = .paths_first,
1352 }) catch |archive_err| switch (archive_err) {1354 }) catch |archive_err| switch (archive_err) {
1353 error.LinkFailure => return, // error reported via diags1355 error.LinkFailure => return, // error reported via diags
1354 else => |e| diags.addParseError(dso_path, "failed to parse archive {}: {s}", .{ archive_path, @errorName(e) }),1356 else => |e| diags.addParseError(dso_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }),
1355 };1357 };
1356 },1358 },
1357 error.LinkFailure => return, // error reported via diags1359 error.LinkFailure => return, // error reported via diags
...@@ -1874,7 +1876,7 @@ pub fn resolveInputs(...@@ -1874,7 +1876,7 @@ pub fn resolveInputs(
1874 )) |lib_result| {1876 )) |lib_result| {
1875 switch (lib_result) {1877 switch (lib_result) {
1876 .ok => {},1878 .ok => {},
1877 .no_match => fatal("{}: file not found", .{pq.path}),1879 .no_match => fatal("{f}: file not found", .{pq.path}),
1878 }1880 }
1879 }1881 }
1880 continue;1882 continue;
...@@ -1928,10 +1930,10 @@ fn resolveLibInput(...@@ -1928,10 +1930,10 @@ fn resolveLibInput(
1928 .root_dir = lib_directory,1930 .root_dir = lib_directory,
1929 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}),1931 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}),
1930 };1932 };
1931 try checked_paths.writer(gpa).print("\n {}", .{test_path});1933 try checked_paths.writer(gpa).print("\n {f}", .{test_path});
1932 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {1934 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
1933 error.FileNotFound => break :tbd,1935 error.FileNotFound => break :tbd,
1934 else => |e| fatal("unable to search for tbd library '{}': {s}", .{ test_path, @errorName(e) }),1936 else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }),
1935 };1937 };
1936 errdefer file.close();1938 errdefer file.close();
1937 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);1939 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
...@@ -1947,7 +1949,7 @@ fn resolveLibInput(...@@ -1947,7 +1949,7 @@ fn resolveLibInput(
1947 },1949 },
1948 }),1950 }),
1949 };1951 };
1950 try checked_paths.writer(gpa).print("\n {}", .{test_path});1952 try checked_paths.writer(gpa).print("\n {f}", .{test_path});
1951 switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{1953 switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{
1952 .path = test_path,1954 .path = test_path,
1953 .query = name_query.query,1955 .query = name_query.query,
...@@ -1964,10 +1966,10 @@ fn resolveLibInput(...@@ -1964,10 +1966,10 @@ fn resolveLibInput(
1964 .root_dir = lib_directory,1966 .root_dir = lib_directory,
1965 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}),1967 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}),
1966 };1968 };
1967 try checked_paths.writer(gpa).print("\n {}", .{test_path});1969 try checked_paths.writer(gpa).print("\n {f}", .{test_path});
1968 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {1970 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
1969 error.FileNotFound => break :so,1971 error.FileNotFound => break :so,
1970 else => |e| fatal("unable to search for so library '{}': {s}", .{1972 else => |e| fatal("unable to search for so library '{f}': {s}", .{
1971 test_path, @errorName(e),1973 test_path, @errorName(e),
1972 }),1974 }),
1973 };1975 };
...@@ -1982,10 +1984,10 @@ fn resolveLibInput(...@@ -1982,10 +1984,10 @@ fn resolveLibInput(
1982 .root_dir = lib_directory,1984 .root_dir = lib_directory,
1983 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}),1985 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}),
1984 };1986 };
1985 try checked_paths.writer(gpa).print("\n {}", .{test_path});1987 try checked_paths.writer(gpa).print("\n {f}", .{test_path});
1986 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {1988 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
1987 error.FileNotFound => break :mingw,1989 error.FileNotFound => break :mingw,
1988 else => |e| fatal("unable to search for static library '{}': {s}", .{ test_path, @errorName(e) }),1990 else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }),
1989 };1991 };
1990 errdefer file.close();1992 errdefer file.close();
1991 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);1993 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
...@@ -2037,7 +2039,7 @@ fn resolvePathInput(...@@ -2037,7 +2039,7 @@ fn resolvePathInput(
2037 .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color),2039 .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color),
2038 .object => {2040 .object => {
2039 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|2041 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|
2040 fatal("failed to open object {}: {s}", .{ pq.path, @errorName(err) });2042 fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) });
2041 errdefer file.close();2043 errdefer file.close();
2042 try resolved_inputs.append(gpa, .{ .object = .{2044 try resolved_inputs.append(gpa, .{ .object = .{
2043 .path = pq.path,2045 .path = pq.path,
...@@ -2049,7 +2051,7 @@ fn resolvePathInput(...@@ -2049,7 +2051,7 @@ fn resolvePathInput(
2049 },2051 },
2050 .res => {2052 .res => {
2051 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|2053 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|
2052 fatal("failed to open windows resource {}: {s}", .{ pq.path, @errorName(err) });2054 fatal("failed to open windows resource {f}: {s}", .{ pq.path, @errorName(err) });
2053 errdefer file.close();2055 errdefer file.close();
2054 try resolved_inputs.append(gpa, .{ .res = .{2056 try resolved_inputs.append(gpa, .{ .res = .{
2055 .path = pq.path,2057 .path = pq.path,
...@@ -2057,7 +2059,7 @@ fn resolvePathInput(...@@ -2057,7 +2059,7 @@ fn resolvePathInput(
2057 } });2059 } });
2058 return null;2060 return null;
2059 },2061 },
2060 else => fatal("{}: unrecognized file extension", .{pq.path}),2062 else => fatal("{f}: unrecognized file extension", .{pq.path}),
2061 }2063 }
2062}2064}
20632065
...@@ -2086,14 +2088,14 @@ fn resolvePathInputLib(...@@ -2086,14 +2088,14 @@ fn resolvePathInputLib(
2086 }) {2088 }) {
2087 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {2089 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2088 error.FileNotFound => return .no_match,2090 error.FileNotFound => return .no_match,
2089 else => |e| fatal("unable to search for {s} library '{'}': {s}", .{2091 else => |e| fatal("unable to search for {s} library '{f}': {s}", .{
2090 @tagName(link_mode), test_path, @errorName(e),2092 @tagName(link_mode), std.fmt.alt(test_path, .formatEscapeChar), @errorName(e),
2091 }),2093 }),
2092 };2094 };
2093 errdefer file.close();2095 errdefer file.close();
2094 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));2096 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
2095 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{'}': {s}", .{2097 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f}': {s}", .{
2096 test_path, @errorName(err),2098 std.fmt.alt(test_path, .formatEscapeChar), @errorName(err),
2097 });2099 });
2098 const buf = ld_script_bytes.items[0..n];2100 const buf = ld_script_bytes.items[0..n];
2099 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {2101 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
...@@ -2101,14 +2103,14 @@ fn resolvePathInputLib(...@@ -2101,14 +2103,14 @@ fn resolvePathInputLib(
2101 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);2103 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2102 }2104 }
2103 const stat = file.stat() catch |err|2105 const stat = file.stat() catch |err|
2104 fatal("failed to stat {}: {s}", .{ test_path, @errorName(err) });2106 fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });
2105 const size = std.math.cast(u32, stat.size) orelse2107 const size = std.math.cast(u32, stat.size) orelse
2106 fatal("{}: linker script too big", .{test_path});2108 fatal("{f}: linker script too big", .{test_path});
2107 try ld_script_bytes.resize(gpa, size);2109 try ld_script_bytes.resize(gpa, size);
2108 const buf2 = ld_script_bytes.items[n..];2110 const buf2 = ld_script_bytes.items[n..];
2109 const n2 = file.preadAll(buf2, n) catch |err|2111 const n2 = file.preadAll(buf2, n) catch |err|
2110 fatal("failed to read {}: {s}", .{ test_path, @errorName(err) });2112 fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });
2111 if (n2 != buf2.len) fatal("failed to read {}: unexpected end of file", .{test_path});2113 if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});
2112 var diags = Diags.init(gpa);2114 var diags = Diags.init(gpa);
2113 defer diags.deinit();2115 defer diags.deinit();
2114 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);2116 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);
...@@ -2128,7 +2130,7 @@ fn resolvePathInputLib(...@@ -2128,7 +2130,7 @@ fn resolvePathInputLib(
2128 }2130 }
21292131
2130 var ld_script = ld_script_result catch |err|2132 var ld_script = ld_script_result catch |err|
2131 fatal("{}: failed to parse linker script: {s}", .{ test_path, @errorName(err) });2133 fatal("{f}: failed to parse linker script: {s}", .{ test_path, @errorName(err) });
2132 defer ld_script.deinit(gpa);2134 defer ld_script.deinit(gpa);
21332135
2134 try unresolved_inputs.ensureUnusedCapacity(gpa, ld_script.args.len);2136 try unresolved_inputs.ensureUnusedCapacity(gpa, ld_script.args.len);
...@@ -2159,7 +2161,7 @@ fn resolvePathInputLib(...@@ -2159,7 +2161,7 @@ fn resolvePathInputLib(
21592161
2160 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {2162 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2161 error.FileNotFound => return .no_match,2163 error.FileNotFound => return .no_match,
2162 else => |e| fatal("unable to search for {s} library {}: {s}", .{2164 else => |e| fatal("unable to search for {s} library {f}: {s}", .{
2163 @tagName(link_mode), test_path, @errorName(e),2165 @tagName(link_mode), test_path, @errorName(e),
2164 }),2166 }),
2165 };2167 };
...@@ -2192,19 +2194,19 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso...@@ -2192,19 +2194,19 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso
21922194
2193pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input {2195pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input {
2194 return .{ .object = openObject(path, false, false) catch |err| {2196 return .{ .object = openObject(path, false, false) catch |err| {
2195 return diags.failParse(path, "failed to open {}: {s}", .{ path, @errorName(err) });2197 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2196 } };2198 } };
2197}2199}
21982200
2199pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input {2201pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input {
2200 return .{ .archive = openObject(path, must_link, hidden) catch |err| {2202 return .{ .archive = openObject(path, must_link, hidden) catch |err| {
2201 return diags.failParse(path, "failed to open {}: {s}", .{ path, @errorName(err) });2203 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2202 } };2204 } };
2203}2205}
22042206
2205pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input {2207pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input {
2206 return .{ .dso = openDso(path, needed, weak, reexport) catch |err| {2208 return .{ .dso = openDso(path, needed, weak, reexport) catch |err| {
2207 return diags.failParse(path, "failed to open {}: {s}", .{ path, @errorName(err) });2209 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2208 } };2210 } };
2209}2211}
22102212
src/link/C.zig+177-153
...@@ -25,34 +25,34 @@ base: link.File,...@@ -25,34 +25,34 @@ base: link.File,
25/// This linker backend does not try to incrementally link output C source code.25/// This linker backend does not try to incrementally link output C source code.
26/// Instead, it tracks all declarations in this table, and iterates over it26/// Instead, it tracks all declarations in this table, and iterates over it
27/// in the flush function, stitching pre-rendered pieces of C code together.27/// in the flush function, stitching pre-rendered pieces of C code together.
28navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock) = .empty,28navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock),
29/// All the string bytes of rendered C code, all squished into one array.29/// All the string bytes of rendered C code, all squished into one array.
30/// While in progress, a separate buffer is used, and then when finished, the30/// While in progress, a separate buffer is used, and then when finished, the
31/// buffer is copied into this one.31/// buffer is copied into this one.
32string_bytes: std.ArrayListUnmanaged(u8) = .empty,32string_bytes: std.ArrayListUnmanaged(u8),
33/// Tracks all the anonymous decls that are used by all the decls so they can33/// Tracks all the anonymous decls that are used by all the decls so they can
34/// be rendered during flush().34/// be rendered during flush().
35uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock) = .empty,35uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock),
36/// Sparse set of uavs that are overaligned. Underaligned anon decls are36/// Sparse set of uavs that are overaligned. Underaligned anon decls are
37/// lowered the same as ABI-aligned anon decls. The keys here are a subset of37/// lowered the same as ABI-aligned anon decls. The keys here are a subset of
38/// the keys of `uavs`.38/// the keys of `uavs`.
39aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty,39aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
4040
41exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock) = .empty,41exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock),
42exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .empty,42exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock),
4343
44/// Optimization, `updateDecl` reuses this buffer rather than creating a new44/// Optimization, `updateDecl` reuses this buffer rather than creating a new
45/// one with every call.45/// one with every call.
46fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty,46fwd_decl_buf: []u8,
47/// Optimization, `updateDecl` reuses this buffer rather than creating a new47/// Optimization, `updateDecl` reuses this buffer rather than creating a new
48/// one with every call.48/// one with every call.
49code_buf: std.ArrayListUnmanaged(u8) = .empty,49code_header_buf: []u8,
50/// Optimization, `flush` reuses this buffer rather than creating a new50/// Optimization, `updateDecl` reuses this buffer rather than creating a new
51/// one with every call.51/// one with every call.
52lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty,52code_buf: []u8,
53/// Optimization, `flush` reuses this buffer rather than creating a new53/// Optimization, `flush` reuses this buffer rather than creating a new
54/// one with every call.54/// one with every call.
55lazy_code_buf: std.ArrayListUnmanaged(u8) = .empty,55scratch_buf: []u32,
5656
57/// A reference into `string_bytes`.57/// A reference into `string_bytes`.
58const String = extern struct {58const String = extern struct {
...@@ -63,15 +63,23 @@ const String = extern struct {...@@ -63,15 +63,23 @@ const String = extern struct {
63 .start = 0,63 .start = 0,
64 .len = 0,64 .len = 0,
65 };65 };
66
67 fn concat(lhs: String, rhs: String) String {
68 assert(lhs.start + lhs.len == rhs.start);
69 return .{
70 .start = lhs.start,
71 .len = lhs.len + rhs.len,
72 };
73 }
66};74};
6775
68/// Per-declaration data.76/// Per-declaration data.
69pub const AvBlock = struct {77pub const AvBlock = struct {
70 code: String = String.empty,78 fwd_decl: String = .empty,
71 fwd_decl: String = String.empty,79 code: String = .empty,
72 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate80 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
73 /// over each `Decl` and generate the definition for each used `CType` once.81 /// over each `Decl` and generate the definition for each used `CType` once.
74 ctype_pool: codegen.CType.Pool = codegen.CType.Pool.empty,82 ctype_pool: codegen.CType.Pool = .empty,
75 /// May contain string references to ctype_pool83 /// May contain string references to ctype_pool
76 lazy_fns: codegen.LazyFnMap = .{},84 lazy_fns: codegen.LazyFnMap = .{},
7785
...@@ -84,7 +92,7 @@ pub const AvBlock = struct {...@@ -84,7 +92,7 @@ pub const AvBlock = struct {
8492
85/// Per-exported-symbol data.93/// Per-exported-symbol data.
86pub const ExportedBlock = struct {94pub const ExportedBlock = struct {
87 fwd_decl: String = String.empty,95 fwd_decl: String = .empty,
88};96};
8997
90pub fn getString(this: C, s: String) []const u8 {98pub fn getString(this: C, s: String) []const u8 {
...@@ -147,6 +155,16 @@ pub fn createEmpty(...@@ -147,6 +155,16 @@ pub fn createEmpty(
147 .file = file,155 .file = file,
148 .build_id = options.build_id,156 .build_id = options.build_id,
149 },157 },
158 .navs = .empty,
159 .string_bytes = .empty,
160 .uavs = .empty,
161 .aligned_uavs = .empty,
162 .exported_navs = .empty,
163 .exported_uavs = .empty,
164 .fwd_decl_buf = &.{},
165 .code_header_buf = &.{},
166 .code_buf = &.{},
167 .scratch_buf = &.{},
150 };168 };
151169
152 return c_file;170 return c_file;
...@@ -170,10 +188,10 @@ pub fn deinit(self: *C) void {...@@ -170,10 +188,10 @@ pub fn deinit(self: *C) void {
170 self.exported_uavs.deinit(gpa);188 self.exported_uavs.deinit(gpa);
171189
172 self.string_bytes.deinit(gpa);190 self.string_bytes.deinit(gpa);
173 self.fwd_decl_buf.deinit(gpa);191 gpa.free(self.fwd_decl_buf);
174 self.code_buf.deinit(gpa);192 gpa.free(self.code_header_buf);
175 self.lazy_fwd_decl_buf.deinit(gpa);193 gpa.free(self.code_buf);
176 self.lazy_code_buf.deinit(gpa);194 gpa.free(self.scratch_buf);
177}195}
178196
179pub fn updateFunc(197pub fn updateFunc(
...@@ -194,20 +212,17 @@ pub fn updateFunc(...@@ -194,20 +212,17 @@ pub fn updateFunc(
194 .ctype_pool = mir.c.ctype_pool.move(),212 .ctype_pool = mir.c.ctype_pool.move(),
195 .lazy_fns = mir.c.lazy_fns.move(),213 .lazy_fns = mir.c.lazy_fns.move(),
196 };214 };
197 gop.value_ptr.code = try self.addString(mir.c.code);
198 gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl);215 gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl);
216 const code_header = try self.addString(mir.c.code_header);
217 const code = try self.addString(mir.c.code);
218 gop.value_ptr.code = code_header.concat(code);
199 try self.addUavsFromCodegen(&mir.c.uavs);219 try self.addUavsFromCodegen(&mir.c.uavs);
200}220}
201221
202fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {222fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) link.File.FlushError!void {
203 const gpa = self.base.comp.gpa;223 const gpa = self.base.comp.gpa;
204 const uav = self.uavs.keys()[i];224 const uav = self.uavs.keys()[i];
205225
206 const fwd_decl = &self.fwd_decl_buf;
207 const code = &self.code_buf;
208 fwd_decl.clearRetainingCapacity();
209 code.clearRetainingCapacity();
210
211 var object: codegen.Object = .{226 var object: codegen.Object = .{
212 .dg = .{227 .dg = .{
213 .gpa = gpa,228 .gpa = gpa,
...@@ -217,21 +232,24 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {...@@ -217,21 +232,24 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
217 .pass = .{ .uav = uav },232 .pass = .{ .uav = uav },
218 .is_naked_fn = false,233 .is_naked_fn = false,
219 .expected_block = null,234 .expected_block = null,
220 .fwd_decl = fwd_decl.toManaged(gpa),235 .fwd_decl = undefined,
221 .ctype_pool = codegen.CType.Pool.empty,236 .ctype_pool = .empty,
222 .scratch = .{},237 .scratch = .initBuffer(self.scratch_buf),
223 .uavs = .empty,238 .uavs = .empty,
224 },239 },
225 .code = code.toManaged(gpa),240 .code_header = undefined,
226 .indent_writer = undefined, // set later so we can get a pointer to object.code241 .code = undefined,
242 .indent_counter = 0,
227 };243 };
228 object.indent_writer = .{ .underlying_writer = object.code.writer() };244 object.dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf);
245 object.code = .initOwnedSlice(gpa, self.code_buf);
229 defer {246 defer {
230 object.dg.uavs.deinit(gpa);247 object.dg.uavs.deinit(gpa);
231 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
232 object.dg.ctype_pool.deinit(object.dg.gpa);248 object.dg.ctype_pool.deinit(object.dg.gpa);
233 object.dg.scratch.deinit(gpa);249
234 code.* = object.code.moveToUnmanaged();250 self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice();
251 self.code_buf = object.code.toArrayList().allocatedSlice();
252 self.scratch_buf = object.dg.scratch.allocatedSlice();
235 }253 }
236 try object.dg.ctype_pool.init(gpa);254 try object.dg.ctype_pool.init(gpa);
237255
...@@ -243,15 +261,15 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {...@@ -243,15 +261,15 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
243 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);261 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
244 //return;262 //return;
245 },263 },
246 else => |e| return e,264 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
247 };265 };
248266
249 try self.addUavsFromCodegen(&object.dg.uavs);267 try self.addUavsFromCodegen(&object.dg.uavs);
250268
251 object.dg.ctype_pool.freeUnusedCapacity(gpa);269 object.dg.ctype_pool.freeUnusedCapacity(gpa);
252 self.uavs.values()[i] = .{270 self.uavs.values()[i] = .{
253 .code = try self.addString(object.code.items),271 .fwd_decl = try self.addString(object.dg.fwd_decl.getWritten()),
254 .fwd_decl = try self.addString(object.dg.fwd_decl.items),272 .code = try self.addString(object.code.getWritten()),
255 .ctype_pool = object.dg.ctype_pool.move(),273 .ctype_pool = object.dg.ctype_pool.move(),
256 };274 };
257}275}
...@@ -277,12 +295,8 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l...@@ -277,12 +295,8 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
277 errdefer _ = self.navs.pop();295 errdefer _ = self.navs.pop();
278 if (!gop.found_existing) gop.value_ptr.* = .{};296 if (!gop.found_existing) gop.value_ptr.* = .{};
279 const ctype_pool = &gop.value_ptr.ctype_pool;297 const ctype_pool = &gop.value_ptr.ctype_pool;
280 const fwd_decl = &self.fwd_decl_buf;
281 const code = &self.code_buf;
282 try ctype_pool.init(gpa);298 try ctype_pool.init(gpa);
283 ctype_pool.clearRetainingCapacity();299 ctype_pool.clearRetainingCapacity();
284 fwd_decl.clearRetainingCapacity();
285 code.clearRetainingCapacity();
286300
287 var object: codegen.Object = .{301 var object: codegen.Object = .{
288 .dg = .{302 .dg = .{
...@@ -293,22 +307,25 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l...@@ -293,22 +307,25 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
293 .pass = .{ .nav = nav_index },307 .pass = .{ .nav = nav_index },
294 .is_naked_fn = false,308 .is_naked_fn = false,
295 .expected_block = null,309 .expected_block = null,
296 .fwd_decl = fwd_decl.toManaged(gpa),310 .fwd_decl = undefined,
297 .ctype_pool = ctype_pool.*,311 .ctype_pool = ctype_pool.*,
298 .scratch = .{},312 .scratch = .initBuffer(self.scratch_buf),
299 .uavs = .empty,313 .uavs = .empty,
300 },314 },
301 .code = code.toManaged(gpa),315 .code_header = undefined,
302 .indent_writer = undefined, // set later so we can get a pointer to object.code316 .code = undefined,
317 .indent_counter = 0,
303 };318 };
304 object.indent_writer = .{ .underlying_writer = object.code.writer() };319 object.dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf);
320 object.code = .initOwnedSlice(gpa, self.code_buf);
305 defer {321 defer {
306 object.dg.uavs.deinit(gpa);322 object.dg.uavs.deinit(gpa);
307 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
308 ctype_pool.* = object.dg.ctype_pool.move();323 ctype_pool.* = object.dg.ctype_pool.move();
309 ctype_pool.freeUnusedCapacity(gpa);324 ctype_pool.freeUnusedCapacity(gpa);
310 object.dg.scratch.deinit(gpa);325
311 code.* = object.code.moveToUnmanaged();326 self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice();
327 self.code_buf = object.code.toArrayList().allocatedSlice();
328 self.scratch_buf = object.dg.scratch.allocatedSlice();
312 }329 }
313330
314 codegen.genDecl(&object) catch |err| switch (err) {331 codegen.genDecl(&object) catch |err| switch (err) {
...@@ -316,10 +333,10 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l...@@ -316,10 +333,10 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
316 error.CodegenFail => return,333 error.CodegenFail => return,
317 error.OutOfMemory => |e| return e,334 error.OutOfMemory => |e| return e,
318 },335 },
319 else => |e| return e,336 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
320 };337 };
321 gop.value_ptr.code = try self.addString(object.code.items);338 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.getWritten());
322 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);339 gop.value_ptr.code = try self.addString(object.code.getWritten());
323 try self.addUavsFromCodegen(&object.dg.uavs);340 try self.addUavsFromCodegen(&object.dg.uavs);
324}341}
325342
...@@ -331,19 +348,14 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn...@@ -331,19 +348,14 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn
331 _ = ti_id;348 _ = ti_id;
332}349}
333350
334fn abiDefines(self: *C, target: *const std.Target) !std.ArrayList(u8) {351fn abiDefines(w: *std.io.Writer, target: *const std.Target) !void {
335 const gpa = self.base.comp.gpa;
336 var defines = std.ArrayList(u8).init(gpa);
337 errdefer defines.deinit();
338 const writer = defines.writer();
339 switch (target.abi) {352 switch (target.abi) {
340 .msvc, .itanium => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),353 .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
341 else => {},354 else => {},
342 }355 }
343 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{356 try w.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
344 target.cMaxIntAlignment(),357 target.cMaxIntAlignment(),
345 });358 });
346 return defines;
347}359}
348360
349pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {361pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
...@@ -374,37 +386,47 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P...@@ -374,37 +386,47 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
374 // emit-h is in `flushEmitH` below.386 // emit-h is in `flushEmitH` below.
375387
376 var f: Flush = .{388 var f: Flush = .{
377 .ctype_pool = codegen.CType.Pool.empty,389 .ctype_pool = .empty,
378 .lazy_ctype_pool = codegen.CType.Pool.empty,390 .ctype_global_from_decl_map = .empty,
391 .ctypes = .empty,
392
393 .lazy_ctype_pool = .empty,
394 .lazy_fns = .empty,
395 .lazy_fwd_decl = .empty,
396 .lazy_code = .empty,
397
398 .all_buffers = .empty,
399 .file_size = 0,
379 };400 };
380 defer f.deinit(gpa);401 defer f.deinit(gpa);
381402
382 const abi_defines = try self.abiDefines(zcu.getTarget());403 var abi_defines_aw: std.io.Writer.Allocating = .init(gpa);
383 defer abi_defines.deinit();404 defer abi_defines_aw.deinit();
405 abiDefines(&abi_defines_aw.writer, zcu.getTarget()) catch |err| switch (err) {
406 error.WriteFailed => return error.OutOfMemory,
407 };
384408
385 // Covers defines, zig.h, ctypes, asm, lazy fwd.409 // Covers defines, zig.h, ctypes, asm, lazy fwd.
386 try f.all_buffers.ensureUnusedCapacity(gpa, 5);410 try f.all_buffers.ensureUnusedCapacity(gpa, 5);
387411
388 f.appendBufAssumeCapacity(abi_defines.items);412 f.appendBufAssumeCapacity(abi_defines_aw.getWritten());
389 f.appendBufAssumeCapacity(zig_h);413 f.appendBufAssumeCapacity(zig_h);
390414
391 const ctypes_index = f.all_buffers.items.len;415 const ctypes_index = f.all_buffers.items.len;
392 f.all_buffers.items.len += 1;416 f.all_buffers.items.len += 1;
393417
394 {418 var asm_aw: std.io.Writer.Allocating = .init(gpa);
395 var asm_buf = f.asm_buf.toManaged(gpa);419 defer asm_aw.deinit();
396 defer f.asm_buf = asm_buf.moveToUnmanaged();420 codegen.genGlobalAsm(zcu, &asm_aw.writer) catch |err| switch (err) {
397 try codegen.genGlobalAsm(zcu, asm_buf.writer());421 error.WriteFailed => return error.OutOfMemory,
398 f.appendBufAssumeCapacity(asm_buf.items);422 };
399 }423 f.appendBufAssumeCapacity(asm_aw.getWritten());
400424
401 const lazy_index = f.all_buffers.items.len;425 const lazy_index = f.all_buffers.items.len;
402 f.all_buffers.items.len += 1;426 f.all_buffers.items.len += 1;
403427
404 self.lazy_fwd_decl_buf.clearRetainingCapacity();
405 self.lazy_code_buf.clearRetainingCapacity();
406 try f.lazy_ctype_pool.init(gpa);428 try f.lazy_ctype_pool.init(gpa);
407 try self.flushErrDecls(pt, &f.lazy_ctype_pool);429 try self.flushErrDecls(pt, &f);
408430
409 // Unlike other backends, the .c code we are emitting has order-dependent decls.431 // Unlike other backends, the .c code we are emitting has order-dependent decls.
410 // `CType`s, forward decls, and non-functions first.432 // `CType`s, forward decls, and non-functions first.
...@@ -462,22 +484,15 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P...@@ -462,22 +484,15 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
462 }484 }
463 }485 }
464486
465 f.all_buffers.items[ctypes_index] = .{487 f.all_buffers.items[ctypes_index] = f.ctypes.items;
466 .base = if (f.ctypes_buf.items.len > 0) f.ctypes_buf.items.ptr else "",488 f.file_size += f.ctypes.items.len;
467 .len = f.ctypes_buf.items.len,
468 };
469 f.file_size += f.ctypes_buf.items.len;
470489
471 const lazy_fwd_decl_len = self.lazy_fwd_decl_buf.items.len;490 f.all_buffers.items[lazy_index] = f.lazy_fwd_decl.items;
472 f.all_buffers.items[lazy_index] = .{491 f.file_size += f.lazy_fwd_decl.items.len;
473 .base = if (lazy_fwd_decl_len > 0) self.lazy_fwd_decl_buf.items.ptr else "",
474 .len = lazy_fwd_decl_len,
475 };
476 f.file_size += lazy_fwd_decl_len;
477492
478 // Now the code.493 // Now the code.
479 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2);494 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2);
480 f.appendBufAssumeCapacity(self.lazy_code_buf.items);495 f.appendBufAssumeCapacity(f.lazy_code.items);
481 for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity(496 for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity(
482 if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) {497 if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) {
483 .@"extern" => .zig_extern,498 .@"extern" => .zig_extern,
...@@ -493,31 +508,35 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P...@@ -493,31 +508,35 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
493508
494 const file = self.base.file.?;509 const file = self.base.file.?;
495 file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)});510 file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)});
496 file.pwritevAll(f.all_buffers.items, 0) catch |err| return diags.fail("failed to write to '{'}': {s}", .{511 var fw = file.writer(&.{});
497 self.base.emit, @errorName(err),512 var w = &fw.interface;
498 });513 w.writeVecAll(f.all_buffers.items) catch |err| switch (err) {
514 error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{
515 std.fmt.alt(self.base.emit, .formatEscapeChar), @errorName(fw.err.?),
516 }),
517 };
499}518}
500519
501const Flush = struct {520const Flush = struct {
502 ctype_pool: codegen.CType.Pool,521 ctype_pool: codegen.CType.Pool,
503 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .empty,522 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType),
504 ctypes_buf: std.ArrayListUnmanaged(u8) = .empty,523 ctypes: std.ArrayListUnmanaged(u8),
505524
506 lazy_ctype_pool: codegen.CType.Pool,525 lazy_ctype_pool: codegen.CType.Pool,
507 lazy_fns: LazyFns = .{},526 lazy_fns: LazyFns,
508527 lazy_fwd_decl: std.ArrayListUnmanaged(u8),
509 asm_buf: std.ArrayListUnmanaged(u8) = .empty,528 lazy_code: std.ArrayListUnmanaged(u8),
510529
511 /// We collect a list of buffers to write, and write them all at once with pwritev 😎530 /// We collect a list of buffers to write, and write them all at once with pwritev 😎
512 all_buffers: std.ArrayListUnmanaged(std.posix.iovec_const) = .empty,531 all_buffers: std.ArrayListUnmanaged([]const u8),
513 /// Keeps track of the total bytes of `all_buffers`.532 /// Keeps track of the total bytes of `all_buffers`.
514 file_size: u64 = 0,533 file_size: u64,
515534
516 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);535 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);
517536
518 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {537 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {
519 if (buf.len == 0) return;538 if (buf.len == 0) return;
520 f.all_buffers.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len });539 f.all_buffers.appendAssumeCapacity(buf);
521 f.file_size += buf.len;540 f.file_size += buf.len;
522 }541 }
523542
...@@ -532,14 +551,15 @@ const Flush = struct {...@@ -532,14 +551,15 @@ const Flush = struct {
532 }551 }
533552
534 fn deinit(f: *Flush, gpa: Allocator) void {553 fn deinit(f: *Flush, gpa: Allocator) void {
535 f.all_buffers.deinit(gpa);554 f.ctype_pool.deinit(gpa);
536 f.asm_buf.deinit(gpa);
537 f.lazy_fns.deinit(gpa);
538 f.lazy_ctype_pool.deinit(gpa);
539 f.ctypes_buf.deinit(gpa);
540 assert(f.ctype_global_from_decl_map.items.len == 0);555 assert(f.ctype_global_from_decl_map.items.len == 0);
541 f.ctype_global_from_decl_map.deinit(gpa);556 f.ctype_global_from_decl_map.deinit(gpa);
542 f.ctype_pool.deinit(gpa);557 f.ctypes.deinit(gpa);
558 f.lazy_ctype_pool.deinit(gpa);
559 f.lazy_fns.deinit(gpa);
560 f.lazy_fwd_decl.deinit(gpa);
561 f.lazy_code.deinit(gpa);
562 f.all_buffers.deinit(gpa);
543 }563 }
544};564};
545565
...@@ -562,9 +582,9 @@ fn flushCTypes(...@@ -562,9 +582,9 @@ fn flushCTypes(
562 try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len);582 try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len);
563 defer global_from_decl_map.clearRetainingCapacity();583 defer global_from_decl_map.clearRetainingCapacity();
564584
565 var ctypes_buf = f.ctypes_buf.toManaged(gpa);585 var ctypes_aw: std.io.Writer.Allocating = .fromArrayList(gpa, &f.ctypes);
566 defer f.ctypes_buf = ctypes_buf.moveToUnmanaged();586 const ctypes_bw = &ctypes_aw.writer;
567 const writer = ctypes_buf.writer();587 defer f.ctypes = ctypes_aw.toArrayList();
568588
569 for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| {589 for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| {
570 const PoolAdapter = struct {590 const PoolAdapter = struct {
...@@ -591,26 +611,25 @@ fn flushCTypes(...@@ -591,26 +611,25 @@ fn flushCTypes(
591 PoolAdapter{ .global_from_decl_map = global_from_decl_map.items },611 PoolAdapter{ .global_from_decl_map = global_from_decl_map.items },
592 );612 );
593 global_from_decl_map.appendAssumeCapacity(global_ctype);613 global_from_decl_map.appendAssumeCapacity(global_ctype);
594 try codegen.genTypeDecl(614 codegen.genTypeDecl(
595 zcu,615 zcu,
596 writer,616 ctypes_bw,
597 global_ctype_pool,617 global_ctype_pool,
598 global_ctype,618 global_ctype,
599 pass,619 pass,
600 decl_ctype_pool,620 decl_ctype_pool,
601 decl_ctype,621 decl_ctype,
602 found_existing,622 found_existing,
603 );623 ) catch |err| switch (err) {
624 error.WriteFailed => return error.OutOfMemory,
625 };
604 }626 }
605}627}
606628
607fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) FlushDeclError!void {629fn flushErrDecls(self: *C, pt: Zcu.PerThread, f: *Flush) FlushDeclError!void {
608 const gpa = self.base.comp.gpa;630 const gpa = self.base.comp.gpa;
609631
610 const fwd_decl = &self.lazy_fwd_decl_buf;632 var object: codegen.Object = .{
611 const code = &self.lazy_code_buf;
612
613 var object = codegen.Object{
614 .dg = .{633 .dg = .{
615 .gpa = gpa,634 .gpa = gpa,
616 .pt = pt,635 .pt = pt,
...@@ -619,27 +638,30 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F...@@ -619,27 +638,30 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
619 .pass = .flush,638 .pass = .flush,
620 .is_naked_fn = false,639 .is_naked_fn = false,
621 .expected_block = null,640 .expected_block = null,
622 .fwd_decl = fwd_decl.toManaged(gpa),641 .fwd_decl = undefined,
623 .ctype_pool = ctype_pool.*,642 .ctype_pool = f.lazy_ctype_pool,
624 .scratch = .{},643 .scratch = .initBuffer(self.scratch_buf),
625 .uavs = .empty,644 .uavs = .empty,
626 },645 },
627 .code = code.toManaged(gpa),646 .code_header = undefined,
628 .indent_writer = undefined, // set later so we can get a pointer to object.code647 .code = undefined,
648 .indent_counter = 0,
629 };649 };
630 object.indent_writer = .{ .underlying_writer = object.code.writer() };650 object.dg.fwd_decl = .fromArrayList(gpa, &f.lazy_fwd_decl);
651 object.code = .fromArrayList(gpa, &f.lazy_code);
631 defer {652 defer {
632 object.dg.uavs.deinit(gpa);653 object.dg.uavs.deinit(gpa);
633 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();654 f.lazy_ctype_pool = object.dg.ctype_pool.move();
634 ctype_pool.* = object.dg.ctype_pool.move();655 f.lazy_ctype_pool.freeUnusedCapacity(gpa);
635 ctype_pool.freeUnusedCapacity(gpa);656
636 object.dg.scratch.deinit(gpa);657 f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList();
637 code.* = object.code.moveToUnmanaged();658 f.lazy_code = object.code.toArrayList();
659 self.scratch_buf = object.dg.scratch.allocatedSlice();
638 }660 }
639661
640 codegen.genErrDecls(&object) catch |err| switch (err) {662 codegen.genErrDecls(&object) catch |err| switch (err) {
641 error.AnalysisFail => unreachable,663 error.AnalysisFail => unreachable,
642 else => |e| return e,664 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
643 };665 };
644666
645 try self.addUavsFromCodegen(&object.dg.uavs);667 try self.addUavsFromCodegen(&object.dg.uavs);
...@@ -649,16 +671,13 @@ fn flushLazyFn(...@@ -649,16 +671,13 @@ fn flushLazyFn(
649 self: *C,671 self: *C,
650 pt: Zcu.PerThread,672 pt: Zcu.PerThread,
651 mod: *Module,673 mod: *Module,
652 ctype_pool: *codegen.CType.Pool,674 f: *Flush,
653 lazy_ctype_pool: *const codegen.CType.Pool,675 lazy_ctype_pool: *const codegen.CType.Pool,
654 lazy_fn: codegen.LazyFnMap.Entry,676 lazy_fn: codegen.LazyFnMap.Entry,
655) FlushDeclError!void {677) FlushDeclError!void {
656 const gpa = self.base.comp.gpa;678 const gpa = self.base.comp.gpa;
657679
658 const fwd_decl = &self.lazy_fwd_decl_buf;680 var object: codegen.Object = .{
659 const code = &self.lazy_code_buf;
660
661 var object = codegen.Object{
662 .dg = .{681 .dg = .{
663 .gpa = gpa,682 .gpa = gpa,
664 .pt = pt,683 .pt = pt,
...@@ -667,29 +686,32 @@ fn flushLazyFn(...@@ -667,29 +686,32 @@ fn flushLazyFn(
667 .pass = .flush,686 .pass = .flush,
668 .is_naked_fn = false,687 .is_naked_fn = false,
669 .expected_block = null,688 .expected_block = null,
670 .fwd_decl = fwd_decl.toManaged(gpa),689 .fwd_decl = undefined,
671 .ctype_pool = ctype_pool.*,690 .ctype_pool = f.lazy_ctype_pool,
672 .scratch = .{},691 .scratch = .initBuffer(self.scratch_buf),
673 .uavs = .empty,692 .uavs = .empty,
674 },693 },
675 .code = code.toManaged(gpa),694 .code_header = undefined,
676 .indent_writer = undefined, // set later so we can get a pointer to object.code695 .code = undefined,
696 .indent_counter = 0,
677 };697 };
678 object.indent_writer = .{ .underlying_writer = object.code.writer() };698 object.dg.fwd_decl = .fromArrayList(gpa, &f.lazy_fwd_decl);
699 object.code = .fromArrayList(gpa, &f.lazy_code);
679 defer {700 defer {
680 // If this assert trips just handle the anon_decl_deps the same as701 // If this assert trips just handle the anon_decl_deps the same as
681 // `updateFunc()` does.702 // `updateFunc()` does.
682 assert(object.dg.uavs.count() == 0);703 assert(object.dg.uavs.count() == 0);
683 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();704 f.lazy_ctype_pool = object.dg.ctype_pool.move();
684 ctype_pool.* = object.dg.ctype_pool.move();705 f.lazy_ctype_pool.freeUnusedCapacity(gpa);
685 ctype_pool.freeUnusedCapacity(gpa);706
686 object.dg.scratch.deinit(gpa);707 f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList();
687 code.* = object.code.moveToUnmanaged();708 f.lazy_code = object.code.toArrayList();
709 self.scratch_buf = object.dg.scratch.allocatedSlice();
688 }710 }
689711
690 codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) {712 codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) {
691 error.AnalysisFail => unreachable,713 error.AnalysisFail => unreachable,
692 else => |e| return e,714 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
693 };715 };
694}716}
695717
...@@ -709,7 +731,7 @@ fn flushLazyFns(...@@ -709,7 +731,7 @@ fn flushLazyFns(
709 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);731 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
710 if (gop.found_existing) continue;732 if (gop.found_existing) continue;
711 gop.value_ptr.* = {};733 gop.value_ptr.* = {};
712 try self.flushLazyFn(pt, mod, &f.lazy_ctype_pool, lazy_ctype_pool, entry);734 try self.flushLazyFn(pt, mod, f, lazy_ctype_pool, entry);
713 }735 }
714}736}
715737
...@@ -802,8 +824,6 @@ pub fn updateExports(...@@ -802,8 +824,6 @@ pub fn updateExports(
802 },824 },
803 };825 };
804 const ctype_pool = &decl_block.ctype_pool;826 const ctype_pool = &decl_block.ctype_pool;
805 const fwd_decl = &self.fwd_decl_buf;
806 fwd_decl.clearRetainingCapacity();
807 var dg: codegen.DeclGen = .{827 var dg: codegen.DeclGen = .{
808 .gpa = gpa,828 .gpa = gpa,
809 .pt = pt,829 .pt = pt,
...@@ -812,20 +832,24 @@ pub fn updateExports(...@@ -812,20 +832,24 @@ pub fn updateExports(
812 .pass = pass,832 .pass = pass,
813 .is_naked_fn = false,833 .is_naked_fn = false,
814 .expected_block = null,834 .expected_block = null,
815 .fwd_decl = fwd_decl.toManaged(gpa),835 .fwd_decl = undefined,
816 .ctype_pool = decl_block.ctype_pool,836 .ctype_pool = decl_block.ctype_pool,
817 .scratch = .{},837 .scratch = .initBuffer(self.scratch_buf),
818 .uavs = .empty,838 .uavs = .empty,
819 };839 };
840 dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf);
820 defer {841 defer {
821 assert(dg.uavs.count() == 0);842 assert(dg.uavs.count() == 0);
822 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
823 ctype_pool.* = dg.ctype_pool.move();843 ctype_pool.* = dg.ctype_pool.move();
824 ctype_pool.freeUnusedCapacity(gpa);844 ctype_pool.freeUnusedCapacity(gpa);
825 dg.scratch.deinit(gpa);845
846 self.fwd_decl_buf = dg.fwd_decl.toArrayList().allocatedSlice();
847 self.scratch_buf = dg.scratch.allocatedSlice();
826 }848 }
827 try codegen.genExports(&dg, exported, export_indices);849 codegen.genExports(&dg, exported, export_indices) catch |err| switch (err) {
828 exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.items) };850 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
851 };
852 exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.getWritten()) };
829}853}
830854
831pub fn deleteExport(855pub fn deleteExport(
src/link/Coff.zig+26-41
...@@ -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 {
...@@ -1213,7 +1213,7 @@ fn updateLazySymbolAtom(...@@ -1213,7 +1213,7 @@ fn updateLazySymbolAtom(
1213 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;1213 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
1214 defer code_buffer.deinit(gpa);1214 defer code_buffer.deinit(gpa);
12151215
1216 const name = try allocPrint(gpa, "__lazy_{s}_{}", .{1216 const name = try allocPrint(gpa, "__lazy_{s}_{f}", .{
1217 @tagName(sym.kind),1217 @tagName(sym.kind),
1218 Type.fromInterned(sym.ty).fmt(pt),1218 Type.fromInterned(sym.ty).fmt(pt),
1219 });1219 });
...@@ -1333,7 +1333,7 @@ fn updateNavCode(...@@ -1333,7 +1333,7 @@ fn updateNavCode(
1333 const ip = &zcu.intern_pool;1333 const ip = &zcu.intern_pool;
1334 const nav = ip.getNav(nav_index);1334 const nav = ip.getNav(nav_index);
13351335
1336 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });1336 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
13371337
1338 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;1338 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
1339 const required_alignment = switch (pt.navAlignment(nav_index)) {1339 const required_alignment = switch (pt.navAlignment(nav_index)) {
...@@ -1361,7 +1361,7 @@ fn updateNavCode(...@@ -1361,7 +1361,7 @@ fn updateNavCode(
1361 error.OutOfMemory => return error.OutOfMemory,1361 error.OutOfMemory => return error.OutOfMemory,
1362 else => |e| return coff.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(e)}),1362 else => |e| return coff.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(e)}),
1363 };1363 };
1364 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), sym.value, vaddr });1364 log.debug("growing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), sym.value, vaddr });
1365 log.debug(" (required alignment 0x{x}", .{required_alignment});1365 log.debug(" (required alignment 0x{x}", .{required_alignment});
13661366
1367 if (vaddr != sym.value) {1367 if (vaddr != sym.value) {
...@@ -1389,7 +1389,7 @@ fn updateNavCode(...@@ -1389,7 +1389,7 @@ fn updateNavCode(
1389 else => |e| return coff.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(e)}),1389 else => |e| return coff.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(e)}),
1390 };1390 };
1391 errdefer coff.freeAtom(atom_index);1391 errdefer coff.freeAtom(atom_index);
1392 log.debug("allocated atom for {} at 0x{x}", .{ nav.fqn.fmt(ip), vaddr });1392 log.debug("allocated atom for {f} at 0x{x}", .{ nav.fqn.fmt(ip), vaddr });
1393 coff.getAtomPtr(atom_index).size = code_len;1393 coff.getAtomPtr(atom_index).size = code_len;
1394 sym.value = vaddr;1394 sym.value = vaddr;
13951395
...@@ -1454,7 +1454,7 @@ pub fn updateExports(...@@ -1454,7 +1454,7 @@ pub fn updateExports(
14541454
1455 for (export_indices) |export_idx| {1455 for (export_indices) |export_idx| {
1456 const exp = export_idx.ptr(zcu);1456 const exp = export_idx.ptr(zcu);
1457 log.debug("adding new export '{}'", .{exp.opts.name.fmt(&zcu.intern_pool)});1457 log.debug("adding new export '{f}'", .{exp.opts.name.fmt(&zcu.intern_pool)});
14581458
1459 if (exp.opts.section.toSlice(&zcu.intern_pool)) |section_name| {1459 if (exp.opts.section.toSlice(&zcu.intern_pool)) |section_name| {
1460 if (!mem.eql(u8, section_name, ".text")) {1460 if (!mem.eql(u8, section_name, ".text")) {
...@@ -1530,7 +1530,7 @@ pub fn deleteExport(...@@ -1530,7 +1530,7 @@ pub fn deleteExport(
1530 const gpa = coff.base.comp.gpa;1530 const gpa = coff.base.comp.gpa;
1531 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };1531 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };
1532 const sym = coff.getSymbolPtr(sym_loc);1532 const sym = coff.getSymbolPtr(sym_loc);
1533 log.debug("deleting export '{}'", .{name.fmt(&zcu.intern_pool)});1533 log.debug("deleting export '{f}'", .{name.fmt(&zcu.intern_pool)});
1534 assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED);1534 assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED);
1535 sym.* = .{1535 sym.* = .{
1536 .name = [_]u8{0} ** 8,1536 .name = [_]u8{0} ** 8,
...@@ -1748,7 +1748,7 @@ pub fn getNavVAddr(...@@ -1748,7 +1748,7 @@ pub fn getNavVAddr(
1748 const zcu = pt.zcu;1748 const zcu = pt.zcu;
1749 const ip = &zcu.intern_pool;1749 const ip = &zcu.intern_pool;
1750 const nav = ip.getNav(nav_index);1750 const nav = ip.getNav(nav_index);
1751 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });1751 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
1752 const sym_index = if (nav.getExtern(ip)) |e|1752 const sym_index = if (nav.getExtern(ip)) |e|
1753 try coff.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip))1753 try coff.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip))
1754 else1754 else
...@@ -2588,7 +2588,7 @@ fn logSymtab(coff: *Coff) void {...@@ -2588,7 +2588,7 @@ fn logSymtab(coff: *Coff) void {
2588 .DEBUG => unreachable, // TODO2588 .DEBUG => unreachable, // TODO
2589 else => @intFromEnum(sym.section_number),2589 else => @intFromEnum(sym.section_number),
2590 };2590 };
2591 log.debug(" %{d}: {?s} @{x} in {s}({d}), {s}", .{2591 log.debug(" %{d}: {s} @{x} in {s}({d}), {s}", .{
2592 sym_id,2592 sym_id,
2593 coff.getSymbolName(.{ .sym_index = @as(u32, @intCast(sym_id)), .file = null }),2593 coff.getSymbolName(.{ .sym_index = @as(u32, @intCast(sym_id)), .file = null }),
2594 sym.value,2594 sym.value,
...@@ -2605,7 +2605,7 @@ fn logSymtab(coff: *Coff) void {...@@ -2605,7 +2605,7 @@ fn logSymtab(coff: *Coff) void {
2605 }2605 }
26062606
2607 log.debug("GOT entries:", .{});2607 log.debug("GOT entries:", .{});
2608 log.debug("{}", .{coff.got_table});2608 log.debug("{f}", .{coff.got_table});
2609}2609}
26102610
2611fn logSections(coff: *Coff) void {2611fn logSections(coff: *Coff) void {
...@@ -2625,7 +2625,7 @@ fn logImportTables(coff: *const Coff) void {...@@ -2625,7 +2625,7 @@ fn logImportTables(coff: *const Coff) void {
2625 log.debug("import tables:", .{});2625 log.debug("import tables:", .{});
2626 for (coff.import_tables.keys(), 0..) |off, i| {2626 for (coff.import_tables.keys(), 0..) |off, i| {
2627 const itable = coff.import_tables.values()[i];2627 const itable = coff.import_tables.values()[i];
2628 log.debug("{}", .{itable.fmtDebug(.{2628 log.debug("{f}", .{itable.fmtDebug(.{
2629 .coff = coff,2629 .coff = coff,
2630 .index = i,2630 .index = i,
2631 .name_off = off,2631 .name_off = off,
...@@ -3061,40 +3061,25 @@ const ImportTable = struct {...@@ -3061,40 +3061,25 @@ const ImportTable = struct {
3061 return base_vaddr + index * @sizeOf(u64);3061 return base_vaddr + index * @sizeOf(u64);
3062 }3062 }
30633063
3064 const FormatContext = struct {3064 const Format = struct {
3065 itab: ImportTable,3065 itab: ImportTable,
3066 ctx: Context,3066 ctx: Context,
3067 };
30683067
3069 fn format(itab: ImportTable, comptime unused_format_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {3068 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
3070 _ = itab;3069 const lib_name = f.ctx.coff.temp_strtab.getAssumeExists(f.ctx.name_off);
3071 _ = unused_format_string;3070 const base_vaddr = getBaseAddress(f.ctx);
3072 _ = options;3071 try writer.print("IAT({s}.dll) @{x}:", .{ lib_name, base_vaddr });
3073 _ = writer;3072 for (f.itab.entries.items, 0..) |entry, i| {
3074 @compileError("do not format ImportTable directly; use itab.fmtDebug()");3073 try writer.print("\n {d}@{?x} => {s}", .{
3075 }3074 i,
30763075 f.itab.getImportAddress(entry, f.ctx),
3077 fn format2(3076 f.ctx.coff.getSymbolName(entry),
3078 fmt_ctx: FormatContext,3077 });
3079 comptime unused_format_string: []const u8,3078 }
3080 options: fmt.FormatOptions,
3081 writer: anytype,
3082 ) @TypeOf(writer).Error!void {
3083 _ = options;
3084 comptime assert(unused_format_string.len == 0);
3085 const lib_name = fmt_ctx.ctx.coff.temp_strtab.getAssumeExists(fmt_ctx.ctx.name_off);
3086 const base_vaddr = getBaseAddress(fmt_ctx.ctx);
3087 try writer.print("IAT({s}.dll) @{x}:", .{ lib_name, base_vaddr });
3088 for (fmt_ctx.itab.entries.items, 0..) |entry, i| {
3089 try writer.print("\n {d}@{?x} => {s}", .{
3090 i,
3091 fmt_ctx.itab.getImportAddress(entry, fmt_ctx.ctx),
3092 fmt_ctx.ctx.coff.getSymbolName(entry),
3093 });
3094 }3079 }
3095 }3080 };
30963081
3097 fn fmtDebug(itab: ImportTable, ctx: Context) fmt.Formatter(format2) {3082 fn fmtDebug(itab: ImportTable, ctx: Context) fmt.Formatter(Format, Format.default) {
3098 return .{ .data = .{ .itab = itab, .ctx = ctx } };3083 return .{ .data = .{ .itab = itab, .ctx = ctx } };
3099 }3084 }
31003085
src/link/Dwarf.zig+12-12
...@@ -973,7 +973,7 @@ const Entry = struct {...@@ -973,7 +973,7 @@ const Entry = struct {
973 else973 else
974 .main;974 .main;
975 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)975 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)
976 log.err("missing Type({}({d}))", .{976 log.err("missing Type({f}({d}))", .{
977 Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }),977 Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }),
978 @intFromEnum(ty),978 @intFromEnum(ty),
979 });979 });
...@@ -981,7 +981,7 @@ const Entry = struct {...@@ -981,7 +981,7 @@ const Entry = struct {
981 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {981 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {
982 const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod.?) catch unreachable;982 const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod.?) catch unreachable;
983 if (sec.getUnit(nav_unit) == unit and unit.getEntry(other_entry) == entry)983 if (sec.getUnit(nav_unit) == unit and unit.getEntry(other_entry) == entry)
984 log.err("missing Nav({}({d}))", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) });984 log.err("missing Nav({f}({d}))", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) });
985 }985 }
986 }986 }
987 @panic("missing dwarf relocation target");987 @panic("missing dwarf relocation target");
...@@ -1957,7 +1957,7 @@ pub const WipNav = struct {...@@ -1957,7 +1957,7 @@ pub const WipNav = struct {
1957 .{ .debug_output = .{ .dwarf = wip_nav } },1957 .{ .debug_output = .{ .dwarf = wip_nav } },
1958 );1958 );
1959 if (old_len + bytes != wip_nav.debug_info.items.len) {1959 if (old_len + bytes != wip_nav.debug_info.items.len) {
1960 std.debug.print("{} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), bytes, wip_nav.debug_info.items.len - old_len });1960 std.debug.print("{f} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), bytes, wip_nav.debug_info.items.len - old_len });
1961 unreachable;1961 unreachable;
1962 }1962 }
1963 }1963 }
...@@ -2427,7 +2427,7 @@ fn initWipNavInner(...@@ -2427,7 +2427,7 @@ fn initWipNavInner(
2427 const inst_info = nav.srcInst(ip).resolveFull(ip).?;2427 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
2428 const file = zcu.fileByIndex(inst_info.file);2428 const file = zcu.fileByIndex(inst_info.file);
2429 const decl = file.zir.?.getDeclaration(inst_info.inst);2429 const decl = file.zir.?.getDeclaration(inst_info.inst);
2430 log.debug("initWipNav({s}:{d}:{d} %{d} = {})", .{2430 log.debug("initWipNav({s}:{d}:{d} %{d} = {f})", .{
2431 file.sub_file_path,2431 file.sub_file_path,
2432 decl.src_line + 1,2432 decl.src_line + 1,
2433 decl.src_column + 1,2433 decl.src_column + 1,
...@@ -2632,7 +2632,7 @@ pub fn finishWipNavFunc(...@@ -2632,7 +2632,7 @@ pub fn finishWipNavFunc(
2632 const ip = &zcu.intern_pool;2632 const ip = &zcu.intern_pool;
2633 const nav = ip.getNav(nav_index);2633 const nav = ip.getNav(nav_index);
2634 assert(wip_nav.func != .none);2634 assert(wip_nav.func != .none);
2635 log.debug("finishWipNavFunc({})", .{nav.fqn.fmt(ip)});2635 log.debug("finishWipNavFunc({f})", .{nav.fqn.fmt(ip)});
26362636
2637 {2637 {
2638 const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;2638 const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
...@@ -2733,7 +2733,7 @@ pub fn finishWipNav(...@@ -2733,7 +2733,7 @@ pub fn finishWipNav(
2733 const zcu = pt.zcu;2733 const zcu = pt.zcu;
2734 const ip = &zcu.intern_pool;2734 const ip = &zcu.intern_pool;
2735 const nav = ip.getNav(nav_index);2735 const nav = ip.getNav(nav_index);
2736 log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});2736 log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)});
27372737
2738 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);2738 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);
2739 if (wip_nav.debug_line.items.len > 0) {2739 if (wip_nav.debug_line.items.len > 0) {
...@@ -2765,7 +2765,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2765,7 +2765,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2765 const inst_info = nav.srcInst(ip).resolveFull(ip).?;2765 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
2766 const file = zcu.fileByIndex(inst_info.file);2766 const file = zcu.fileByIndex(inst_info.file);
2767 const decl = file.zir.?.getDeclaration(inst_info.inst);2767 const decl = file.zir.?.getDeclaration(inst_info.inst);
2768 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {})", .{2768 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {f})", .{
2769 file.sub_file_path,2769 file.sub_file_path,
2770 decl.src_line + 1,2770 decl.src_line + 1,
2771 decl.src_column + 1,2771 decl.src_column + 1,
...@@ -3215,7 +3215,7 @@ fn updateLazyType(...@@ -3215,7 +3215,7 @@ fn updateLazyType(
3215 const ty: Type = .fromInterned(type_index);3215 const ty: Type = .fromInterned(type_index);
3216 switch (type_index) {3216 switch (type_index) {
3217 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),3217 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),
3218 else => log.debug("updateLazyType({})", .{ty.fmt(pt)}),3218 else => log.debug("updateLazyType({f})", .{ty.fmt(pt)}),
3219 }3219 }
32203220
3221 var wip_nav: WipNav = .{3221 var wip_nav: WipNav = .{
...@@ -3243,7 +3243,7 @@ fn updateLazyType(...@@ -3243,7 +3243,7 @@ fn updateLazyType(
3243 const diw = wip_nav.debug_info.writer(dwarf.gpa);3243 const diw = wip_nav.debug_info.writer(dwarf.gpa);
3244 const name = switch (type_index) {3244 const name = switch (type_index) {
3245 .generic_poison_type => "",3245 .generic_poison_type => "",
3246 else => try std.fmt.allocPrint(dwarf.gpa, "{}", .{ty.fmt(pt)}),3246 else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}),
3247 };3247 };
3248 defer dwarf.gpa.free(name);3248 defer dwarf.gpa.free(name);
32493249
...@@ -3718,7 +3718,7 @@ fn updateLazyValue(...@@ -3718,7 +3718,7 @@ fn updateLazyValue(
3718 const zcu = pt.zcu;3718 const zcu = pt.zcu;
3719 const ip = &zcu.intern_pool;3719 const ip = &zcu.intern_pool;
3720 assert(ip.typeOf(value_index) != .type_type);3720 assert(ip.typeOf(value_index) != .type_type);
3721 log.debug("updateLazyValue(@as({}, {}))", .{3721 log.debug("updateLazyValue(@as({f}, {f}))", .{
3722 Value.fromInterned(value_index).typeOf(zcu).fmt(pt),3722 Value.fromInterned(value_index).typeOf(zcu).fmt(pt),
3723 Value.fromInterned(value_index).fmtValue(pt),3723 Value.fromInterned(value_index).fmtValue(pt),
3724 });3724 });
...@@ -4110,7 +4110,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP...@@ -4110,7 +4110,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
4110 const ip = &zcu.intern_pool;4110 const ip = &zcu.intern_pool;
4111 const ty: Type = .fromInterned(type_index);4111 const ty: Type = .fromInterned(type_index);
4112 const ty_src_loc = ty.srcLoc(zcu);4112 const ty_src_loc = ty.srcLoc(zcu);
4113 log.debug("updateContainerType({})", .{ty.fmt(pt)});4113 log.debug("updateContainerType({f})", .{ty.fmt(pt)});
41144114
4115 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;4115 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;
4116 const file = zcu.fileByIndex(inst_info.file);4116 const file = zcu.fileByIndex(inst_info.file);
...@@ -4239,7 +4239,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP...@@ -4239,7 +4239,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
4239 };4239 };
4240 defer wip_nav.deinit();4240 defer wip_nav.deinit();
4241 const diw = wip_nav.debug_info.writer(dwarf.gpa);4241 const diw = wip_nav.debug_info.writer(dwarf.gpa);
4242 const name = try std.fmt.allocPrint(dwarf.gpa, "{}", .{ty.fmt(pt)});4242 const name = try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)});
4243 defer dwarf.gpa.free(name);4243 defer dwarf.gpa.free(name);
42444244
4245 switch (ip.indexToKey(type_index)) {4245 switch (ip.indexToKey(type_index)) {
src/link/Elf.zig+36-72
...@@ -702,7 +702,7 @@ pub fn allocateChunk(self: *Elf, args: struct {...@@ -702,7 +702,7 @@ pub fn allocateChunk(self: *Elf, args: struct {
702 shdr.sh_addr + res.value,702 shdr.sh_addr + res.value,
703 shdr.sh_offset + res.value,703 shdr.sh_offset + res.value,
704 });704 });
705 log.debug(" placement {}, {s}", .{705 log.debug(" placement {f}, {s}", .{
706 res.placement,706 res.placement,
707 if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",707 if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",
708 });708 });
...@@ -869,7 +869,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -869,7 +869,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
869 // Dump the state for easy debugging.869 // Dump the state for easy debugging.
870 // State can be dumped via `--debug-log link_state`.870 // State can be dumped via `--debug-log link_state`.
871 if (build_options.enable_logging) {871 if (build_options.enable_logging) {
872 state_log.debug("{}", .{self.dumpState()});872 state_log.debug("{f}", .{self.dumpState()});
873 }873 }
874874
875 // Beyond this point, everything has been allocated a virtual address and we can resolve875 // Beyond this point, everything has been allocated a virtual address and we can resolve
...@@ -3544,7 +3544,7 @@ pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {...@@ -3544,7 +3544,7 @@ pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {
3544}3544}
35453545
3546pub fn addRelaDynAssumeCapacity(self: *Elf, opts: RelaDyn) void {3546pub fn addRelaDynAssumeCapacity(self: *Elf, opts: RelaDyn) void {
3547 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{3547 relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
3548 relocation.fmtRelocType(opts.type, self.getTarget().cpu.arch),3548 relocation.fmtRelocType(opts.type, self.getTarget().cpu.arch),
3549 opts.offset,3549 opts.offset,
3550 opts.sym,3550 opts.sym,
...@@ -3791,7 +3791,7 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {...@@ -3791,7 +3791,7 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
3791 for (refs.items[0..nrefs]) |ref| {3791 for (refs.items[0..nrefs]) |ref| {
3792 const atom_ptr = self.atom(ref).?;3792 const atom_ptr = self.atom(ref).?;
3793 const file_ptr = atom_ptr.file(self).?;3793 const file_ptr = atom_ptr.file(self).?;
3794 err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });3794 err.addNote("referenced by {f}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
3795 }3795 }
37963796
3797 if (refs.items.len > max_notes) {3797 if (refs.items.len > max_notes) {
...@@ -3813,12 +3813,12 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor...@@ -3813,12 +3813,12 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor
38133813
3814 var err = try diags.addErrorWithNotes(nnotes + 1);3814 var err = try diags.addErrorWithNotes(nnotes + 1);
3815 try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)});3815 try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)});
3816 err.addNote("defined by {}", .{sym.file(self).?.fmtPath()});3816 err.addNote("defined by {f}", .{sym.file(self).?.fmtPath()});
38173817
3818 var inote: usize = 0;3818 var inote: usize = 0;
3819 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {3819 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
3820 const file_ptr = self.file(notes.items[inote]).?;3820 const file_ptr = self.file(notes.items[inote]).?;
3821 err.addNote("defined by {}", .{file_ptr.fmtPath()});3821 err.addNote("defined by {f}", .{file_ptr.fmtPath()});
3822 }3822 }
38233823
3824 if (notes.items.len > max_notes) {3824 if (notes.items.len > max_notes) {
...@@ -3847,7 +3847,7 @@ pub fn addFileError(...@@ -3847,7 +3847,7 @@ pub fn addFileError(
3847 const diags = &self.base.comp.link_diags;3847 const diags = &self.base.comp.link_diags;
3848 var err = try diags.addErrorWithNotes(1);3848 var err = try diags.addErrorWithNotes(1);
3849 try err.addMsg(format, args);3849 try err.addMsg(format, args);
3850 err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()});3850 err.addNote("while parsing {f}", .{self.file(file_index).?.fmtPath()});
3851}3851}
38523852
3853pub fn failFile(3853pub fn failFile(
...@@ -3860,28 +3860,21 @@ pub fn failFile(...@@ -3860,28 +3860,21 @@ pub fn failFile(
3860 return error.LinkFailure;3860 return error.LinkFailure;
3861}3861}
38623862
3863const FormatShdrCtx = struct {3863const FormatShdr = struct {
3864 elf_file: *Elf,3864 elf_file: *Elf,
3865 shdr: elf.Elf64_Shdr,3865 shdr: elf.Elf64_Shdr,
3866};3866};
38673867
3868fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(formatShdr) {3868fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(FormatShdr, formatShdr) {
3869 return .{ .data = .{3869 return .{ .data = .{
3870 .shdr = shdr,3870 .shdr = shdr,
3871 .elf_file = self,3871 .elf_file = self,
3872 } };3872 } };
3873}3873}
38743874
3875fn formatShdr(3875fn formatShdr(ctx: FormatShdr, writer: *std.io.Writer) std.io.Writer.Error!void {
3876 ctx: FormatShdrCtx,
3877 comptime unused_fmt_string: []const u8,
3878 options: std.fmt.FormatOptions,
3879 writer: anytype,
3880) !void {
3881 _ = options;
3882 _ = unused_fmt_string;
3883 const shdr = ctx.shdr;3876 const shdr = ctx.shdr;
3884 try writer.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({})", .{3877 try writer.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({f})", .{
3885 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,3878 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,
3886 shdr.sh_addr, shdr.sh_addralign,3879 shdr.sh_addr, shdr.sh_addralign,
3887 shdr.sh_size, shdr.sh_entsize,3880 shdr.sh_size, shdr.sh_entsize,
...@@ -3889,18 +3882,11 @@ fn formatShdr(...@@ -3889,18 +3882,11 @@ fn formatShdr(
3889 });3882 });
3890}3883}
38913884
3892pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) {3885pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(u64, formatShdrFlags) {
3893 return .{ .data = sh_flags };3886 return .{ .data = sh_flags };
3894}3887}
38953888
3896fn formatShdrFlags(3889fn formatShdrFlags(sh_flags: u64, writer: *std.io.Writer) std.io.Writer.Error!void {
3897 sh_flags: u64,
3898 comptime unused_fmt_string: []const u8,
3899 options: std.fmt.FormatOptions,
3900 writer: anytype,
3901) !void {
3902 _ = unused_fmt_string;
3903 _ = options;
3904 if (elf.SHF_WRITE & sh_flags != 0) {3890 if (elf.SHF_WRITE & sh_flags != 0) {
3905 try writer.writeAll("W");3891 try writer.writeAll("W");
3906 }3892 }
...@@ -3945,26 +3931,19 @@ fn formatShdrFlags(...@@ -3945,26 +3931,19 @@ fn formatShdrFlags(
3945 }3931 }
3946}3932}
39473933
3948const FormatPhdrCtx = struct {3934const FormatPhdr = struct {
3949 elf_file: *Elf,3935 elf_file: *Elf,
3950 phdr: elf.Elf64_Phdr,3936 phdr: elf.Elf64_Phdr,
3951};3937};
39523938
3953fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(formatPhdr) {3939fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(FormatPhdr, formatPhdr) {
3954 return .{ .data = .{3940 return .{ .data = .{
3955 .phdr = phdr,3941 .phdr = phdr,
3956 .elf_file = self,3942 .elf_file = self,
3957 } };3943 } };
3958}3944}
39593945
3960fn formatPhdr(3946fn formatPhdr(ctx: FormatPhdr, writer: *std.io.Writer) std.io.Writer.Error!void {
3961 ctx: FormatPhdrCtx,
3962 comptime unused_fmt_string: []const u8,
3963 options: std.fmt.FormatOptions,
3964 writer: anytype,
3965) !void {
3966 _ = options;
3967 _ = unused_fmt_string;
3968 const phdr = ctx.phdr;3947 const phdr = ctx.phdr;
3969 const write = phdr.p_flags & elf.PF_W != 0;3948 const write = phdr.p_flags & elf.PF_W != 0;
3970 const read = phdr.p_flags & elf.PF_R != 0;3949 const read = phdr.p_flags & elf.PF_R != 0;
...@@ -3991,24 +3970,16 @@ fn formatPhdr(...@@ -3991,24 +3970,16 @@ fn formatPhdr(
3991 });3970 });
3992}3971}
39933972
3994pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {3973pub fn dumpState(self: *Elf) std.fmt.Formatter(*Elf, fmtDumpState) {
3995 return .{ .data = self };3974 return .{ .data = self };
3996}3975}
39973976
3998fn fmtDumpState(3977fn fmtDumpState(self: *Elf, writer: *std.io.Writer) std.io.Writer.Error!void {
3999 self: *Elf,
4000 comptime unused_fmt_string: []const u8,
4001 options: std.fmt.FormatOptions,
4002 writer: anytype,
4003) !void {
4004 _ = unused_fmt_string;
4005 _ = options;
4006
4007 const shared_objects = self.shared_objects.values();3978 const shared_objects = self.shared_objects.values();
40083979
4009 if (self.zigObjectPtr()) |zig_object| {3980 if (self.zigObjectPtr()) |zig_object| {
4010 try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.basename });3981 try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.basename });
4011 try writer.print("{}{}", .{3982 try writer.print("{f}{f}", .{
4012 zig_object.fmtAtoms(self),3983 zig_object.fmtAtoms(self),
4013 zig_object.fmtSymtab(self),3984 zig_object.fmtSymtab(self),
4014 });3985 });
...@@ -4017,10 +3988,10 @@ fn fmtDumpState(...@@ -4017,10 +3988,10 @@ fn fmtDumpState(
40173988
4018 for (self.objects.items) |index| {3989 for (self.objects.items) |index| {
4019 const object = self.file(index).?.object;3990 const object = self.file(index).?.object;
4020 try writer.print("object({d}) : {}", .{ index, object.fmtPath() });3991 try writer.print("object({d}) : {f}", .{ index, object.fmtPath() });
4021 if (!object.alive) try writer.writeAll(" : [*]");3992 if (!object.alive) try writer.writeAll(" : [*]");
4022 try writer.writeByte('\n');3993 try writer.writeByte('\n');
4023 try writer.print("{}{}{}{}{}\n", .{3994 try writer.print("{f}{f}{f}{f}{f}\n", .{
4024 object.fmtAtoms(self),3995 object.fmtAtoms(self),
4025 object.fmtCies(self),3996 object.fmtCies(self),
4026 object.fmtFdes(self),3997 object.fmtFdes(self),
...@@ -4031,51 +4002,51 @@ fn fmtDumpState(...@@ -4031,51 +4002,51 @@ fn fmtDumpState(
40314002
4032 for (shared_objects) |index| {4003 for (shared_objects) |index| {
4033 const shared_object = self.file(index).?.shared_object;4004 const shared_object = self.file(index).?.shared_object;
4034 try writer.print("shared_object({d}) : {} : needed({})", .{4005 try writer.print("shared_object({d}) : {f} : needed({})", .{
4035 index, shared_object.path, shared_object.needed,4006 index, shared_object.path, shared_object.needed,
4036 });4007 });
4037 if (!shared_object.alive) try writer.writeAll(" : [*]");4008 if (!shared_object.alive) try writer.writeAll(" : [*]");
4038 try writer.writeByte('\n');4009 try writer.writeByte('\n');
4039 try writer.print("{}\n", .{shared_object.fmtSymtab(self)});4010 try writer.print("{f}\n", .{shared_object.fmtSymtab(self)});
4040 }4011 }
40414012
4042 if (self.linker_defined_index) |index| {4013 if (self.linker_defined_index) |index| {
4043 const linker_defined = self.file(index).?.linker_defined;4014 const linker_defined = self.file(index).?.linker_defined;
4044 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});4015 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});
4045 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});4016 try writer.print("{f}\n", .{linker_defined.fmtSymtab(self)});
4046 }4017 }
40474018
4048 const slice = self.sections.slice();4019 const slice = self.sections.slice();
4049 {4020 {
4050 try writer.writeAll("atom lists\n");4021 try writer.writeAll("atom lists\n");
4051 for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| {4022 for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| {
4052 try writer.print("shdr({d}) : {s} : {}\n", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) });4023 try writer.print("shdr({d}) : {s} : {f}\n", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) });
4053 }4024 }
4054 }4025 }
40554026
4056 if (self.requiresThunks()) {4027 if (self.requiresThunks()) {
4057 try writer.writeAll("thunks\n");4028 try writer.writeAll("thunks\n");
4058 for (self.thunks.items, 0..) |th, index| {4029 for (self.thunks.items, 0..) |th, index| {
4059 try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });4030 try writer.print("thunk({d}) : {f}\n", .{ index, th.fmt(self) });
4060 }4031 }
4061 }4032 }
40624033
4063 try writer.print("{}\n", .{self.got.fmt(self)});4034 try writer.print("{f}\n", .{self.got.fmt(self)});
4064 try writer.print("{}\n", .{self.plt.fmt(self)});4035 try writer.print("{f}\n", .{self.plt.fmt(self)});
40654036
4066 try writer.writeAll("Output groups\n");4037 try writer.writeAll("Output groups\n");
4067 for (self.group_sections.items) |cg| {4038 for (self.group_sections.items) |cg| {
4068 try writer.print(" shdr({d}) : GROUP({})\n", .{ cg.shndx, cg.cg_ref });4039 try writer.print(" shdr({d}) : GROUP({f})\n", .{ cg.shndx, cg.cg_ref });
4069 }4040 }
40704041
4071 try writer.writeAll("\nOutput merge sections\n");4042 try writer.writeAll("\nOutput merge sections\n");
4072 for (self.merge_sections.items) |msec| {4043 for (self.merge_sections.items) |msec| {
4073 try writer.print(" shdr({d}) : {}\n", .{ msec.output_section_index, msec.fmt(self) });4044 try writer.print(" shdr({d}) : {f}\n", .{ msec.output_section_index, msec.fmt(self) });
4074 }4045 }
40754046
4076 try writer.writeAll("\nOutput shdrs\n");4047 try writer.writeAll("\nOutput shdrs\n");
4077 for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| {4048 for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| {
4078 try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{4049 try writer.print(" shdr({d}) : phdr({d}) : {f}\n", .{
4079 shndx,4050 shndx,
4080 phndx,4051 phndx,
4081 self.fmtShdr(shdr),4052 self.fmtShdr(shdr),
...@@ -4083,7 +4054,7 @@ fn fmtDumpState(...@@ -4083,7 +4054,7 @@ fn fmtDumpState(
4083 }4054 }
4084 try writer.writeAll("\nOutput phdrs\n");4055 try writer.writeAll("\nOutput phdrs\n");
4085 for (self.phdrs.items, 0..) |phdr, phndx| {4056 for (self.phdrs.items, 0..) |phdr, phndx| {
4086 try writer.print(" phdr({d}) : {}\n", .{ phndx, self.fmtPhdr(phdr) });4057 try writer.print(" phdr({d}) : {f}\n", .{ phndx, self.fmtPhdr(phdr) });
4087 }4058 }
4088}4059}
40894060
...@@ -4221,15 +4192,8 @@ pub const Ref = struct {...@@ -4221,15 +4192,8 @@ pub const Ref = struct {
4221 return ref.index == other.index and ref.file == other.file;4192 return ref.index == other.index and ref.file == other.file;
4222 }4193 }
42234194
4224 pub fn format(4195 pub fn format(ref: Ref, writer: *std.io.Writer) std.io.Writer.Error!void {
4225 ref: Ref,4196 try writer.print("ref({d},{d})", .{ ref.index, ref.file });
4226 comptime unused_fmt_string: []const u8,
4227 options: std.fmt.FormatOptions,
4228 writer: anytype,
4229 ) !void {
4230 _ = unused_fmt_string;
4231 _ = options;
4232 try writer.print("ref({},{})", .{ ref.index, ref.file });
4233 }4197 }
4234};4198};
42354199
...@@ -4424,7 +4388,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -4424,7 +4388,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
4424 for (atom_list.atoms.keys()[start..i]) |ref| {4388 for (atom_list.atoms.keys()[start..i]) |ref| {
4425 const atom_ptr = elf_file.atom(ref).?;4389 const atom_ptr = elf_file.atom(ref).?;
4426 const file_ptr = atom_ptr.file(elf_file).?;4390 const file_ptr = atom_ptr.file(elf_file).?;
4427 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });4391 log.debug("atom({f}) {s}", .{ ref, atom_ptr.name(elf_file) });
4428 for (atom_ptr.relocs(elf_file)) |rel| {4392 for (atom_ptr.relocs(elf_file)) |rel| {
4429 const is_reachable = switch (cpu_arch) {4393 const is_reachable = switch (cpu_arch) {
4430 .aarch64 => r: {4394 .aarch64 => r: {
...@@ -4453,7 +4417,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -4453,7 +4417,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
44534417
4454 thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));4418 thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));
44554419
4456 log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) });4420 log.debug("thunk({d}) : {f}", .{ thunk_index, thunk_ptr.fmt(elf_file) });
4457 }4421 }
4458}4422}
44594423
src/link/Elf/Archive.zig+17-44
...@@ -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
...@@ -83,7 +83,7 @@ pub fn parse(...@@ -83,7 +83,7 @@ pub fn parse(
83 .alive = false,83 .alive = false,
84 };84 };
8585
86 log.debug("extracting object '{}' from archive '{}'", .{86 log.debug("extracting object '{f}' from archive '{f}'", .{
87 @as(Path, object.path), @as(Path, path),87 @as(Path, object.path), @as(Path, path),
88 });88 });
8989
...@@ -201,48 +201,28 @@ pub const ArSymtab = struct {...@@ -201,48 +201,28 @@ pub const ArSymtab = struct {
201 }201 }
202 }202 }
203203
204 pub fn format(204 const Format = struct {
205 ar: ArSymtab,
206 comptime unused_fmt_string: []const u8,
207 options: std.fmt.FormatOptions,
208 writer: anytype,
209 ) !void {
210 _ = ar;
211 _ = unused_fmt_string;
212 _ = options;
213 _ = writer;
214 @compileError("do not format ar symtab directly; use fmt instead");
215 }
216
217 const FormatContext = struct {
218 ar: ArSymtab,205 ar: ArSymtab,
219 elf_file: *Elf,206 elf_file: *Elf,
207
208 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
209 const ar = f.ar;
210 const elf_file = f.elf_file;
211 for (ar.symtab.items, 0..) |entry, i| {
212 const name = ar.strtab.getAssumeExists(entry.off);
213 const file = elf_file.file(entry.file_index).?;
214 try writer.print(" {d}: {s} in file({d})({f})\n", .{ i, name, entry.file_index, file.fmtPath() });
215 }
216 }
220 };217 };
221218
222 pub fn fmt(ar: ArSymtab, elf_file: *Elf) std.fmt.Formatter(format2) {219 pub fn fmt(ar: ArSymtab, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
223 return .{ .data = .{220 return .{ .data = .{
224 .ar = ar,221 .ar = ar,
225 .elf_file = elf_file,222 .elf_file = elf_file,
226 } };223 } };
227 }224 }
228225
229 fn format2(
230 ctx: FormatContext,
231 comptime unused_fmt_string: []const u8,
232 options: std.fmt.FormatOptions,
233 writer: anytype,
234 ) !void {
235 _ = unused_fmt_string;
236 _ = options;
237 const ar = ctx.ar;
238 const elf_file = ctx.elf_file;
239 for (ar.symtab.items, 0..) |entry, i| {
240 const name = ar.strtab.getAssumeExists(entry.off);
241 const file = elf_file.file(entry.file_index).?;
242 try writer.print(" {d}: {s} in file({d})({})\n", .{ i, name, entry.file_index, file.fmtPath() });
243 }
244 }
245
246 const Entry = struct {226 const Entry = struct {
247 /// Offset into the string table.227 /// Offset into the string table.
248 off: u32,228 off: u32,
...@@ -280,15 +260,8 @@ pub const ArStrtab = struct {...@@ -280,15 +260,8 @@ pub const ArStrtab = struct {
280 try writer.writeAll(ar.buffer.items);260 try writer.writeAll(ar.buffer.items);
281 }261 }
282262
283 pub fn format(263 pub fn format(ar: ArStrtab, writer: *std.io.Writer) std.io.Writer.Error!void {
284 ar: ArStrtab,264 try writer.print("{f}", .{std.ascii.hexEscape(ar.buffer.items, .lower)});
285 comptime unused_fmt_string: []const u8,
286 options: std.fmt.FormatOptions,
287 writer: anytype,
288 ) !void {
289 _ = unused_fmt_string;
290 _ = options;
291 try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});
292 }265 }
293};266};
294267
src/link/Elf/Atom.zig+57-79
...@@ -142,7 +142,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {...@@ -142,7 +142,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
142}142}
143143
144pub fn free(self: *Atom, elf_file: *Elf) void {144pub fn free(self: *Atom, elf_file: *Elf) void {
145 log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) });145 log.debug("freeAtom atom({f}) ({s})", .{ self.ref(), self.name(elf_file) });
146146
147 const comp = elf_file.base.comp;147 const comp = elf_file.base.comp;
148 const gpa = comp.gpa;148 const gpa = comp.gpa;
...@@ -243,7 +243,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El...@@ -243,7 +243,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
243 },243 },
244 }244 }
245245
246 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{246 relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
247 relocation.fmtRelocType(rel.r_type(), cpu_arch),247 relocation.fmtRelocType(rel.r_type(), cpu_arch),
248 r_offset,248 r_offset,
249 r_sym,249 r_sym,
...@@ -316,7 +316,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype...@@ -316,7 +316,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
316 };316 };
317 // Violation of One Definition Rule for COMDATs.317 // Violation of One Definition Rule for COMDATs.
318 // TODO convert into an error318 // TODO convert into an error
319 log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{319 log.debug("{f}: {s}: {s} refers to a discarded COMDAT section", .{
320 file_ptr.fmtPath(),320 file_ptr.fmtPath(),
321 self.name(elf_file),321 self.name(elf_file),
322 sym_name,322 sym_name,
...@@ -519,11 +519,11 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 {...@@ -519,11 +519,11 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 {
519fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) RelocError!void {519fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) RelocError!void {
520 const diags = &elf_file.base.comp.link_diags;520 const diags = &elf_file.base.comp.link_diags;
521 var err = try diags.addErrorWithNotes(1);521 var err = try diags.addErrorWithNotes(1);
522 try err.addMsg("fatal linker error: unhandled relocation type {} at offset 0x{x}", .{522 try err.addMsg("fatal linker error: unhandled relocation type {f} at offset 0x{x}", .{
523 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),523 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
524 rel.r_offset,524 rel.r_offset,
525 });525 });
526 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });526 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
527 return error.RelocFailure;527 return error.RelocFailure;
528}528}
529529
...@@ -539,7 +539,7 @@ fn reportTextRelocError(...@@ -539,7 +539,7 @@ fn reportTextRelocError(
539 rel.r_offset,539 rel.r_offset,
540 symbol.name(elf_file),540 symbol.name(elf_file),
541 });541 });
542 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });542 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
543 return error.RelocFailure;543 return error.RelocFailure;
544}544}
545545
...@@ -555,7 +555,7 @@ fn reportPicError(...@@ -555,7 +555,7 @@ fn reportPicError(
555 rel.r_offset,555 rel.r_offset,
556 symbol.name(elf_file),556 symbol.name(elf_file),
557 });557 });
558 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });558 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
559 err.addNote("recompile with -fPIC", .{});559 err.addNote("recompile with -fPIC", .{});
560 return error.RelocFailure;560 return error.RelocFailure;
561}561}
...@@ -572,7 +572,7 @@ fn reportNoPicError(...@@ -572,7 +572,7 @@ fn reportNoPicError(
572 rel.r_offset,572 rel.r_offset,
573 symbol.name(elf_file),573 symbol.name(elf_file),
574 });574 });
575 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });575 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
576 err.addNote("recompile with -fno-PIC", .{});576 err.addNote("recompile with -fno-PIC", .{});
577 return error.RelocFailure;577 return error.RelocFailure;
578}578}
...@@ -652,7 +652,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -652,7 +652,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
652 // Address of the dynamic thread pointer.652 // Address of the dynamic thread pointer.
653 const DTP = elf_file.dtpAddress();653 const DTP = elf_file.dtpAddress();
654654
655 relocs_log.debug(" {s}: {x}: [{x} => {x}] GOT({x}) ({s})", .{655 relocs_log.debug(" {f}: {x}: [{x} => {x}] GOT({x}) ({s})", .{
656 relocation.fmtRelocType(rel.r_type(), cpu_arch),656 relocation.fmtRelocType(rel.r_type(), cpu_arch),
657 r_offset,657 r_offset,
658 P,658 P,
...@@ -823,7 +823,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -823,7 +823,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
823 };823 };
824 // Violation of One Definition Rule for COMDATs.824 // Violation of One Definition Rule for COMDATs.
825 // TODO convert into an error825 // TODO convert into an error
826 log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{826 log.debug("{f}: {s}: {s} refers to a discarded COMDAT section", .{
827 file_ptr.fmtPath(),827 file_ptr.fmtPath(),
828 self.name(elf_file),828 self.name(elf_file),
829 sym_name,829 sym_name,
...@@ -855,7 +855,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -855,7 +855,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
855855
856 const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP };856 const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP };
857857
858 relocs_log.debug(" {}: {x}: [{x} => {x}] ({s})", .{858 relocs_log.debug(" {f}: {x}: [{x} => {x}] ({s})", .{
859 relocation.fmtRelocType(rel.r_type(), cpu_arch),859 relocation.fmtRelocType(rel.r_type(), cpu_arch),
860 rel.r_offset,860 rel.r_offset,
861 P,861 P,
...@@ -904,65 +904,45 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {...@@ -904,65 +904,45 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
904 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);904 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);
905}905}
906906
907pub fn format(907pub fn fmt(atom: Atom, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
908 atom: Atom,
909 comptime unused_fmt_string: []const u8,
910 options: std.fmt.FormatOptions,
911 writer: anytype,
912) !void {
913 _ = atom;
914 _ = unused_fmt_string;
915 _ = options;
916 _ = writer;
917 @compileError("do not format Atom directly");
918}
919
920pub fn fmt(atom: Atom, elf_file: *Elf) std.fmt.Formatter(format2) {
921 return .{ .data = .{908 return .{ .data = .{
922 .atom = atom,909 .atom = atom,
923 .elf_file = elf_file,910 .elf_file = elf_file,
924 } };911 } };
925}912}
926913
927const FormatContext = struct {914const Format = struct {
928 atom: Atom,915 atom: Atom,
929 elf_file: *Elf,916 elf_file: *Elf,
930};
931917
932fn format2(918 fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void {
933 ctx: FormatContext,919 const atom = f.atom;
934 comptime unused_fmt_string: []const u8,920 const elf_file = f.elf_file;
935 options: std.fmt.FormatOptions,921 try w.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({f}) : next({f})", .{
936 writer: anytype,922 atom.atom_index, atom.name(elf_file), atom.address(elf_file),
937) !void {923 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,
938 _ = options;924 atom.prev_atom_ref, atom.next_atom_ref,
939 _ = unused_fmt_string;925 });
940 const atom = ctx.atom;926 if (atom.file(elf_file)) |atom_file| switch (atom_file) {
941 const elf_file = ctx.elf_file;927 .object => |object| {
942 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({}) : next({})", .{928 if (atom.fdes(object).len > 0) {
943 atom.atom_index, atom.name(elf_file), atom.address(elf_file),929 try w.writeAll(" : fdes{ ");
944 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,930 const extras = atom.extra(elf_file);
945 atom.prev_atom_ref, atom.next_atom_ref,931 for (atom.fdes(object), extras.fde_start..) |fde, i| {
946 });932 try w.print("{d}", .{i});
947 if (atom.file(elf_file)) |atom_file| switch (atom_file) {933 if (!fde.alive) try w.writeAll("([*])");
948 .object => |object| {934 if (i - extras.fde_start < extras.fde_count - 1) try w.writeAll(", ");
949 if (atom.fdes(object).len > 0) {935 }
950 try writer.writeAll(" : fdes{ ");936 try w.writeAll(" }");
951 const extras = atom.extra(elf_file);
952 for (atom.fdes(object), extras.fde_start..) |fde, i| {
953 try writer.print("{d}", .{i});
954 if (!fde.alive) try writer.writeAll("([*])");
955 if (i - extras.fde_start < extras.fde_count - 1) try writer.writeAll(", ");
956 }937 }
957 try writer.writeAll(" }");938 },
958 }939 else => {},
959 },940 };
960 else => {},941 if (!atom.alive) {
961 };942 try w.writeAll(" : [*]");
962 if (!atom.alive) {943 }
963 try writer.writeAll(" : [*]");
964 }944 }
965}945};
966946
967pub const Index = u32;947pub const Index = u32;
968948
...@@ -1189,7 +1169,7 @@ const x86_64 = struct {...@@ -1189,7 +1169,7 @@ const x86_64 = struct {
1189 x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {1169 x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {
1190 var err = try diags.addErrorWithNotes(1);1170 var err = try diags.addErrorWithNotes(1);
1191 try err.addMsg("could not relax {s}", .{@tagName(r_type)});1171 try err.addMsg("could not relax {s}", .{@tagName(r_type)});
1192 err.addNote("in {}:{s} at offset 0x{x}", .{1172 err.addNote("in {f}:{s} at offset 0x{x}", .{
1193 atom.file(elf_file).?.fmtPath(),1173 atom.file(elf_file).?.fmtPath(),
1194 atom.name(elf_file),1174 atom.name(elf_file),
1195 rel.r_offset,1175 rel.r_offset,
...@@ -1285,7 +1265,7 @@ const x86_64 = struct {...@@ -1285,7 +1265,7 @@ const x86_64 = struct {
1285 }, t),1265 }, t),
1286 else => return error.RelaxFailure,1266 else => return error.RelaxFailure,
1287 };1267 };
1288 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1268 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1289 const nop: Instruction = try .new(.none, .nop, &.{}, t);1269 const nop: Instruction = try .new(.none, .nop, &.{}, t);
1290 try encode(&.{ nop, inst }, code);1270 try encode(&.{ nop, inst }, code);
1291 }1271 }
...@@ -1296,7 +1276,7 @@ const x86_64 = struct {...@@ -1296,7 +1276,7 @@ const x86_64 = struct {
1296 switch (old_inst.encoding.mnemonic) {1276 switch (old_inst.encoding.mnemonic) {
1297 .mov => {1277 .mov => {
1298 const inst: Instruction = try .new(old_inst.prefix, .lea, &old_inst.ops, t);1278 const inst: Instruction = try .new(old_inst.prefix, .lea, &old_inst.ops, t);
1299 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1279 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1300 try encode(&.{inst}, code);1280 try encode(&.{inst}, code);
1301 },1281 },
1302 else => return error.RelaxFailure,1282 else => return error.RelaxFailure,
...@@ -1330,11 +1310,11 @@ const x86_64 = struct {...@@ -1330,11 +1310,11 @@ const x86_64 = struct {
13301310
1331 else => {1311 else => {
1332 var err = try diags.addErrorWithNotes(1);1312 var err = try diags.addErrorWithNotes(1);
1333 try err.addMsg("TODO: rewrite {} when followed by {}", .{1313 try err.addMsg("TODO: rewrite {f} when followed by {f}", .{
1334 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1314 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1335 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1315 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1336 });1316 });
1337 err.addNote("in {}:{s} at offset 0x{x}", .{1317 err.addNote("in {f}:{s} at offset 0x{x}", .{
1338 self.file(elf_file).?.fmtPath(),1318 self.file(elf_file).?.fmtPath(),
1339 self.name(elf_file),1319 self.name(elf_file),
1340 rels[0].r_offset,1320 rels[0].r_offset,
...@@ -1386,11 +1366,11 @@ const x86_64 = struct {...@@ -1386,11 +1366,11 @@ const x86_64 = struct {
13861366
1387 else => {1367 else => {
1388 var err = try diags.addErrorWithNotes(1);1368 var err = try diags.addErrorWithNotes(1);
1389 try err.addMsg("TODO: rewrite {} when followed by {}", .{1369 try err.addMsg("TODO: rewrite {f} when followed by {f}", .{
1390 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1370 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1391 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1371 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1392 });1372 });
1393 err.addNote("in {}:{s} at offset 0x{x}", .{1373 err.addNote("in {f}:{s} at offset 0x{x}", .{
1394 self.file(elf_file).?.fmtPath(),1374 self.file(elf_file).?.fmtPath(),
1395 self.name(elf_file),1375 self.name(elf_file),
1396 rels[0].r_offset,1376 rels[0].r_offset,
...@@ -1410,7 +1390,8 @@ const x86_64 = struct {...@@ -1410,7 +1390,8 @@ const x86_64 = struct {
1410 // TODO: hack to force imm32s in the assembler1390 // TODO: hack to force imm32s in the assembler
1411 .{ .imm = .s(-129) },1391 .{ .imm = .s(-129) },
1412 }, t) catch return false;1392 }, t) catch return false;
1413 inst.encode(std.io.null_writer, .{}) catch return false;1393 var trash: std.io.Writer.Discarding = .init(&.{});
1394 inst.encode(&trash.writer, .{}) catch return false;
1414 return true;1395 return true;
1415 },1396 },
1416 else => return false,1397 else => return false,
...@@ -1427,7 +1408,7 @@ const x86_64 = struct {...@@ -1427,7 +1408,7 @@ const x86_64 = struct {
1427 // TODO: hack to force imm32s in the assembler1408 // TODO: hack to force imm32s in the assembler
1428 .{ .imm = .s(-129) },1409 .{ .imm = .s(-129) },
1429 }, t) catch unreachable;1410 }, t) catch unreachable;
1430 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1411 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1431 encode(&.{inst}, code) catch unreachable;1412 encode(&.{inst}, code) catch unreachable;
1432 },1413 },
1433 else => unreachable,1414 else => unreachable,
...@@ -1444,7 +1425,7 @@ const x86_64 = struct {...@@ -1444,7 +1425,7 @@ const x86_64 = struct {
1444 // TODO: hack to force imm32s in the assembler1425 // TODO: hack to force imm32s in the assembler
1445 .{ .imm = .s(-129) },1426 .{ .imm = .s(-129) },
1446 }, target);1427 }, target);
1447 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1428 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1448 try encode(&.{inst}, code);1429 try encode(&.{inst}, code);
1449 },1430 },
1450 else => return error.RelaxFailure,1431 else => return error.RelaxFailure,
...@@ -1476,7 +1457,7 @@ const x86_64 = struct {...@@ -1476,7 +1457,7 @@ const x86_64 = struct {
1476 std.mem.writeInt(i32, insts[12..][0..4], value, .little);1457 std.mem.writeInt(i32, insts[12..][0..4], value, .little);
1477 try stream.seekBy(-4);1458 try stream.seekBy(-4);
1478 try writer.writeAll(&insts);1459 try writer.writeAll(&insts);
1479 relocs_log.debug(" relaxing {} and {}", .{1460 relocs_log.debug(" relaxing {f} and {f}", .{
1480 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1461 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1481 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1462 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1482 });1463 });
...@@ -1484,11 +1465,11 @@ const x86_64 = struct {...@@ -1484,11 +1465,11 @@ const x86_64 = struct {
14841465
1485 else => {1466 else => {
1486 var err = try diags.addErrorWithNotes(1);1467 var err = try diags.addErrorWithNotes(1);
1487 try err.addMsg("fatal linker error: rewrite {} when followed by {}", .{1468 try err.addMsg("fatal linker error: rewrite {f} when followed by {f}", .{
1488 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1469 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1489 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1470 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1490 });1471 });
1491 err.addNote("in {}:{s} at offset 0x{x}", .{1472 err.addNote("in {f}:{s} at offset 0x{x}", .{
1492 self.file(elf_file).?.fmtPath(),1473 self.file(elf_file).?.fmtPath(),
1493 self.name(elf_file),1474 self.name(elf_file),
1494 rels[0].r_offset,1475 rels[0].r_offset,
...@@ -1505,11 +1486,8 @@ const x86_64 = struct {...@@ -1505,11 +1486,8 @@ const x86_64 = struct {
1505 }1486 }
15061487
1507 fn encode(insts: []const Instruction, code: []u8) !void {1488 fn encode(insts: []const Instruction, code: []u8) !void {
1508 var stream = std.io.fixedBufferStream(code);1489 var stream: std.io.Writer = .fixed(code);
1509 const writer = stream.writer();1490 for (insts) |inst| try inst.encode(&stream, .{});
1510 for (insts) |inst| {
1511 try inst.encode(writer, .{});
1512 }
1513 }1491 }
15141492
1515 const bits = @import("../../arch/x86_64/bits.zig");1493 const bits = @import("../../arch/x86_64/bits.zig");
...@@ -1675,7 +1653,7 @@ const aarch64 = struct {...@@ -1675,7 +1653,7 @@ const aarch64 = struct {
1675 // TODO: relax1653 // TODO: relax
1676 var err = try diags.addErrorWithNotes(1);1654 var err = try diags.addErrorWithNotes(1);
1677 try err.addMsg("TODO: relax ADR_GOT_PAGE", .{});1655 try err.addMsg("TODO: relax ADR_GOT_PAGE", .{});
1678 err.addNote("in {}:{s} at offset 0x{x}", .{1656 err.addNote("in {f}:{s} at offset 0x{x}", .{
1679 atom.file(elf_file).?.fmtPath(),1657 atom.file(elf_file).?.fmtPath(),
1680 atom.name(elf_file),1658 atom.name(elf_file),
1681 r_offset,1659 r_offset,
...@@ -1965,7 +1943,7 @@ const riscv = struct {...@@ -1965,7 +1943,7 @@ const riscv = struct {
1965 // TODO: implement searching forward1943 // TODO: implement searching forward
1966 var err = try diags.addErrorWithNotes(1);1944 var err = try diags.addErrorWithNotes(1);
1967 try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{});1945 try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{});
1968 err.addNote("in {}:{s} at offset 0x{x}", .{1946 err.addNote("in {f}:{s} at offset 0x{x}", .{
1969 atom.file(elf_file).?.fmtPath(),1947 atom.file(elf_file).?.fmtPath(),
1970 atom.name(elf_file),1948 atom.name(elf_file),
1971 rel.r_offset,1949 rel.r_offset,
src/link/Elf/AtomList.zig+24-39
...@@ -108,7 +108,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi...@@ -108,7 +108,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi
108 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;108 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;
109 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;109 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
110110
111 log.debug(" atom({}) at 0x{x}", .{ ref, list.offset(elf_file) + off });111 log.debug(" atom({f}) at 0x{x}", .{ ref, list.offset(elf_file) + off });
112112
113 const object = atom_ptr.file(elf_file).?.object;113 const object = atom_ptr.file(elf_file).?.object;
114 const code = try object.codeDecompressAlloc(elf_file, ref.index);114 const code = try object.codeDecompressAlloc(elf_file, ref.index);
...@@ -144,7 +144,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E...@@ -144,7 +144,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E
144 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;144 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;
145 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;145 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
146146
147 log.debug(" atom({}) at 0x{x}", .{ ref, list.offset(elf_file) + off });147 log.debug(" atom({f}) at 0x{x}", .{ ref, list.offset(elf_file) + off });
148148
149 const object = atom_ptr.file(elf_file).?.object;149 const object = atom_ptr.file(elf_file).?.object;
150 const code = try object.codeDecompressAlloc(elf_file, ref.index);150 const code = try object.codeDecompressAlloc(elf_file, ref.index);
...@@ -167,44 +167,29 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {...@@ -167,44 +167,29 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {
167 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;167 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;
168}168}
169169
170pub fn format(170const Format = struct {
171 list: AtomList,171 atom_list: AtomList,
172 comptime unused_fmt_string: []const u8,172 elf_file: *Elf,
173 options: std.fmt.FormatOptions,173
174 writer: anytype,174 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
175) !void {175 const list = f.atom_list;
176 _ = list;176 try writer.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{
177 _ = unused_fmt_string;177 list.address(f.elf_file),
178 _ = options;178 list.output_section_index,
179 _ = writer;179 list.alignment.toByteUnits() orelse 0,
180 @compileError("do not format AtomList directly");180 list.size,
181}181 });
182182 try writer.writeAll(" : atoms{ ");
183const FormatCtx = struct { AtomList, *Elf };183 for (list.atoms.keys(), 0..) |ref, i| {
184184 try writer.print("{f}", .{ref});
185pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) {185 if (i < list.atoms.keys().len - 1) try writer.writeAll(", ");
186 return .{ .data = .{ list, elf_file } };186 }
187}187 try writer.writeAll(" }");
188
189fn format2(
190 ctx: FormatCtx,
191 comptime unused_fmt_string: []const u8,
192 options: std.fmt.FormatOptions,
193 writer: anytype,
194) !void {
195 _ = unused_fmt_string;
196 _ = options;
197 const list, const elf_file = ctx;
198 try writer.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{
199 list.address(elf_file), list.output_section_index,
200 list.alignment.toByteUnits() orelse 0, list.size,
201 });
202 try writer.writeAll(" : atoms{ ");
203 for (list.atoms.keys(), 0..) |ref, i| {
204 try writer.print("{}", .{ref});
205 if (i < list.atoms.keys().len - 1) try writer.writeAll(", ");
206 }188 }
207 try writer.writeAll(" }");189};
190
191pub fn fmt(atom_list: AtomList, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
192 return .{ .data = .{ .atom_list = atom_list, .elf_file = elf_file } };
208}193}
209194
210const assert = std.debug.assert;195const assert = std.debug.assert;
src/link/Elf/LinkerDefined.zig+16-23
...@@ -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| {
...@@ -437,38 +437,31 @@ pub fn setSymbolExtra(self: *LinkerDefined, index: u32, extra: Symbol.Extra) voi...@@ -437,38 +437,31 @@ pub fn setSymbolExtra(self: *LinkerDefined, index: u32, extra: Symbol.Extra) voi
437 }437 }
438}438}
439439
440pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {440pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) {
441 return .{ .data = .{441 return .{ .data = .{
442 .self = self,442 .self = self,
443 .elf_file = elf_file,443 .elf_file = elf_file,
444 } };444 } };
445}445}
446446
447const FormatContext = struct {447const Format = struct {
448 self: *LinkerDefined,448 self: *LinkerDefined,
449 elf_file: *Elf,449 elf_file: *Elf,
450};
451450
452fn formatSymtab(451 fn symtab(ctx: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
453 ctx: FormatContext,452 const self = ctx.self;
454 comptime unused_fmt_string: []const u8,453 const elf_file = ctx.elf_file;
455 options: std.fmt.FormatOptions,454 try writer.writeAll(" globals\n");
456 writer: anytype,455 for (self.symbols.items, 0..) |sym, i| {
457) !void {456 const ref = self.resolveSymbol(@intCast(i), elf_file);
458 _ = unused_fmt_string;457 if (elf_file.symbol(ref)) |ref_sym| {
459 _ = options;458 try writer.print(" {f}\n", .{ref_sym.fmt(elf_file)});
460 const self = ctx.self;459 } else {
461 const elf_file = ctx.elf_file;460 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
462 try writer.writeAll(" globals\n");461 }
463 for (self.symbols.items, 0..) |sym, i| {
464 const ref = self.resolveSymbol(@intCast(i), elf_file);
465 if (elf_file.symbol(ref)) |ref_sym| {
466 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});
467 } else {
468 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
469 }462 }
470 }463 }
471}464};
472465
473const assert = std.debug.assert;466const assert = std.debug.assert;
474const elf = std.elf;467const elf = std.elf;
src/link/Elf/Merge.zig+31-71
...@@ -157,54 +157,34 @@ pub const Section = struct {...@@ -157,54 +157,34 @@ pub const Section = struct {
157 }157 }
158 };158 };
159159
160 pub fn format(160 pub fn fmt(msec: Section, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
161 msec: Section,
162 comptime unused_fmt_string: []const u8,
163 options: std.fmt.FormatOptions,
164 writer: anytype,
165 ) !void {
166 _ = msec;
167 _ = unused_fmt_string;
168 _ = options;
169 _ = writer;
170 @compileError("do not format directly");
171 }
172
173 pub fn fmt(msec: Section, elf_file: *Elf) std.fmt.Formatter(format2) {
174 return .{ .data = .{161 return .{ .data = .{
175 .msec = msec,162 .msec = msec,
176 .elf_file = elf_file,163 .elf_file = elf_file,
177 } };164 } };
178 }165 }
179166
180 const FormatContext = struct {167 const Format = struct {
181 msec: Section,168 msec: Section,
182 elf_file: *Elf,169 elf_file: *Elf,
183 };
184170
185 pub fn format2(171 pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
186 ctx: FormatContext,172 const msec = f.msec;
187 comptime unused_fmt_string: []const u8,173 const elf_file = f.elf_file;
188 options: std.fmt.FormatOptions,174 try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{
189 writer: anytype,175 msec.name(elf_file),
190 ) !void {176 msec.address(elf_file),
191 _ = options;177 msec.size,
192 _ = unused_fmt_string;178 msec.alignment.toByteUnits() orelse 0,
193 const msec = ctx.msec;179 msec.entsize,
194 const elf_file = ctx.elf_file;180 msec.type,
195 try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{181 msec.flags,
196 msec.name(elf_file),182 });
197 msec.address(elf_file),183 for (msec.subsections.items) |msub| {
198 msec.size,184 try writer.print(" {f}\n", .{msub.fmt(elf_file)});
199 msec.alignment.toByteUnits() orelse 0,185 }
200 msec.entsize,
201 msec.type,
202 msec.flags,
203 });
204 for (msec.subsections.items) |msub| {
205 try writer.print(" {}\n", .{msub.fmt(elf_file)});
206 }186 }
207 }187 };
208188
209 pub const Index = u32;189 pub const Index = u32;
210};190};
...@@ -231,48 +211,28 @@ pub const Subsection = struct {...@@ -231,48 +211,28 @@ pub const Subsection = struct {
231 return msec.bytes.items[msub.string_index..][0..msub.size];211 return msec.bytes.items[msub.string_index..][0..msub.size];
232 }212 }
233213
234 pub fn format(214 pub fn fmt(msub: Subsection, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
235 msub: Subsection,
236 comptime unused_fmt_string: []const u8,
237 options: std.fmt.FormatOptions,
238 writer: anytype,
239 ) !void {
240 _ = msub;
241 _ = unused_fmt_string;
242 _ = options;
243 _ = writer;
244 @compileError("do not format directly");
245 }
246
247 pub fn fmt(msub: Subsection, elf_file: *Elf) std.fmt.Formatter(format2) {
248 return .{ .data = .{215 return .{ .data = .{
249 .msub = msub,216 .msub = msub,
250 .elf_file = elf_file,217 .elf_file = elf_file,
251 } };218 } };
252 }219 }
253220
254 const FormatContext = struct {221 const Format = struct {
255 msub: Subsection,222 msub: Subsection,
256 elf_file: *Elf,223 elf_file: *Elf,
257 };
258224
259 pub fn format2(225 pub fn default(ctx: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
260 ctx: FormatContext,226 const msub = ctx.msub;
261 comptime unused_fmt_string: []const u8,227 const elf_file = ctx.elf_file;
262 options: std.fmt.FormatOptions,228 try writer.print("@{x} : align({x}) : size({x})", .{
263 writer: anytype,229 msub.address(elf_file),
264 ) !void {230 msub.alignment,
265 _ = options;231 msub.size,
266 _ = unused_fmt_string;232 });
267 const msub = ctx.msub;233 if (!msub.alive) try writer.writeAll(" : [*]");
268 const elf_file = ctx.elf_file;234 }
269 try writer.print("@{x} : align({x}) : size({x})", .{235 };
270 msub.address(elf_file),
271 msub.alignment,
272 msub.size,
273 });
274 if (!msub.alive) try writer.writeAll(" : [*]");
275 }
276236
277 pub const Index = u32;237 pub const Index = u32;
278};238};
src/link/Elf/Object.zig+75-133
...@@ -281,7 +281,7 @@ fn initAtoms(...@@ -281,7 +281,7 @@ fn initAtoms(
281 elf.SHT_GROUP => {281 elf.SHT_GROUP => {
282 if (shdr.sh_info >= self.symtab.items.len) {282 if (shdr.sh_info >= self.symtab.items.len) {
283 // TODO convert into an error283 // TODO convert into an error
284 log.debug("{}: invalid symbol index in sh_info", .{self.fmtPath()});284 log.debug("{f}: invalid symbol index in sh_info", .{self.fmtPath()});
285 continue;285 continue;
286 }286 }
287 const group_info_sym = self.symtab.items[shdr.sh_info];287 const group_info_sym = self.symtab.items[shdr.sh_info];
...@@ -488,10 +488,7 @@ fn parseEhFrame(...@@ -488,10 +488,7 @@ fn parseEhFrame(
488 if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index));488 if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index));
489 } else {489 } else {
490 // TODO convert into an error490 // TODO convert into an error
491 log.debug("{s}: no matching CIE found for FDE at offset {x}", .{491 log.debug("{f}: no matching CIE found for FDE at offset {x}", .{ self.fmtPath(), fde.offset });
492 self.fmtPath(),
493 fde.offset,
494 });
495 continue;492 continue;
496 };493 };
497 fde.cie_index = cie_index;494 fde.cie_index = cie_index;
...@@ -582,7 +579,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {...@@ -582,7 +579,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
582 if (sym.flags.import) {579 if (sym.flags.import) {
583 if (sym.type(elf_file) != elf.STT_FUNC)580 if (sym.type(elf_file) != elf.STT_FUNC)
584 // TODO convert into an error581 // TODO convert into an error
585 log.debug("{s}: {s}: CIE referencing external data reference", .{582 log.debug("{f}: {s}: CIE referencing external data reference", .{
586 self.fmtPath(), sym.name(elf_file),583 self.fmtPath(), sym.name(elf_file),
587 });584 });
588 sym.flags.needs_plt = true;585 sym.flags.needs_plt = true;
...@@ -796,7 +793,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -796,7 +793,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
796 if (!isNull(data[end .. end + sh_entsize])) {793 if (!isNull(data[end .. end + sh_entsize])) {
797 var err = try diags.addErrorWithNotes(1);794 var err = try diags.addErrorWithNotes(1);
798 try err.addMsg("string not null terminated", .{});795 try err.addMsg("string not null terminated", .{});
799 err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });796 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
800 return error.LinkFailure;797 return error.LinkFailure;
801 }798 }
802 end += sh_entsize;799 end += sh_entsize;
...@@ -811,7 +808,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -811,7 +808,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
811 if (shdr.sh_size % sh_entsize != 0) {808 if (shdr.sh_size % sh_entsize != 0) {
812 var err = try diags.addErrorWithNotes(1);809 var err = try diags.addErrorWithNotes(1);
813 try err.addMsg("size not a multiple of sh_entsize", .{});810 try err.addMsg("size not a multiple of sh_entsize", .{});
814 err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });811 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
815 return error.LinkFailure;812 return error.LinkFailure;
816 }813 }
817814
...@@ -889,7 +886,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{...@@ -889,7 +886,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
889 var err = try diags.addErrorWithNotes(2);886 var err = try diags.addErrorWithNotes(2);
890 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});887 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});
891 err.addNote("for symbol {s}", .{sym.name(elf_file)});888 err.addNote("for symbol {s}", .{sym.name(elf_file)});
892 err.addNote("in {}", .{self.fmtPath()});889 err.addNote("in {f}", .{self.fmtPath()});
893 return error.LinkFailure;890 return error.LinkFailure;
894 };891 };
895892
...@@ -914,7 +911,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{...@@ -914,7 +911,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
914 const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {911 const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {
915 var err = try diags.addErrorWithNotes(1);912 var err = try diags.addErrorWithNotes(1);
916 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});913 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});
917 err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });914 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
918 return error.LinkFailure;915 return error.LinkFailure;
919 };916 };
920917
...@@ -1432,171 +1429,116 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {...@@ -1432,171 +1429,116 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {
1432 return &self.groups.items[index];1429 return &self.groups.items[index];
1433}1430}
14341431
1435pub fn format(1432pub fn fmtSymtab(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) {
1436 self: *Object,
1437 comptime unused_fmt_string: []const u8,
1438 options: std.fmt.FormatOptions,
1439 writer: anytype,
1440) !void {
1441 _ = self;
1442 _ = unused_fmt_string;
1443 _ = options;
1444 _ = writer;
1445 @compileError("do not format objects directly");
1446}
1447
1448pub fn fmtSymtab(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
1449 return .{ .data = .{1433 return .{ .data = .{
1450 .object = self,1434 .object = self,
1451 .elf_file = elf_file,1435 .elf_file = elf_file,
1452 } };1436 } };
1453}1437}
14541438
1455const FormatContext = struct {1439const Format = struct {
1456 object: *Object,1440 object: *Object,
1457 elf_file: *Elf,1441 elf_file: *Elf,
1458};
14591442
1460fn formatSymtab(1443 fn symtab(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
1461 ctx: FormatContext,1444 const object = f.object;
1462 comptime unused_fmt_string: []const u8,1445 const elf_file = f.elf_file;
1463 options: std.fmt.FormatOptions,1446 try writer.writeAll(" locals\n");
1464 writer: anytype,1447 for (object.locals()) |sym| {
1465) !void {1448 try writer.print(" {f}\n", .{sym.fmt(elf_file)});
1466 _ = unused_fmt_string;1449 }
1467 _ = options;1450 try writer.writeAll(" globals\n");
1468 const object = ctx.object;1451 for (object.globals(), 0..) |sym, i| {
1469 const elf_file = ctx.elf_file;1452 const first_global = object.first_global.?;
1470 try writer.writeAll(" locals\n");1453 const ref = object.resolveSymbol(@intCast(i + first_global), elf_file);
1471 for (object.locals()) |sym| {1454 if (elf_file.symbol(ref)) |ref_sym| {
1472 try writer.print(" {}\n", .{sym.fmt(elf_file)});1455 try writer.print(" {f}\n", .{ref_sym.fmt(elf_file)});
1456 } else {
1457 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
1458 }
1459 }
1473 }1460 }
1474 try writer.writeAll(" globals\n");1461
1475 for (object.globals(), 0..) |sym, i| {1462 fn atoms(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
1476 const first_global = object.first_global.?;1463 const object = f.object;
1477 const ref = object.resolveSymbol(@intCast(i + first_global), elf_file);1464 try writer.writeAll(" atoms\n");
1478 if (elf_file.symbol(ref)) |ref_sym| {1465 for (object.atoms_indexes.items) |atom_index| {
1479 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});1466 const atom_ptr = object.atom(atom_index) orelse continue;
1480 } else {1467 try writer.print(" {f}\n", .{atom_ptr.fmt(f.elf_file)});
1481 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});1468 }
1469 }
1470
1471 fn cies(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
1472 const object = f.object;
1473 try writer.writeAll(" cies\n");
1474 for (object.cies.items, 0..) |cie, i| {
1475 try writer.print(" cie({d}) : {f}\n", .{ i, cie.fmt(f.elf_file) });
1482 }1476 }
1483 }1477 }
1484}
14851478
1486pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {1479 fn fdes(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
1480 const object = f.object;
1481 try writer.writeAll(" fdes\n");
1482 for (object.fdes.items, 0..) |fde, i| {
1483 try writer.print(" fde({d}) : {f}\n", .{ i, fde.fmt(f.elf_file) });
1484 }
1485 }
1486
1487 fn groups(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
1488 const object = f.object;
1489 const elf_file = f.elf_file;
1490 try writer.writeAll(" groups\n");
1491 for (object.groups.items, 0..) |g, g_index| {
1492 try writer.print(" {s}({d})", .{ if (g.is_comdat) "COMDAT" else "GROUP", g_index });
1493 if (!g.alive) try writer.writeAll(" : [*]");
1494 try writer.writeByte('\n');
1495 const g_members = g.members(elf_file);
1496 for (g_members) |shndx| {
1497 const atom_index = object.atoms_indexes.items[shndx];
1498 const atom_ptr = object.atom(atom_index) orelse continue;
1499 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });
1500 }
1501 }
1502 }
1503};
1504
1505pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.atoms) {
1487 return .{ .data = .{1506 return .{ .data = .{
1488 .object = self,1507 .object = self,
1489 .elf_file = elf_file,1508 .elf_file = elf_file,
1490 } };1509 } };
1491}1510}
14921511
1493fn formatAtoms(1512pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.cies) {
1494 ctx: FormatContext,
1495 comptime unused_fmt_string: []const u8,
1496 options: std.fmt.FormatOptions,
1497 writer: anytype,
1498) !void {
1499 _ = unused_fmt_string;
1500 _ = options;
1501 const object = ctx.object;
1502 try writer.writeAll(" atoms\n");
1503 for (object.atoms_indexes.items) |atom_index| {
1504 const atom_ptr = object.atom(atom_index) orelse continue;
1505 try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});
1506 }
1507}
1508
1509pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {
1510 return .{ .data = .{1513 return .{ .data = .{
1511 .object = self,1514 .object = self,
1512 .elf_file = elf_file,1515 .elf_file = elf_file,
1513 } };1516 } };
1514}1517}
15151518
1516fn formatCies(1519pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.fdes) {
1517 ctx: FormatContext,
1518 comptime unused_fmt_string: []const u8,
1519 options: std.fmt.FormatOptions,
1520 writer: anytype,
1521) !void {
1522 _ = unused_fmt_string;
1523 _ = options;
1524 const object = ctx.object;
1525 try writer.writeAll(" cies\n");
1526 for (object.cies.items, 0..) |cie, i| {
1527 try writer.print(" cie({d}) : {}\n", .{ i, cie.fmt(ctx.elf_file) });
1528 }
1529}
1530
1531pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatFdes) {
1532 return .{ .data = .{1520 return .{ .data = .{
1533 .object = self,1521 .object = self,
1534 .elf_file = elf_file,1522 .elf_file = elf_file,
1535 } };1523 } };
1536}1524}
15371525
1538fn formatFdes(1526pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.groups) {
1539 ctx: FormatContext,
1540 comptime unused_fmt_string: []const u8,
1541 options: std.fmt.FormatOptions,
1542 writer: anytype,
1543) !void {
1544 _ = unused_fmt_string;
1545 _ = options;
1546 const object = ctx.object;
1547 try writer.writeAll(" fdes\n");
1548 for (object.fdes.items, 0..) |fde, i| {
1549 try writer.print(" fde({d}) : {}\n", .{ i, fde.fmt(ctx.elf_file) });
1550 }
1551}
1552
1553pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups) {
1554 return .{ .data = .{1527 return .{ .data = .{
1555 .object = self,1528 .object = self,
1556 .elf_file = elf_file,1529 .elf_file = elf_file,
1557 } };1530 } };
1558}1531}
15591532
1560fn formatGroups(1533pub fn fmtPath(self: Object) std.fmt.Formatter(Object, formatPath) {
1561 ctx: FormatContext,
1562 comptime unused_fmt_string: []const u8,
1563 options: std.fmt.FormatOptions,
1564 writer: anytype,
1565) !void {
1566 _ = unused_fmt_string;
1567 _ = options;
1568 const object = ctx.object;
1569 const elf_file = ctx.elf_file;
1570 try writer.writeAll(" groups\n");
1571 for (object.groups.items, 0..) |g, g_index| {
1572 try writer.print(" {s}({d})", .{ if (g.is_comdat) "COMDAT" else "GROUP", g_index });
1573 if (!g.alive) try writer.writeAll(" : [*]");
1574 try writer.writeByte('\n');
1575 const g_members = g.members(elf_file);
1576 for (g_members) |shndx| {
1577 const atom_index = object.atoms_indexes.items[shndx];
1578 const atom_ptr = object.atom(atom_index) orelse continue;
1579 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });
1580 }
1581 }
1582}
1583
1584pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {
1585 return .{ .data = self };1534 return .{ .data = self };
1586}1535}
15871536
1588fn formatPath(1537fn formatPath(object: Object, writer: *std.io.Writer) std.io.Writer.Error!void {
1589 object: Object,
1590 comptime unused_fmt_string: []const u8,
1591 options: std.fmt.FormatOptions,
1592 writer: anytype,
1593) !void {
1594 _ = unused_fmt_string;
1595 _ = options;
1596 if (object.archive) |ar| {1538 if (object.archive) |ar| {
1597 try writer.print("{}({})", .{ ar.path, object.path });1539 try writer.print("{f}({f})", .{ ar.path, object.path });
1598 } else {1540 } else {
1599 try writer.print("{}", .{object.path});1541 try writer.print("{f}", .{object.path});
1600 }1542 }
1601}1543}
16021544
src/link/Elf/SharedObject.zig+14-34
...@@ -509,51 +509,31 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void...@@ -509,51 +509,31 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void
509 }509 }
510}510}
511511
512pub fn format(512pub fn fmtSymtab(self: SharedObject, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) {
513 self: SharedObject,
514 comptime unused_fmt_string: []const u8,
515 options: std.fmt.FormatOptions,
516 writer: anytype,
517) !void {
518 _ = self;
519 _ = unused_fmt_string;
520 _ = options;
521 _ = writer;
522 @compileError("unreachable");
523}
524
525pub fn fmtSymtab(self: SharedObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
526 return .{ .data = .{513 return .{ .data = .{
527 .shared = self,514 .shared = self,
528 .elf_file = elf_file,515 .elf_file = elf_file,
529 } };516 } };
530}517}
531518
532const FormatContext = struct {519const Format = struct {
533 shared: SharedObject,520 shared: SharedObject,
534 elf_file: *Elf,521 elf_file: *Elf,
535};
536522
537fn formatSymtab(523 fn symtab(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
538 ctx: FormatContext,524 const shared = f.shared;
539 comptime unused_fmt_string: []const u8,525 const elf_file = f.elf_file;
540 options: std.fmt.FormatOptions,526 try writer.writeAll(" globals\n");
541 writer: anytype,527 for (shared.symbols.items, 0..) |sym, i| {
542) !void {528 const ref = shared.resolveSymbol(@intCast(i), elf_file);
543 _ = unused_fmt_string;529 if (elf_file.symbol(ref)) |ref_sym| {
544 _ = options;530 try writer.print(" {f}\n", .{ref_sym.fmt(elf_file)});
545 const shared = ctx.shared;531 } else {
546 const elf_file = ctx.elf_file;532 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
547 try writer.writeAll(" globals\n");533 }
548 for (shared.symbols.items, 0..) |sym, i| {
549 const ref = shared.resolveSymbol(@intCast(i), elf_file);
550 if (elf_file.symbol(ref)) |ref_sym| {
551 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});
552 } else {
553 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
554 }534 }
555 }535 }
556}536};
557537
558const SharedObject = @This();538const SharedObject = @This();
559539
src/link/Elf/Symbol.zig+50-77
...@@ -316,99 +316,72 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -316,99 +316,72 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
316 out.st_size = esym.st_size;316 out.st_size = esym.st_size;
317}317}
318318
319pub fn format(319const Format = struct {
320 symbol: Symbol,
321 comptime unused_fmt_string: []const u8,
322 options: std.fmt.FormatOptions,
323 writer: anytype,
324) !void {
325 _ = symbol;
326 _ = unused_fmt_string;
327 _ = options;
328 _ = writer;
329 @compileError("do not format Symbol directly");
330}
331
332const FormatContext = struct {
333 symbol: Symbol,320 symbol: Symbol,
334 elf_file: *Elf,321 elf_file: *Elf,
322
323 fn name(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
324 const elf_file = f.elf_file;
325 const symbol = f.symbol;
326 try writer.writeAll(symbol.name(elf_file));
327 switch (symbol.version_index.VERSION) {
328 @intFromEnum(elf.VER_NDX.LOCAL), @intFromEnum(elf.VER_NDX.GLOBAL) => {},
329 else => {
330 const file_ptr = symbol.file(elf_file).?;
331 assert(file_ptr == .shared_object);
332 const shared_object = file_ptr.shared_object;
333 try writer.print("@{s}", .{shared_object.versionString(symbol.version_index)});
334 },
335 }
336 }
337
338 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
339 const symbol = f.symbol;
340 const elf_file = f.elf_file;
341 try writer.print("%{d} : {f} : @{x}", .{
342 symbol.esym_index,
343 symbol.fmtName(elf_file),
344 symbol.address(.{ .plt = false, .trampoline = false }, elf_file),
345 });
346 if (symbol.file(elf_file)) |file_ptr| {
347 if (symbol.isAbs(elf_file)) {
348 if (symbol.elfSym(elf_file).st_shndx == elf.SHN_UNDEF) {
349 try writer.writeAll(" : undef");
350 } else {
351 try writer.writeAll(" : absolute");
352 }
353 } else if (symbol.outputShndx(elf_file)) |shndx| {
354 try writer.print(" : shdr({d})", .{shndx});
355 }
356 if (symbol.atom(elf_file)) |atom_ptr| {
357 try writer.print(" : atom({d})", .{atom_ptr.atom_index});
358 }
359 var buf: [2]u8 = .{'_'} ** 2;
360 if (symbol.flags.@"export") buf[0] = 'E';
361 if (symbol.flags.import) buf[1] = 'I';
362 try writer.print(" : {s}", .{&buf});
363 if (symbol.flags.weak) try writer.writeAll(" : weak");
364 switch (file_ptr) {
365 inline else => |x| try writer.print(" : {s}({d})", .{ @tagName(file_ptr), x.index }),
366 }
367 } else try writer.writeAll(" : unresolved");
368 }
335};369};
336370
337pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(formatName) {371pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(Format, Format.name) {
338 return .{ .data = .{372 return .{ .data = .{
339 .symbol = symbol,373 .symbol = symbol,
340 .elf_file = elf_file,374 .elf_file = elf_file,
341 } };375 } };
342}376}
343377
344fn formatName(378pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
345 ctx: FormatContext,
346 comptime unused_fmt_string: []const u8,
347 options: std.fmt.FormatOptions,
348 writer: anytype,
349) !void {
350 _ = options;
351 _ = unused_fmt_string;
352 const elf_file = ctx.elf_file;
353 const symbol = ctx.symbol;
354 try writer.writeAll(symbol.name(elf_file));
355 switch (symbol.version_index.VERSION) {
356 @intFromEnum(elf.VER_NDX.LOCAL), @intFromEnum(elf.VER_NDX.GLOBAL) => {},
357 else => {
358 const file_ptr = symbol.file(elf_file).?;
359 assert(file_ptr == .shared_object);
360 const shared_object = file_ptr.shared_object;
361 try writer.print("@{s}", .{shared_object.versionString(symbol.version_index)});
362 },
363 }
364}
365
366pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(format2) {
367 return .{ .data = .{379 return .{ .data = .{
368 .symbol = symbol,380 .symbol = symbol,
369 .elf_file = elf_file,381 .elf_file = elf_file,
370 } };382 } };
371}383}
372384
373fn format2(
374 ctx: FormatContext,
375 comptime unused_fmt_string: []const u8,
376 options: std.fmt.FormatOptions,
377 writer: anytype,
378) !void {
379 _ = options;
380 _ = unused_fmt_string;
381 const symbol = ctx.symbol;
382 const elf_file = ctx.elf_file;
383 try writer.print("%{d} : {s} : @{x}", .{
384 symbol.esym_index,
385 symbol.fmtName(elf_file),
386 symbol.address(.{ .plt = false, .trampoline = false }, elf_file),
387 });
388 if (symbol.file(elf_file)) |file_ptr| {
389 if (symbol.isAbs(elf_file)) {
390 if (symbol.elfSym(elf_file).st_shndx == elf.SHN_UNDEF) {
391 try writer.writeAll(" : undef");
392 } else {
393 try writer.writeAll(" : absolute");
394 }
395 } else if (symbol.outputShndx(elf_file)) |shndx| {
396 try writer.print(" : shdr({d})", .{shndx});
397 }
398 if (symbol.atom(elf_file)) |atom_ptr| {
399 try writer.print(" : atom({d})", .{atom_ptr.atom_index});
400 }
401 var buf: [2]u8 = .{'_'} ** 2;
402 if (symbol.flags.@"export") buf[0] = 'E';
403 if (symbol.flags.import) buf[1] = 'I';
404 try writer.print(" : {s}", .{&buf});
405 if (symbol.flags.weak) try writer.writeAll(" : weak");
406 switch (file_ptr) {
407 inline else => |x| try writer.print(" : {s}({d})", .{ @tagName(file_ptr), x.index }),
408 }
409 } else try writer.writeAll(" : unresolved");
410}
411
412pub const Flags = packed struct {385pub const Flags = packed struct {
413 /// Whether the symbol is imported at runtime.386 /// Whether the symbol is imported at runtime.
414 import: bool = false,387 import: bool = false,
src/link/Elf/Thunk.zig+11-31
...@@ -65,47 +65,27 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {...@@ -65,47 +65,27 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {
65 };65 };
66}66}
6767
68pub fn format(68pub fn fmt(thunk: Thunk, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
69 thunk: Thunk,
70 comptime unused_fmt_string: []const u8,
71 options: std.fmt.FormatOptions,
72 writer: anytype,
73) !void {
74 _ = thunk;
75 _ = unused_fmt_string;
76 _ = options;
77 _ = writer;
78 @compileError("do not format Thunk directly");
79}
80
81pub fn fmt(thunk: Thunk, elf_file: *Elf) std.fmt.Formatter(format2) {
82 return .{ .data = .{69 return .{ .data = .{
83 .thunk = thunk,70 .thunk = thunk,
84 .elf_file = elf_file,71 .elf_file = elf_file,
85 } };72 } };
86}73}
8774
88const FormatContext = struct {75const Format = struct {
89 thunk: Thunk,76 thunk: Thunk,
90 elf_file: *Elf,77 elf_file: *Elf,
91};
9278
93fn format2(79 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
94 ctx: FormatContext,80 const thunk = f.thunk;
95 comptime unused_fmt_string: []const u8,81 const elf_file = f.elf_file;
96 options: std.fmt.FormatOptions,82 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
97 writer: anytype,83 for (thunk.symbols.keys()) |ref| {
98) !void {84 const sym = elf_file.symbol(ref).?;
99 _ = options;85 try writer.print(" {f} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value });
100 _ = unused_fmt_string;86 }
101 const thunk = ctx.thunk;
102 const elf_file = ctx.elf_file;
103 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
104 for (thunk.symbols.keys()) |ref| {
105 const sym = elf_file.symbol(ref).?;
106 try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value });
107 }87 }
108}88};
10989
110pub const Index = u32;90pub const Index = u32;
11191
src/link/Elf/ZigObject.zig+46-60
...@@ -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];
...@@ -925,7 +925,7 @@ pub fn getNavVAddr(...@@ -925,7 +925,7 @@ pub fn getNavVAddr(
925 const zcu = pt.zcu;925 const zcu = pt.zcu;
926 const ip = &zcu.intern_pool;926 const ip = &zcu.intern_pool;
927 const nav = ip.getNav(nav_index);927 const nav = ip.getNav(nav_index);
928 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });928 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
929 const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(929 const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(
930 elf_file,930 elf_file,
931 nav.name.toSlice(ip),931 nav.name.toSlice(ip),
...@@ -1268,7 +1268,7 @@ fn updateNavCode(...@@ -1268,7 +1268,7 @@ fn updateNavCode(
1268 const ip = &zcu.intern_pool;1268 const ip = &zcu.intern_pool;
1269 const nav = ip.getNav(nav_index);1269 const nav = ip.getNav(nav_index);
12701270
1271 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });1271 log.debug("updateNavCode {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
12721272
1273 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;1273 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
1274 const required_alignment = switch (pt.navAlignment(nav_index)) {1274 const required_alignment = switch (pt.navAlignment(nav_index)) {
...@@ -1302,7 +1302,7 @@ fn updateNavCode(...@@ -1302,7 +1302,7 @@ fn updateNavCode(
1302 self.allocateAtom(atom_ptr, true, elf_file) catch |err|1302 self.allocateAtom(atom_ptr, true, elf_file) catch |err|
1303 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});1303 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
13041304
1305 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });1305 log.debug("growing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });
1306 if (old_vaddr != atom_ptr.value) {1306 if (old_vaddr != atom_ptr.value) {
1307 sym.value = 0;1307 sym.value = 0;
1308 esym.st_value = 0;1308 esym.st_value = 0;
...@@ -1347,7 +1347,7 @@ fn updateNavCode(...@@ -1347,7 +1347,7 @@ fn updateNavCode(
1347 const file_offset = atom_ptr.offset(elf_file);1347 const file_offset = atom_ptr.offset(elf_file);
1348 elf_file.base.file.?.pwriteAll(code, file_offset) catch |err|1348 elf_file.base.file.?.pwriteAll(code, file_offset) catch |err|
1349 return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)});1349 return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)});
1350 log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });1350 log.debug("writing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
1351 }1351 }
1352}1352}
13531353
...@@ -1365,7 +1365,7 @@ fn updateTlv(...@@ -1365,7 +1365,7 @@ fn updateTlv(
1365 const gpa = zcu.gpa;1365 const gpa = zcu.gpa;
1366 const nav = ip.getNav(nav_index);1366 const nav = ip.getNav(nav_index);
13671367
1368 log.debug("updateTlv {}({d})", .{ nav.fqn.fmt(ip), nav_index });1368 log.debug("updateTlv {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
13691369
1370 const required_alignment = pt.navAlignment(nav_index);1370 const required_alignment = pt.navAlignment(nav_index);
13711371
...@@ -1424,7 +1424,7 @@ pub fn updateFunc(...@@ -1424,7 +1424,7 @@ pub fn updateFunc(
1424 const gpa = elf_file.base.comp.gpa;1424 const gpa = elf_file.base.comp.gpa;
1425 const func = zcu.funcInfo(func_index);1425 const func = zcu.funcInfo(func_index);
14261426
1427 log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });1427 log.debug("updateFunc {f}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });
14281428
1429 const sym_index = try self.getOrCreateMetadataForNav(zcu, func.owner_nav);1429 const sym_index = try self.getOrCreateMetadataForNav(zcu, func.owner_nav);
1430 self.atom(self.symbol(sym_index).ref.index).?.freeRelocs(self);1430 self.atom(self.symbol(sym_index).ref.index).?.freeRelocs(self);
...@@ -1447,7 +1447,7 @@ pub fn updateFunc(...@@ -1447,7 +1447,7 @@ pub fn updateFunc(
1447 const code = code_buffer.items;1447 const code = code_buffer.items;
14481448
1449 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);1449 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);
1450 log.debug("setting shdr({x},{s}) for {}", .{1450 log.debug("setting shdr({x},{s}) for {f}", .{
1451 shndx,1451 shndx,
1452 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),1452 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
1453 ip.getNav(func.owner_nav).fqn.fmt(ip),1453 ip.getNav(func.owner_nav).fqn.fmt(ip),
...@@ -1529,7 +1529,7 @@ pub fn updateNav(...@@ -1529,7 +1529,7 @@ pub fn updateNav(
1529 const ip = &zcu.intern_pool;1529 const ip = &zcu.intern_pool;
1530 const nav = ip.getNav(nav_index);1530 const nav = ip.getNav(nav_index);
15311531
1532 log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });1532 log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
15331533
1534 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {1534 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
1535 .func => .none,1535 .func => .none,
...@@ -1576,7 +1576,7 @@ pub fn updateNav(...@@ -1576,7 +1576,7 @@ pub fn updateNav(
1576 const code = code_buffer.items;1576 const code = code_buffer.items;
15771577
1578 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);1578 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);
1579 log.debug("setting shdr({x},{s}) for {}", .{1579 log.debug("setting shdr({x},{s}) for {f}", .{
1580 shndx,1580 shndx,
1581 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),1581 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
1582 nav.fqn.fmt(ip),1582 nav.fqn.fmt(ip),
...@@ -1622,7 +1622,7 @@ fn updateLazySymbol(...@@ -1622,7 +1622,7 @@ fn updateLazySymbol(
1622 defer code_buffer.deinit(gpa);1622 defer code_buffer.deinit(gpa);
16231623
1624 const name_str_index = blk: {1624 const name_str_index = blk: {
1625 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{1625 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
1626 @tagName(sym.kind),1626 @tagName(sym.kind),
1627 Type.fromInterned(sym.ty).fmt(pt),1627 Type.fromInterned(sym.ty).fmt(pt),
1628 });1628 });
...@@ -1941,7 +1941,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e...@@ -1941,7 +1941,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e
1941 .requires_padding = requires_padding,1941 .requires_padding = requires_padding,
1942 });1942 });
1943 atom_ptr.value = @intCast(alloc_res.value);1943 atom_ptr.value = @intCast(alloc_res.value);
1944 log.debug("allocated {s} at {x}\n placement {?}", .{1944 log.debug("allocated {s} at {x}\n placement {f}", .{
1945 atom_ptr.name(elf_file),1945 atom_ptr.name(elf_file),
1946 atom_ptr.offset(elf_file),1946 atom_ptr.offset(elf_file),
1947 alloc_res.placement,1947 alloc_res.placement,
...@@ -1986,7 +1986,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e...@@ -1986,7 +1986,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e
1986 atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 };1986 atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 };
1987 }1987 }
19881988
1989 log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });1989 log.debug(" prev {f}, next {f}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });
1990}1990}
19911991
1992pub fn resetShdrIndexes(self: *ZigObject, backlinks: []const u32) void {1992pub fn resetShdrIndexes(self: *ZigObject, backlinks: []const u32) void {
...@@ -2195,60 +2195,46 @@ pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void {...@@ -2195,60 +2195,46 @@ pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void {
2195 }2195 }
2196}2196}
21972197
2198pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {2198const Format = struct {
2199 return .{ .data = .{
2200 .self = self,
2201 .elf_file = elf_file,
2202 } };
2203}
2204
2205const FormatContext = struct {
2206 self: *ZigObject,2199 self: *ZigObject,
2207 elf_file: *Elf,2200 elf_file: *Elf,
2208};
22092201
2210fn formatSymtab(2202 fn symtab(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
2211 ctx: FormatContext,2203 const self = f.self;
2212 comptime unused_fmt_string: []const u8,2204 const elf_file = f.elf_file;
2213 options: std.fmt.FormatOptions,2205 try writer.writeAll(" locals\n");
2214 writer: anytype,2206 for (self.local_symbols.items) |index| {
2215) !void {2207 const local = self.symbols.items[index];
2216 _ = unused_fmt_string;2208 try writer.print(" {f}\n", .{local.fmt(elf_file)});
2217 _ = options;2209 }
2218 const self = ctx.self;2210 try writer.writeAll(" globals\n");
2219 const elf_file = ctx.elf_file;2211 for (f.self.global_symbols.items) |index| {
2220 try writer.writeAll(" locals\n");2212 const global = self.symbols.items[index];
2221 for (self.local_symbols.items) |index| {2213 try writer.print(" {f}\n", .{global.fmt(elf_file)});
2222 const local = self.symbols.items[index];2214 }
2223 try writer.print(" {}\n", .{local.fmt(elf_file)});
2224 }2215 }
2225 try writer.writeAll(" globals\n");2216
2226 for (ctx.self.global_symbols.items) |index| {2217 fn atoms(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
2227 const global = self.symbols.items[index];2218 try writer.writeAll(" atoms\n");
2228 try writer.print(" {}\n", .{global.fmt(elf_file)});2219 for (f.self.atoms_indexes.items) |atom_index| {
2220 const atom_ptr = f.self.atom(atom_index) orelse continue;
2221 try writer.print(" {f}\n", .{atom_ptr.fmt(f.elf_file)});
2222 }
2229 }2223 }
2230}2224};
22312225
2232pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {2226pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) {
2233 return .{ .data = .{2227 return .{ .data = .{
2234 .self = self,2228 .self = self,
2235 .elf_file = elf_file,2229 .elf_file = elf_file,
2236 } };2230 } };
2237}2231}
22382232
2239fn formatAtoms(2233pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(Format, Format.atoms) {
2240 ctx: FormatContext,2234 return .{ .data = .{
2241 comptime unused_fmt_string: []const u8,2235 .self = self,
2242 options: std.fmt.FormatOptions,2236 .elf_file = elf_file,
2243 writer: anytype,2237 } };
2244) !void {
2245 _ = unused_fmt_string;
2246 _ = options;
2247 try writer.writeAll(" atoms\n");
2248 for (ctx.self.atoms_indexes.items) |atom_index| {
2249 const atom_ptr = ctx.self.atom(atom_index) orelse continue;
2250 try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});
2251 }
2252}2238}
22532239
2254const ElfSym = struct {2240const ElfSym = struct {
...@@ -2285,7 +2271,7 @@ fn checkNavAllocated(pt: Zcu.PerThread, index: InternPool.Nav.Index, meta: AvMet...@@ -2285,7 +2271,7 @@ fn checkNavAllocated(pt: Zcu.PerThread, index: InternPool.Nav.Index, meta: AvMet
2285 const zcu = pt.zcu;2271 const zcu = pt.zcu;
2286 const ip = &zcu.intern_pool;2272 const ip = &zcu.intern_pool;
2287 const nav = ip.getNav(index);2273 const nav = ip.getNav(index);
2288 log.err("NAV {}({d}) assigned symbol {d} but not allocated!", .{2274 log.err("NAV {f}({d}) assigned symbol {d} but not allocated!", .{
2289 nav.fqn.fmt(ip),2275 nav.fqn.fmt(ip),
2290 index,2276 index,
2291 meta.symbol_index,2277 meta.symbol_index,
...@@ -2298,7 +2284,7 @@ fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadat...@@ -2298,7 +2284,7 @@ fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadat
2298 const zcu = pt.zcu;2284 const zcu = pt.zcu;
2299 const uav = Value.fromInterned(index);2285 const uav = Value.fromInterned(index);
2300 const ty = uav.typeOf(zcu);2286 const ty = uav.typeOf(zcu);
2301 log.err("UAV {}({d}) assigned symbol {d} but not allocated!", .{2287 log.err("UAV {f}({d}) assigned symbol {d} but not allocated!", .{
2302 ty.fmt(pt),2288 ty.fmt(pt),
2303 index,2289 index,
2304 meta.symbol_index,2290 meta.symbol_index,
src/link/Elf/eh_frame.zig+34-74
...@@ -47,52 +47,32 @@ pub const Fde = struct {...@@ -47,52 +47,32 @@ pub const Fde = struct {
47 return object.relocs.items[fde.rel_index..][0..fde.rel_num];47 return object.relocs.items[fde.rel_index..][0..fde.rel_num];
48 }48 }
4949
50 pub fn format(50 pub fn fmt(fde: Fde, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
51 fde: Fde,
52 comptime unused_fmt_string: []const u8,
53 options: std.fmt.FormatOptions,
54 writer: anytype,
55 ) !void {
56 _ = fde;
57 _ = unused_fmt_string;
58 _ = options;
59 _ = writer;
60 @compileError("do not format FDEs directly");
61 }
62
63 pub fn fmt(fde: Fde, elf_file: *Elf) std.fmt.Formatter(format2) {
64 return .{ .data = .{51 return .{ .data = .{
65 .fde = fde,52 .fde = fde,
66 .elf_file = elf_file,53 .elf_file = elf_file,
67 } };54 } };
68 }55 }
6956
70 const FdeFormatContext = struct {57 const Format = struct {
71 fde: Fde,58 fde: Fde,
72 elf_file: *Elf,59 elf_file: *Elf,
73 };
7460
75 fn format2(61 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
76 ctx: FdeFormatContext,62 const fde = f.fde;
77 comptime unused_fmt_string: []const u8,63 const elf_file = f.elf_file;
78 options: std.fmt.FormatOptions,64 const base_addr = fde.address(elf_file);
79 writer: anytype,65 const object = elf_file.file(fde.file_index).?.object;
80 ) !void {66 const atom_name = fde.atom(object).name(elf_file);
81 _ = unused_fmt_string;67 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{
82 _ = options;68 base_addr + fde.out_offset,
83 const fde = ctx.fde;69 fde.calcSize(),
84 const elf_file = ctx.elf_file;70 fde.cie_index,
85 const base_addr = fde.address(elf_file);71 atom_name,
86 const object = elf_file.file(fde.file_index).?.object;72 });
87 const atom_name = fde.atom(object).name(elf_file);73 if (!fde.alive) try writer.writeAll(" : [*]");
88 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{74 }
89 base_addr + fde.out_offset,75 };
90 fde.calcSize(),
91 fde.cie_index,
92 atom_name,
93 });
94 if (!fde.alive) try writer.writeAll(" : [*]");
95 }
96};76};
9777
98pub const Cie = struct {78pub const Cie = struct {
...@@ -150,48 +130,28 @@ pub const Cie = struct {...@@ -150,48 +130,28 @@ pub const Cie = struct {
150 return true;130 return true;
151 }131 }
152132
153 pub fn format(133 pub fn fmt(cie: Cie, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
154 cie: Cie,
155 comptime unused_fmt_string: []const u8,
156 options: std.fmt.FormatOptions,
157 writer: anytype,
158 ) !void {
159 _ = cie;
160 _ = unused_fmt_string;
161 _ = options;
162 _ = writer;
163 @compileError("do not format CIEs directly");
164 }
165
166 pub fn fmt(cie: Cie, elf_file: *Elf) std.fmt.Formatter(format2) {
167 return .{ .data = .{134 return .{ .data = .{
168 .cie = cie,135 .cie = cie,
169 .elf_file = elf_file,136 .elf_file = elf_file,
170 } };137 } };
171 }138 }
172139
173 const CieFormatContext = struct {140 const Format = struct {
174 cie: Cie,141 cie: Cie,
175 elf_file: *Elf,142 elf_file: *Elf,
176 };
177143
178 fn format2(144 fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
179 ctx: CieFormatContext,145 const cie = f.cie;
180 comptime unused_fmt_string: []const u8,146 const elf_file = f.elf_file;
181 options: std.fmt.FormatOptions,147 const base_addr = cie.address(elf_file);
182 writer: anytype,148 try writer.print("@{x} : size({x})", .{
183 ) !void {149 base_addr + cie.out_offset,
184 _ = unused_fmt_string;150 cie.calcSize(),
185 _ = options;151 });
186 const cie = ctx.cie;152 if (!cie.alive) try writer.writeAll(" : [*]");
187 const elf_file = ctx.elf_file;153 }
188 const base_addr = cie.address(elf_file);154 };
189 try writer.print("@{x} : size({x})", .{
190 base_addr + cie.out_offset,
191 cie.calcSize(),
192 });
193 if (!cie.alive) try writer.writeAll(" : [*]");
194 }
195};155};
196156
197pub const Iterator = struct {157pub const Iterator = struct {
...@@ -316,7 +276,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -316,7 +276,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
316 const S = math.cast(i64, sym.address(.{}, elf_file)) orelse return error.Overflow;276 const S = math.cast(i64, sym.address(.{}, elf_file)) orelse return error.Overflow;
317 const A = rel.r_addend;277 const A = rel.r_addend;
318278
319 relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{279 relocs_log.debug(" {f}: {x}: [{x} => {x}] ({s})", .{
320 relocation.fmtRelocType(rel.r_type(), cpu_arch),280 relocation.fmtRelocType(rel.r_type(), cpu_arch),
321 offset,281 offset,
322 P,282 P,
...@@ -438,7 +398,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R...@@ -438,7 +398,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R
438 },398 },
439 }399 }
440400
441 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{401 relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
442 relocation.fmtRelocType(r_type, cpu_arch),402 relocation.fmtRelocType(r_type, cpu_arch),
443 r_offset,403 r_offset,
444 r_sym,404 r_sym,
...@@ -607,11 +567,11 @@ const riscv = struct {...@@ -607,11 +567,11 @@ const riscv = struct {
607fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {567fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {
608 const diags = &elf_file.base.comp.link_diags;568 const diags = &elf_file.base.comp.link_diags;
609 var err = try diags.addErrorWithNotes(1);569 var err = try diags.addErrorWithNotes(1);
610 try err.addMsg("invalid relocation type {} at offset 0x{x}", .{570 try err.addMsg("invalid relocation type {f} at offset 0x{x}", .{
611 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),571 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
612 rel.r_offset,572 rel.r_offset,
613 });573 });
614 err.addNote("in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});574 err.addNote("in {f}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});
615 return error.RelocFailure;575 return error.RelocFailure;
616}576}
617577
src/link/Elf/file.zig+4-11
...@@ -10,23 +10,16 @@ pub const File = union(enum) {...@@ -10,23 +10,16 @@ pub const File = union(enum) {
10 };10 };
11 }11 }
1212
13 pub fn fmtPath(file: File) std.fmt.Formatter(formatPath) {13 pub fn fmtPath(file: File) std.fmt.Formatter(File, formatPath) {
14 return .{ .data = file };14 return .{ .data = file };
15 }15 }
1616
17 fn formatPath(17 fn formatPath(file: File, writer: *std.io.Writer) std.io.Writer.Error!void {
18 file: File,
19 comptime unused_fmt_string: []const u8,
20 options: std.fmt.FormatOptions,
21 writer: anytype,
22 ) !void {
23 _ = unused_fmt_string;
24 _ = options;
25 switch (file) {18 switch (file) {
26 .zig_object => |zo| try writer.writeAll(zo.basename),19 .zig_object => |zo| try writer.writeAll(zo.basename),
27 .linker_defined => try writer.writeAll("(linker defined)"),20 .linker_defined => try writer.writeAll("(linker defined)"),
28 .object => |x| try writer.print("{}", .{x.fmtPath()}),21 .object => |x| try writer.print("{f}", .{x.fmtPath()}),
29 .shared_object => |x| try writer.print("{}", .{@as(Path, x.path)}),22 .shared_object => |x| try writer.print("{f}", .{@as(Path, x.path)}),
30 }23 }
31 }24 }
3225
src/link/Elf/gc.zig+6-13
...@@ -111,7 +111,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {...@@ -111,7 +111,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
111 const target_sym = elf_file.symbol(ref) orelse continue;111 const target_sym = elf_file.symbol(ref) orelse continue;
112 const target_atom = target_sym.atom(elf_file) orelse continue;112 const target_atom = target_sym.atom(elf_file) orelse continue;
113 target_atom.alive = true;113 target_atom.alive = true;
114 gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });114 gc_track_live_log.debug("{f}marking live atom({d})", .{ track_live_level, target_atom.atom_index });
115 if (markAtom(target_atom)) markLive(target_atom, elf_file);115 if (markAtom(target_atom)) markLive(target_atom, elf_file);
116 }116 }
117 }117 }
...@@ -128,7 +128,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {...@@ -128,7 +128,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
128 }128 }
129 const target_atom = target_sym.atom(elf_file) orelse continue;129 const target_atom = target_sym.atom(elf_file) orelse continue;
130 target_atom.alive = true;130 target_atom.alive = true;
131 gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });131 gc_track_live_log.debug("{f}marking live atom({d})", .{ track_live_level, target_atom.atom_index });
132 if (markAtom(target_atom)) markLive(target_atom, elf_file);132 if (markAtom(target_atom)) markLive(target_atom, elf_file);
133 }133 }
134}134}
...@@ -163,14 +163,14 @@ fn prune(elf_file: *Elf) void {...@@ -163,14 +163,14 @@ 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.io.getStdErr().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| {
170 const atom = file.atom(atom_index) orelse continue;170 const atom = file.atom(atom_index) orelse continue;
171 if (!atom.alive)171 if (!atom.alive)
172 // TODO should we simply print to stderr?172 // TODO should we simply print to stderr?
173 try stderr.print("link: removing unused section '{s}' in file '{}'\n", .{173 try stderr.print("link: removing unused section '{s}' in file '{f}'\n", .{
174 atom.name(elf_file),174 atom.name(elf_file),
175 atom.file(elf_file).?.fmtPath(),175 atom.file(elf_file).?.fmtPath(),
176 });176 });
...@@ -185,15 +185,8 @@ const Level = struct {...@@ -185,15 +185,8 @@ const Level = struct {
185 self.value += 1;185 self.value += 1;
186 }186 }
187187
188 pub fn format(188 pub fn format(self: *const @This(), w: *std.io.Writer) std.io.Writer.Error!void {
189 self: *const @This(),189 try w.splatByteAll(' ', self.value);
190 comptime unused_fmt_string: []const u8,
191 options: std.fmt.FormatOptions,
192 writer: anytype,
193 ) !void {
194 _ = unused_fmt_string;
195 _ = options;
196 try writer.writeByteNTimes(' ', self.value);
197 }190 }
198};191};
199192
src/link/Elf/relocatable.zig+4-4
...@@ -31,7 +31,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -31,7 +31,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
31 try elf_file.allocateNonAllocSections();31 try elf_file.allocateNonAllocSections();
3232
33 if (build_options.enable_logging) {33 if (build_options.enable_logging) {
34 state_log.debug("{}", .{elf_file.dumpState()});34 state_log.debug("{f}", .{elf_file.dumpState()});
35 }35 }
3636
37 try elf_file.writeMergeSections();37 try elf_file.writeMergeSections();
...@@ -96,8 +96,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -96,8 +96,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
96 };96 };
9797
98 if (build_options.enable_logging) {98 if (build_options.enable_logging) {
99 state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(elf_file)});99 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)});
100 state_log.debug("ar_strtab\n{}\n", .{ar_strtab});100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
101 }101 }
102102
103 var buffer = std.ArrayList(u8).init(gpa);103 var buffer = std.ArrayList(u8).init(gpa);
...@@ -170,7 +170,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {...@@ -170,7 +170,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
170 try elf_file.allocateNonAllocSections();170 try elf_file.allocateNonAllocSections();
171171
172 if (build_options.enable_logging) {172 if (build_options.enable_logging) {
173 state_log.debug("{}", .{elf_file.dumpState()});173 state_log.debug("{f}", .{elf_file.dumpState()});
174 }174 }
175175
176 try writeAtoms(elf_file);176 try writeAtoms(elf_file);
src/link/Elf/relocation.zig+2-9
...@@ -141,21 +141,14 @@ const FormatRelocTypeCtx = struct {...@@ -141,21 +141,14 @@ const FormatRelocTypeCtx = struct {
141 cpu_arch: std.Target.Cpu.Arch,141 cpu_arch: std.Target.Cpu.Arch,
142};142};
143143
144pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(formatRelocType) {144pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(FormatRelocTypeCtx, formatRelocType) {
145 return .{ .data = .{145 return .{ .data = .{
146 .r_type = r_type,146 .r_type = r_type,
147 .cpu_arch = cpu_arch,147 .cpu_arch = cpu_arch,
148 } };148 } };
149}149}
150150
151fn formatRelocType(151fn formatRelocType(ctx: FormatRelocTypeCtx, writer: *std.io.Writer) std.io.Writer.Error!void {
152 ctx: FormatRelocTypeCtx,
153 comptime unused_fmt_string: []const u8,
154 options: std.fmt.FormatOptions,
155 writer: anytype,
156) !void {
157 _ = unused_fmt_string;
158 _ = options;
159 const r_type = ctx.r_type;152 const r_type = ctx.r_type;
160 switch (ctx.cpu_arch) {153 switch (ctx.cpu_arch) {
161 .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),154 .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),
src/link/Elf/synthetic_sections.zig+37-51
...@@ -606,37 +606,30 @@ pub const GotSection = struct {...@@ -606,37 +606,30 @@ pub const GotSection = struct {
606 }606 }
607 }607 }
608608
609 const FormatCtx = struct {609 const Format = struct {
610 got: GotSection,610 got: GotSection,
611 elf_file: *Elf,611 elf_file: *Elf,
612
613 pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
614 const got = f.got;
615 const elf_file = f.elf_file;
616 try writer.writeAll("GOT\n");
617 for (got.entries.items) |entry| {
618 const symbol = elf_file.symbol(entry.ref).?;
619 try writer.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
620 entry.cell_index,
621 entry.address(elf_file),
622 entry.ref,
623 symbol.address(.{}, elf_file),
624 symbol.name(elf_file),
625 });
626 }
627 }
612 };628 };
613629
614 pub fn fmt(got: GotSection, elf_file: *Elf) std.fmt.Formatter(format2) {630 pub fn fmt(got: GotSection, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
615 return .{ .data = .{ .got = got, .elf_file = elf_file } };631 return .{ .data = .{ .got = got, .elf_file = elf_file } };
616 }632 }
617
618 pub fn format2(
619 ctx: FormatCtx,
620 comptime unused_fmt_string: []const u8,
621 options: std.fmt.FormatOptions,
622 writer: anytype,
623 ) !void {
624 _ = options;
625 _ = unused_fmt_string;
626 const got = ctx.got;
627 const elf_file = ctx.elf_file;
628 try writer.writeAll("GOT\n");
629 for (got.entries.items) |entry| {
630 const symbol = elf_file.symbol(entry.ref).?;
631 try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{
632 entry.cell_index,
633 entry.address(elf_file),
634 entry.ref,
635 symbol.address(.{}, elf_file),
636 symbol.name(elf_file),
637 });
638 }
639 }
640};633};
641634
642pub const PltSection = struct {635pub const PltSection = struct {
...@@ -703,7 +696,7 @@ pub const PltSection = struct {...@@ -703,7 +696,7 @@ pub const PltSection = struct {
703 const r_sym: u64 = extra.dynamic;696 const r_sym: u64 = extra.dynamic;
704 const r_type = relocation.encode(.jump_slot, cpu_arch);697 const r_type = relocation.encode(.jump_slot, cpu_arch);
705698
706 relocs_log.debug(" {s}: [{x} => {d}({s})] + 0", .{699 relocs_log.debug(" {f}: [{x} => {d}({s})] + 0", .{
707 relocation.fmtRelocType(r_type, cpu_arch),700 relocation.fmtRelocType(r_type, cpu_arch),
708 r_offset,701 r_offset,
709 r_sym,702 r_sym,
...@@ -749,38 +742,31 @@ pub const PltSection = struct {...@@ -749,38 +742,31 @@ pub const PltSection = struct {
749 }742 }
750 }743 }
751744
752 const FormatCtx = struct {745 const Format = struct {
753 plt: PltSection,746 plt: PltSection,
754 elf_file: *Elf,747 elf_file: *Elf,
748
749 pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
750 const plt = f.plt;
751 const elf_file = f.elf_file;
752 try writer.writeAll("PLT\n");
753 for (plt.symbols.items, 0..) |ref, i| {
754 const symbol = elf_file.symbol(ref).?;
755 try writer.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
756 i,
757 symbol.pltAddress(elf_file),
758 ref,
759 symbol.address(.{}, elf_file),
760 symbol.name(elf_file),
761 });
762 }
763 }
755 };764 };
756765
757 pub fn fmt(plt: PltSection, elf_file: *Elf) std.fmt.Formatter(format2) {766 pub fn fmt(plt: PltSection, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) {
758 return .{ .data = .{ .plt = plt, .elf_file = elf_file } };767 return .{ .data = .{ .plt = plt, .elf_file = elf_file } };
759 }768 }
760769
761 pub fn format2(
762 ctx: FormatCtx,
763 comptime unused_fmt_string: []const u8,
764 options: std.fmt.FormatOptions,
765 writer: anytype,
766 ) !void {
767 _ = options;
768 _ = unused_fmt_string;
769 const plt = ctx.plt;
770 const elf_file = ctx.elf_file;
771 try writer.writeAll("PLT\n");
772 for (plt.symbols.items, 0..) |ref, i| {
773 const symbol = elf_file.symbol(ref).?;
774 try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{
775 i,
776 symbol.pltAddress(elf_file),
777 ref,
778 symbol.address(.{}, elf_file),
779 symbol.name(elf_file),
780 });
781 }
782 }
783
784 const x86_64 = struct {770 const x86_64 = struct {
785 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {771 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
786 const shdrs = elf_file.sections.items(.shdr);772 const shdrs = elf_file.sections.items(.shdr);
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+12-16
...@@ -294,7 +294,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {...@@ -294,7 +294,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
294 break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);294 break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
295 } else null;295 } else null;
296296
297 log.debug("zcu_obj_path={?}", .{zcu_obj_path});297 log.debug("zcu_obj_path={?f}", .{zcu_obj_path});
298298
299 const compiler_rt_path: ?Cache.Path = if (comp.compiler_rt_strat == .obj)299 const compiler_rt_path: ?Cache.Path = if (comp.compiler_rt_strat == .obj)
300 comp.compiler_rt_obj.?.full_object_path300 comp.compiler_rt_obj.?.full_object_path
...@@ -437,7 +437,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {...@@ -437,7 +437,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
437 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));437 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));
438 }438 }
439 if (comp.version) |version| {439 if (comp.version) |version| {
440 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));440 try argv.append(try allocPrint(arena, "-VERSION:{d}.{d}", .{ version.major, version.minor }));
441 }441 }
442442
443 if (target_util.llvmMachineAbi(target)) |mabi| {443 if (target_util.llvmMachineAbi(target)) |mabi| {
...@@ -507,7 +507,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {...@@ -507,7 +507,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
507507
508 if (comp.emit_implib) |raw_emit_path| {508 if (comp.emit_implib) |raw_emit_path| {
509 const path = try comp.resolveEmitPathFlush(arena, .temp, raw_emit_path);509 const path = try comp.resolveEmitPathFlush(arena, .temp, raw_emit_path);
510 try argv.append(try allocPrint(arena, "-IMPLIB:{}", .{path}));510 try argv.append(try allocPrint(arena, "-IMPLIB:{f}", .{path}));
511 }511 }
512512
513 if (comp.config.link_libc) {513 if (comp.config.link_libc) {
...@@ -533,7 +533,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {...@@ -533,7 +533,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
533 },533 },
534 .object, .archive => |obj| {534 .object, .archive => |obj| {
535 if (obj.must_link) {535 if (obj.must_link) {
536 argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{}", .{@as(Cache.Path, obj.path)}));536 argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{f}", .{@as(Cache.Path, obj.path)}));
537 } else {537 } else {
538 argv.appendAssumeCapacity(try obj.path.toString(arena));538 argv.appendAssumeCapacity(try obj.path.toString(arena));
539 }539 }
...@@ -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}));
...@@ -1218,7 +1216,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -1218,7 +1216,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
1218 if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;1216 if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
1219 }1217 }
12201218
1221 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{1219 const lib_path = try std.fmt.allocPrint(arena, "{f}{c}lib{s}.so.{d}", .{
1222 comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,1220 comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
1223 });1221 });
1224 try argv.append(lib_path);1222 try argv.append(lib_path);
...@@ -1231,14 +1229,14 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -1231,14 +1229,14 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
1231 }));1229 }));
1232 } else if (target.isFreeBSDLibC()) {1230 } else if (target.isFreeBSDLibC()) {
1233 for (freebsd.libs) |lib| {1231 for (freebsd.libs) |lib| {
1234 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{1232 const lib_path = try std.fmt.allocPrint(arena, "{f}{c}lib{s}.so.{d}", .{
1235 comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,1233 comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
1236 });1234 });
1237 try argv.append(lib_path);1235 try argv.append(lib_path);
1238 }1236 }
1239 } else if (target.isNetBSDLibC()) {1237 } else if (target.isNetBSDLibC()) {
1240 for (netbsd.libs) |lib| {1238 for (netbsd.libs) |lib| {
1241 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{1239 const lib_path = try std.fmt.allocPrint(arena, "{f}{c}lib{s}.so.{d}", .{
1242 comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,1240 comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
1243 });1241 });
1244 try argv.append(lib_path);1242 try argv.append(lib_path);
...@@ -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
...@@ -1653,7 +1649,7 @@ fn spawnLld(...@@ -1653,7 +1649,7 @@ fn spawnLld(
1653 child.stderr_behavior = .Pipe;1649 child.stderr_behavior = .Pipe;
16541650
1655 child.spawn() catch |err| break :term err;1651 child.spawn() catch |err| break :term err;
1656 stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));1652 stderr = try child.stderr.?.deprecatedReader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
1657 break :term child.wait();1653 break :term child.wait();
1658 }) catch |first_err| term: {1654 }) catch |first_err| term: {
1659 const err = switch (first_err) {1655 const err = switch (first_err) {
...@@ -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('"');
...@@ -1701,7 +1697,7 @@ fn spawnLld(...@@ -1701,7 +1697,7 @@ fn spawnLld(
1701 rsp_child.stderr_behavior = .Pipe;1697 rsp_child.stderr_behavior = .Pipe;
17021698
1703 rsp_child.spawn() catch |err| break :err err;1699 rsp_child.spawn() catch |err| break :err err;
1704 stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));1700 stderr = try rsp_child.stderr.?.deprecatedReader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
1705 break :term rsp_child.wait() catch |err| break :err err;1701 break :term rsp_child.wait() catch |err| break :err err;
1706 }1702 }
1707 },1703 },
src/link/MachO.zig+56-97
...@@ -543,7 +543,7 @@ pub fn flush(...@@ -543,7 +543,7 @@ pub fn flush(
543 self.allocateSyntheticSymbols();543 self.allocateSyntheticSymbols();
544544
545 if (build_options.enable_logging) {545 if (build_options.enable_logging) {
546 state_log.debug("{}", .{self.dumpState()});546 state_log.debug("{f}", .{self.dumpState()});
547 }547 }
548548
549 // Beyond this point, everything has been allocated a virtual address and we can resolve549 // Beyond this point, everything has been allocated a virtual address and we can resolve
...@@ -677,12 +677,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {...@@ -677,12 +677,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
677677
678 try argv.append("-platform_version");678 try argv.append("-platform_version");
679 try argv.append(@tagName(self.platform.os_tag));679 try argv.append(@tagName(self.platform.os_tag));
680 try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version}));680 try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version}));
681681
682 if (self.sdk_version) |ver| {682 if (self.sdk_version) |ver| {
683 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));683 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));
684 } else {684 } else {
685 try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version}));685 try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version}));
686 }686 }
687687
688 if (comp.sysroot) |syslibroot| {688 if (comp.sysroot) |syslibroot| {
...@@ -863,7 +863,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void {...@@ -863,7 +863,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void {
863863
864 const path, const file = input.pathAndFile().?;864 const path, const file = input.pathAndFile().?;
865 // TODO don't classify now, it's too late. The input file has already been classified865 // TODO don't classify now, it's too late. The input file has already been classified
866 log.debug("classifying input file {}", .{path});866 log.debug("classifying input file {f}", .{path});
867867
868 const fh = try self.addFileHandle(file);868 const fh = try self.addFileHandle(file);
869 var buffer: [Archive.SARMAG]u8 = undefined;869 var buffer: [Archive.SARMAG]u8 = undefined;
...@@ -1591,7 +1591,7 @@ fn reportUndefs(self: *MachO) !void {...@@ -1591,7 +1591,7 @@ fn reportUndefs(self: *MachO) !void {
1591 const ref = refs.items[inote];1591 const ref = refs.items[inote];
1592 const file = self.getFile(ref.file).?;1592 const file = self.getFile(ref.file).?;
1593 const atom = ref.getAtom(self).?;1593 const atom = ref.getAtom(self).?;
1594 err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) });1594 err.addNote("referenced by {f}:{s}", .{ file.fmtPath(), atom.getName(self) });
1595 }1595 }
15961596
1597 if (refs.items.len > max_notes) {1597 if (refs.items.len > max_notes) {
...@@ -3791,7 +3791,7 @@ pub fn reportParseError2(...@@ -3791,7 +3791,7 @@ pub fn reportParseError2(
3791 const diags = &self.base.comp.link_diags;3791 const diags = &self.base.comp.link_diags;
3792 var err = try diags.addErrorWithNotes(1);3792 var err = try diags.addErrorWithNotes(1);
3793 try err.addMsg(format, args);3793 try err.addMsg(format, args);
3794 err.addNote("while parsing {}", .{self.getFile(file_index).?.fmtPath()});3794 err.addNote("while parsing {f}", .{self.getFile(file_index).?.fmtPath()});
3795}3795}
37963796
3797fn reportMissingDependencyError(3797fn reportMissingDependencyError(
...@@ -3806,7 +3806,7 @@ fn reportMissingDependencyError(...@@ -3806,7 +3806,7 @@ fn reportMissingDependencyError(
3806 var err = try diags.addErrorWithNotes(2 + checked_paths.len);3806 var err = try diags.addErrorWithNotes(2 + checked_paths.len);
3807 try err.addMsg(format, args);3807 try err.addMsg(format, args);
3808 err.addNote("while resolving {s}", .{path});3808 err.addNote("while resolving {s}", .{path});
3809 err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});3809 err.addNote("a dependency of {f}", .{self.getFile(parent).?.fmtPath()});
3810 for (checked_paths) |p| {3810 for (checked_paths) |p| {
3811 err.addNote("tried {s}", .{p});3811 err.addNote("tried {s}", .{p});
3812 }3812 }
...@@ -3823,7 +3823,7 @@ fn reportDependencyError(...@@ -3823,7 +3823,7 @@ fn reportDependencyError(
3823 var err = try diags.addErrorWithNotes(2);3823 var err = try diags.addErrorWithNotes(2);
3824 try err.addMsg(format, args);3824 try err.addMsg(format, args);
3825 err.addNote("while parsing {s}", .{path});3825 err.addNote("while parsing {s}", .{path});
3826 err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});3826 err.addNote("a dependency of {f}", .{self.getFile(parent).?.fmtPath()});
3827}3827}
38283828
3829fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {3829fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
...@@ -3853,12 +3853,12 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {...@@ -3853,12 +3853,12 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
38533853
3854 var err = try diags.addErrorWithNotes(nnotes + 1);3854 var err = try diags.addErrorWithNotes(nnotes + 1);
3855 try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});3855 try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});
3856 err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()});3856 err.addNote("defined by {f}", .{sym.getFile(self).?.fmtPath()});
38573857
3858 var inote: usize = 0;3858 var inote: usize = 0;
3859 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {3859 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
3860 const file = self.getFile(notes.items[inote]).?;3860 const file = self.getFile(notes.items[inote]).?;
3861 err.addNote("defined by {}", .{file.fmtPath()});3861 err.addNote("defined by {f}", .{file.fmtPath()});
3862 }3862 }
38633863
3864 if (notes.items.len > max_notes) {3864 if (notes.items.len > max_notes) {
...@@ -3900,35 +3900,28 @@ pub fn ptraceDetach(self: *MachO, pid: std.posix.pid_t) !void {...@@ -3900,35 +3900,28 @@ pub fn ptraceDetach(self: *MachO, pid: std.posix.pid_t) !void {
3900 self.hot_state.mach_task = null;3900 self.hot_state.mach_task = null;
3901}3901}
39023902
3903pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) {3903pub fn dumpState(self: *MachO) std.fmt.Formatter(*MachO, fmtDumpState) {
3904 return .{ .data = self };3904 return .{ .data = self };
3905}3905}
39063906
3907fn fmtDumpState(3907fn fmtDumpState(self: *MachO, w: *Writer) Writer.Error!void {
3908 self: *MachO,
3909 comptime unused_fmt_string: []const u8,
3910 options: std.fmt.FormatOptions,
3911 writer: anytype,
3912) !void {
3913 _ = options;
3914 _ = unused_fmt_string;
3915 if (self.getZigObject()) |zo| {3908 if (self.getZigObject()) |zo| {
3916 try writer.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename });3909 try w.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename });
3917 try writer.print("{}{}\n", .{3910 try w.print("{f}{f}\n", .{
3918 zo.fmtAtoms(self),3911 zo.fmtAtoms(self),
3919 zo.fmtSymtab(self),3912 zo.fmtSymtab(self),
3920 });3913 });
3921 }3914 }
3922 for (self.objects.items) |index| {3915 for (self.objects.items) |index| {
3923 const object = self.getFile(index).?.object;3916 const object = self.getFile(index).?.object;
3924 try writer.print("object({d}) : {} : has_debug({})", .{3917 try w.print("object({d}) : {f} : has_debug({})", .{
3925 index,3918 index,
3926 object.fmtPath(),3919 object.fmtPath(),
3927 object.hasDebugInfo(),3920 object.hasDebugInfo(),
3928 });3921 });
3929 if (!object.alive) try writer.writeAll(" : ([*])");3922 if (!object.alive) try w.writeAll(" : ([*])");
3930 try writer.writeByte('\n');3923 try w.writeByte('\n');
3931 try writer.print("{}{}{}{}{}\n", .{3924 try w.print("{f}{f}{f}{f}{f}\n", .{
3932 object.fmtAtoms(self),3925 object.fmtAtoms(self),
3933 object.fmtCies(self),3926 object.fmtCies(self),
3934 object.fmtFdes(self),3927 object.fmtFdes(self),
...@@ -3938,48 +3931,41 @@ fn fmtDumpState(...@@ -3938,48 +3931,41 @@ fn fmtDumpState(
3938 }3931 }
3939 for (self.dylibs.items) |index| {3932 for (self.dylibs.items) |index| {
3940 const dylib = self.getFile(index).?.dylib;3933 const dylib = self.getFile(index).?.dylib;
3941 try writer.print("dylib({d}) : {} : needed({}) : weak({})", .{3934 try w.print("dylib({d}) : {f} : needed({}) : weak({})", .{
3942 index,3935 index,
3943 @as(Path, dylib.path),3936 @as(Path, dylib.path),
3944 dylib.needed,3937 dylib.needed,
3945 dylib.weak,3938 dylib.weak,
3946 });3939 });
3947 if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])");3940 if (!dylib.isAlive(self)) try w.writeAll(" : ([*])");
3948 try writer.writeByte('\n');3941 try w.writeByte('\n');
3949 try writer.print("{}\n", .{dylib.fmtSymtab(self)});3942 try w.print("{f}\n", .{dylib.fmtSymtab(self)});
3950 }3943 }
3951 if (self.getInternalObject()) |internal| {3944 if (self.getInternalObject()) |internal| {
3952 try writer.print("internal({d}) : internal\n", .{internal.index});3945 try w.print("internal({d}) : internal\n", .{internal.index});
3953 try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) });3946 try w.print("{f}{f}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) });
3954 }3947 }
3955 try writer.writeAll("thunks\n");3948 try w.writeAll("thunks\n");
3956 for (self.thunks.items, 0..) |thunk, index| {3949 for (self.thunks.items, 0..) |thunk, index| {
3957 try writer.print("thunk({d}) : {}\n", .{ index, thunk.fmt(self) });3950 try w.print("thunk({d}) : {f}\n", .{ index, thunk.fmt(self) });
3958 }3951 }
3959 try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)});3952 try w.print("stubs\n{f}\n", .{self.stubs.fmt(self)});
3960 try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)});3953 try w.print("objc_stubs\n{f}\n", .{self.objc_stubs.fmt(self)});
3961 try writer.print("got\n{}\n", .{self.got.fmt(self)});3954 try w.print("got\n{f}\n", .{self.got.fmt(self)});
3962 try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)});3955 try w.print("tlv_ptr\n{f}\n", .{self.tlv_ptr.fmt(self)});
3963 try writer.writeByte('\n');3956 try w.writeByte('\n');
3964 try writer.print("sections\n{}\n", .{self.fmtSections()});3957 try w.print("sections\n{f}\n", .{self.fmtSections()});
3965 try writer.print("segments\n{}\n", .{self.fmtSegments()});3958 try w.print("segments\n{f}\n", .{self.fmtSegments()});
3966}3959}
39673960
3968fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) {3961fn fmtSections(self: *MachO) std.fmt.Formatter(*MachO, formatSections) {
3969 return .{ .data = self };3962 return .{ .data = self };
3970}3963}
39713964
3972fn formatSections(3965fn formatSections(self: *MachO, w: *Writer) Writer.Error!void {
3973 self: *MachO,
3974 comptime unused_fmt_string: []const u8,
3975 options: std.fmt.FormatOptions,
3976 writer: anytype,
3977) !void {
3978 _ = options;
3979 _ = unused_fmt_string;
3980 const slice = self.sections.slice();3966 const slice = self.sections.slice();
3981 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {3967 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {
3982 try writer.print(3968 try w.print(
3983 "sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x}) : relocs({x};{d})\n",3969 "sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x}) : relocs({x};{d})\n",
3984 .{3970 .{
3985 i, seg_id, header.segName(), header.sectName(), header.addr, header.offset,3971 i, seg_id, header.segName(), header.sectName(), header.addr, header.offset,
...@@ -3989,38 +3975,24 @@ fn formatSections(...@@ -3989,38 +3975,24 @@ fn formatSections(
3989 }3975 }
3990}3976}
39913977
3992fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) {3978fn fmtSegments(self: *MachO) std.fmt.Formatter(*MachO, formatSegments) {
3993 return .{ .data = self };3979 return .{ .data = self };
3994}3980}
39953981
3996fn formatSegments(3982fn formatSegments(self: *MachO, w: *Writer) Writer.Error!void {
3997 self: *MachO,
3998 comptime unused_fmt_string: []const u8,
3999 options: std.fmt.FormatOptions,
4000 writer: anytype,
4001) !void {
4002 _ = options;
4003 _ = unused_fmt_string;
4004 for (self.segments.items, 0..) |seg, i| {3983 for (self.segments.items, 0..) |seg, i| {
4005 try writer.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{3984 try w.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{
4006 i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize,3985 i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize,
4007 seg.fileoff, seg.fileoff + seg.filesize,3986 seg.fileoff, seg.fileoff + seg.filesize,
4008 });3987 });
4009 }3988 }
4010}3989}
40113990
4012pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) {3991pub fn fmtSectType(tt: u8) std.fmt.Formatter(u8, formatSectType) {
4013 return .{ .data = tt };3992 return .{ .data = tt };
4014}3993}
40153994
4016fn formatSectType(3995fn formatSectType(tt: u8, w: *Writer) Writer.Error!void {
4017 tt: u8,
4018 comptime unused_fmt_string: []const u8,
4019 options: std.fmt.FormatOptions,
4020 writer: anytype,
4021) !void {
4022 _ = options;
4023 _ = unused_fmt_string;
4024 const name = switch (tt) {3996 const name = switch (tt) {
4025 macho.S_REGULAR => "REGULAR",3997 macho.S_REGULAR => "REGULAR",
4026 macho.S_ZEROFILL => "ZEROFILL",3998 macho.S_ZEROFILL => "ZEROFILL",
...@@ -4044,9 +4016,9 @@ fn formatSectType(...@@ -4044,9 +4016,9 @@ fn formatSectType(
4044 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS",4016 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS",
4045 macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS",4017 macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS",
4046 macho.S_INIT_FUNC_OFFSETS => "INIT_FUNC_OFFSETS",4018 macho.S_INIT_FUNC_OFFSETS => "INIT_FUNC_OFFSETS",
4047 else => |x| return writer.print("UNKNOWN({x})", .{x}),4019 else => |x| return w.print("UNKNOWN({x})", .{x}),
4048 };4020 };
4049 try writer.print("{s}", .{name});4021 try w.print("{s}", .{name});
4050}4022}
40514023
4052const is_hot_update_compatible = switch (builtin.target.os.tag) {4024const is_hot_update_compatible = switch (builtin.target.os.tag) {
...@@ -4279,34 +4251,27 @@ pub const Platform = struct {...@@ -4279,34 +4251,27 @@ pub const Platform = struct {
4279 return false;4251 return false;
4280 }4252 }
42814253
4282 pub fn fmtTarget(plat: Platform, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(formatTarget) {4254 pub fn fmtTarget(plat: Platform, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(Format, Format.target) {
4283 return .{ .data = .{ .platform = plat, .cpu_arch = cpu_arch } };4255 return .{ .data = .{ .platform = plat, .cpu_arch = cpu_arch } };
4284 }4256 }
42854257
4286 const FmtCtx = struct {4258 const Format = struct {
4287 platform: Platform,4259 platform: Platform,
4288 cpu_arch: std.Target.Cpu.Arch,4260 cpu_arch: std.Target.Cpu.Arch,
4289 };
42904261
4291 pub fn formatTarget(4262 pub fn target(f: Format, w: *Writer) Writer.Error!void {
4292 ctx: FmtCtx,4263 try w.print("{s}-{s}", .{ @tagName(f.cpu_arch), @tagName(f.platform.os_tag) });
4293 comptime unused_fmt_string: []const u8,4264 if (f.platform.abi != .none) {
4294 options: std.fmt.FormatOptions,4265 try w.print("-{s}", .{@tagName(f.platform.abi)});
4295 writer: anytype,4266 }
4296 ) !void {
4297 _ = unused_fmt_string;
4298 _ = options;
4299 try writer.print("{s}-{s}", .{ @tagName(ctx.cpu_arch), @tagName(ctx.platform.os_tag) });
4300 if (ctx.platform.abi != .none) {
4301 try writer.print("-{s}", .{@tagName(ctx.platform.abi)});
4302 }4267 }
4303 }4268 };
43044269
4305 /// Caller owns the memory.4270 /// Caller owns the memory.
4306 pub fn allocPrintTarget(plat: Platform, gpa: Allocator, cpu_arch: std.Target.Cpu.Arch) error{OutOfMemory}![]u8 {4271 pub fn allocPrintTarget(plat: Platform, gpa: Allocator, cpu_arch: std.Target.Cpu.Arch) error{OutOfMemory}![]u8 {
4307 var buffer = std.ArrayList(u8).init(gpa);4272 var buffer = std.ArrayList(u8).init(gpa);
4308 defer buffer.deinit();4273 defer buffer.deinit();
4309 try buffer.writer().print("{}", .{plat.fmtTarget(cpu_arch)});4274 try buffer.writer().print("{f}", .{plat.fmtTarget(cpu_arch)});
4310 return buffer.toOwnedSlice();4275 return buffer.toOwnedSlice();
4311 }4276 }
43124277
...@@ -4507,15 +4472,8 @@ pub const Ref = struct {...@@ -4507,15 +4472,8 @@ pub const Ref = struct {
4507 };4472 };
4508 }4473 }
45094474
4510 pub fn format(4475 pub fn format(ref: Ref, bw: *Writer) Writer.Error!void {
4511 ref: Ref,4476 try bw.print("%{d} in file({d})", .{ ref.index, ref.file });
4512 comptime unused_fmt_string: []const u8,
4513 options: std.fmt.FormatOptions,
4514 writer: anytype,
4515 ) !void {
4516 _ = unused_fmt_string;
4517 _ = options;
4518 try writer.print("%{d} in file({d})", .{ ref.index, ref.file });
4519 }4477 }
4520};4478};
45214479
...@@ -5315,7 +5273,7 @@ fn createThunks(macho_file: *MachO, sect_id: u8) !void {...@@ -5315,7 +5273,7 @@ fn createThunks(macho_file: *MachO, sect_id: u8) !void {
5315 try scanThunkRelocs(thunk_index, gpa, atoms[start..i], macho_file);5273 try scanThunkRelocs(thunk_index, gpa, atoms[start..i], macho_file);
5316 thunk.value = advanceSection(header, thunk.size(), .@"4");5274 thunk.value = advanceSection(header, thunk.size(), .@"4");
53175275
5318 log.debug("thunk({d}) : {}", .{ thunk_index, thunk.fmt(macho_file) });5276 log.debug("thunk({d}) : {f}", .{ thunk_index, thunk.fmt(macho_file) });
5319 }5277 }
5320}5278}
53215279
...@@ -5414,6 +5372,7 @@ const macho = std.macho;...@@ -5414,6 +5372,7 @@ const macho = std.macho;
5414const math = std.math;5372const math = std.math;
5415const mem = std.mem;5373const mem = std.mem;
5416const meta = std.meta;5374const meta = std.meta;
5375const Writer = std.io.Writer;
54175376
5418const aarch64 = @import("../arch/aarch64/bits.zig");5377const aarch64 = @import("../arch/aarch64/bits.zig");
5419const bind = @import("MachO/dyld_info/bind.zig");5378const bind = @import("MachO/dyld_info/bind.zig");
src/link/MachO/Archive.zig+17-23
...@@ -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
...@@ -71,7 +71,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File...@@ -71,7 +71,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
71 .mtime = hdr.date() catch 0,71 .mtime = hdr.date() catch 0,
72 };72 };
7373
74 log.debug("extracting object '{}' from archive '{}'", .{ object.path, path });74 log.debug("extracting object '{f}' from archive '{f}'", .{ object.path, path });
7575
76 try self.objects.append(gpa, object);76 try self.objects.append(gpa, object);
77 }77 }
...@@ -230,32 +230,25 @@ pub const ArSymtab = struct {...@@ -230,32 +230,25 @@ pub const ArSymtab = struct {
230 }230 }
231 }231 }
232232
233 const FormatContext = struct {233 const PrintFormat = struct {
234 ar: ArSymtab,234 ar: ArSymtab,
235 macho_file: *MachO,235 macho_file: *MachO,
236
237 fn default(f: PrintFormat, bw: *Writer) Writer.Error!void {
238 const ar = f.ar;
239 const macho_file = f.macho_file;
240 for (ar.entries.items, 0..) |entry, i| {
241 const name = ar.strtab.getAssumeExists(entry.off);
242 const file = macho_file.getFile(entry.file).?;
243 try bw.print(" {d}: {s} in file({d})({f})\n", .{ i, name, entry.file, file.fmtPath() });
244 }
245 }
236 };246 };
237247
238 pub fn fmt(ar: ArSymtab, macho_file: *MachO) std.fmt.Formatter(format2) {248 pub fn fmt(ar: ArSymtab, macho_file: *MachO) std.fmt.Formatter(PrintFormat, PrintFormat.default) {
239 return .{ .data = .{ .ar = ar, .macho_file = macho_file } };249 return .{ .data = .{ .ar = ar, .macho_file = macho_file } };
240 }250 }
241251
242 fn format2(
243 ctx: FormatContext,
244 comptime unused_fmt_string: []const u8,
245 options: std.fmt.FormatOptions,
246 writer: anytype,
247 ) !void {
248 _ = unused_fmt_string;
249 _ = options;
250 const ar = ctx.ar;
251 const macho_file = ctx.macho_file;
252 for (ar.entries.items, 0..) |entry, i| {
253 const name = ar.strtab.getAssumeExists(entry.off);
254 const file = macho_file.getFile(entry.file).?;
255 try writer.print(" {d}: {s} in file({d})({})\n", .{ i, name, entry.file, file.fmtPath() });
256 }
257 }
258
259 const Entry = struct {252 const Entry = struct {
260 /// Symbol name offset253 /// Symbol name offset
261 off: u32,254 off: u32,
...@@ -304,8 +297,9 @@ const log = std.log.scoped(.link);...@@ -304,8 +297,9 @@ const log = std.log.scoped(.link);
304const macho = std.macho;297const macho = std.macho;
305const mem = std.mem;298const mem = std.mem;
306const std = @import("std");299const std = @import("std");
307const Allocator = mem.Allocator;300const Allocator = std.mem.Allocator;
308const Path = std.Build.Cache.Path;301const Path = std.Build.Cache.Path;
302const Writer = std.io.Writer;
309303
310const Archive = @This();304const Archive = @This();
311const File = @import("file.zig").File;305const File = @import("file.zig").File;
src/link/MachO/Atom.zig+41-63
...@@ -602,7 +602,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -602,7 +602,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
602 };602 };
603 try macho_file.reportParseError2(603 try macho_file.reportParseError2(
604 file.getIndex(),604 file.getIndex(),
605 "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {}, target {s}",605 "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {f}, target {s}",
606 .{606 .{
607 name,607 name,
608 self.getAddress(macho_file),608 self.getAddress(macho_file),
...@@ -653,7 +653,7 @@ fn resolveRelocInner(...@@ -653,7 +653,7 @@ fn resolveRelocInner(
653 const divExact = struct {653 const divExact = struct {
654 fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {654 fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {
655 return math.divExact(u12, num, den) catch {655 return math.divExact(u12, num, den) catch {
656 try ctx.reportParseError2(atom.getFile(ctx).getIndex(), "{s}: unexpected remainder when resolving {s} at offset 0x{x}", .{656 try ctx.reportParseError2(atom.getFile(ctx).getIndex(), "{s}: unexpected remainder when resolving {f} at offset 0x{x}", .{
657 atom.getName(ctx),657 atom.getName(ctx),
658 r.fmtPretty(ctx.getTarget().cpu.arch),658 r.fmtPretty(ctx.getTarget().cpu.arch),
659 r.offset,659 r.offset,
...@@ -664,14 +664,14 @@ fn resolveRelocInner(...@@ -664,14 +664,14 @@ fn resolveRelocInner(
664 }.divExact;664 }.divExact;
665665
666 switch (rel.tag) {666 switch (rel.tag) {
667 .local => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] atom({d})", .{667 .local => relocs_log.debug(" {x}<+{d}>: {f}: [=> {x}] atom({d})", .{
668 P,668 P,
669 rel_offset,669 rel_offset,
670 rel.fmtPretty(cpu_arch),670 rel.fmtPretty(cpu_arch),
671 S + A - SUB,671 S + A - SUB,
672 rel.getTargetAtom(self, macho_file).atom_index,672 rel.getTargetAtom(self, macho_file).atom_index,
673 }),673 }),
674 .@"extern" => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] G({x}) ({s})", .{674 .@"extern" => relocs_log.debug(" {x}<+{d}>: {f}: [=> {x}] G({x}) ({s})", .{
675 P,675 P,
676 rel_offset,676 rel_offset,
677 rel.fmtPretty(cpu_arch),677 rel.fmtPretty(cpu_arch),
...@@ -900,19 +900,19 @@ const x86_64 = struct {...@@ -900,19 +900,19 @@ const x86_64 = struct {
900 switch (old_inst.encoding.mnemonic) {900 switch (old_inst.encoding.mnemonic) {
901 .mov => {901 .mov => {
902 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;902 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;
903 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });903 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
904 encode(&.{inst}, code) catch return error.RelaxFail;904 encode(&.{inst}, code) catch return error.RelaxFail;
905 },905 },
906 else => |x| {906 else => |x| {
907 var err = try diags.addErrorWithNotes(2);907 var err = try diags.addErrorWithNotes(2);
908 try err.addMsg("{s}: 0x{x}: 0x{x}: failed to relax relocation of type {}", .{908 try err.addMsg("{s}: 0x{x}: 0x{x}: failed to relax relocation of type {f}", .{
909 self.getName(macho_file),909 self.getName(macho_file),
910 self.getAddress(macho_file),910 self.getAddress(macho_file),
911 rel.offset,911 rel.offset,
912 rel.fmtPretty(.x86_64),912 rel.fmtPretty(.x86_64),
913 });913 });
914 err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)});914 err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)});
915 err.addNote("while parsing {}", .{self.getFile(macho_file).fmtPath()});915 err.addNote("while parsing {f}", .{self.getFile(macho_file).fmtPath()});
916 return error.RelaxFailUnexpectedInstruction;916 return error.RelaxFailUnexpectedInstruction;
917 },917 },
918 }918 }
...@@ -924,7 +924,7 @@ const x86_64 = struct {...@@ -924,7 +924,7 @@ const x86_64 = struct {
924 switch (old_inst.encoding.mnemonic) {924 switch (old_inst.encoding.mnemonic) {
925 .mov => {925 .mov => {
926 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;926 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;
927 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });927 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
928 encode(&.{inst}, code) catch return error.RelaxFail;928 encode(&.{inst}, code) catch return error.RelaxFail;
929 },929 },
930 else => return error.RelaxFail,930 else => return error.RelaxFail,
...@@ -938,11 +938,8 @@ const x86_64 = struct {...@@ -938,11 +938,8 @@ const x86_64 = struct {
938 }938 }
939939
940 fn encode(insts: []const Instruction, code: []u8) !void {940 fn encode(insts: []const Instruction, code: []u8) !void {
941 var stream = std.io.fixedBufferStream(code);941 var stream: Writer = .fixed(code);
942 const writer = stream.writer();942 for (insts) |inst| try inst.encode(&stream, .{});
943 for (insts) |inst| {
944 try inst.encode(writer, .{});
945 }
946 }943 }
947944
948 const bits = @import("../../arch/x86_64/bits.zig");945 const bits = @import("../../arch/x86_64/bits.zig");
...@@ -1003,7 +1000,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1003,7 +1000,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1003 }1000 }
10041001
1005 switch (rel.tag) {1002 switch (rel.tag) {
1006 .local => relocs_log.debug(" {}: [{x} => {d}({s},{s})] + {x}", .{1003 .local => relocs_log.debug(" {f}: [{x} => {d}({s},{s})] + {x}", .{
1007 rel.fmtPretty(cpu_arch),1004 rel.fmtPretty(cpu_arch),
1008 r_address,1005 r_address,
1009 r_symbolnum,1006 r_symbolnum,
...@@ -1011,7 +1008,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1011,7 +1008,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1011 macho_file.sections.items(.header)[r_symbolnum - 1].sectName(),1008 macho_file.sections.items(.header)[r_symbolnum - 1].sectName(),
1012 addend,1009 addend,
1013 }),1010 }),
1014 .@"extern" => relocs_log.debug(" {}: [{x} => {d}({s})] + {x}", .{1011 .@"extern" => relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
1015 rel.fmtPretty(cpu_arch),1012 rel.fmtPretty(cpu_arch),
1016 r_address,1013 r_address,
1017 r_symbolnum,1014 r_symbolnum,
...@@ -1117,60 +1114,40 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1117,60 +1114,40 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1117 assert(i == buffer.len);1114 assert(i == buffer.len);
1118}1115}
11191116
1120pub fn format(1117pub fn fmt(atom: Atom, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) {
1121 atom: Atom,
1122 comptime unused_fmt_string: []const u8,
1123 options: std.fmt.FormatOptions,
1124 writer: anytype,
1125) !void {
1126 _ = atom;
1127 _ = unused_fmt_string;
1128 _ = options;
1129 _ = writer;
1130 @compileError("do not format Atom directly");
1131}
1132
1133pub fn fmt(atom: Atom, macho_file: *MachO) std.fmt.Formatter(format2) {
1134 return .{ .data = .{1118 return .{ .data = .{
1135 .atom = atom,1119 .atom = atom,
1136 .macho_file = macho_file,1120 .macho_file = macho_file,
1137 } };1121 } };
1138}1122}
11391123
1140const FormatContext = struct {1124const Format = struct {
1141 atom: Atom,1125 atom: Atom,
1142 macho_file: *MachO,1126 macho_file: *MachO,
1143};
11441127
1145fn format2(1128 fn print(f: Format, w: *Writer) Writer.Error!void {
1146 ctx: FormatContext,1129 const atom = f.atom;
1147 comptime unused_fmt_string: []const u8,1130 const macho_file = f.macho_file;
1148 options: std.fmt.FormatOptions,1131 const file = atom.getFile(macho_file);
1149 writer: anytype,1132 try w.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{
1150) !void {1133 atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
1151 _ = options;1134 atom.out_n_sect, atom.alignment, atom.size,
1152 _ = unused_fmt_string;1135 atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,
1153 const atom = ctx.atom;1136 });
1154 const macho_file = ctx.macho_file;1137 if (!atom.isAlive()) try w.writeAll(" : [*]");
1155 const file = atom.getFile(macho_file);1138 if (atom.getUnwindRecords(macho_file).len > 0) {
1156 try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{1139 try w.writeAll(" : unwind{ ");
1157 atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),1140 const extra = atom.getExtra(macho_file);
1158 atom.out_n_sect, atom.alignment, atom.size,1141 for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| {
1159 atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,1142 const rec = file.object.getUnwindRecord(index);
1160 });1143 try w.print("{d}", .{index});
1161 if (!atom.isAlive()) try writer.writeAll(" : [*]");1144 if (!rec.alive) try w.writeAll("([*])");
1162 if (atom.getUnwindRecords(macho_file).len > 0) {1145 if (i < extra.unwind_index + extra.unwind_count - 1) try w.writeAll(", ");
1163 try writer.writeAll(" : unwind{ ");1146 }
1164 const extra = atom.getExtra(macho_file);1147 try w.writeAll(" }");
1165 for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| {
1166 const rec = file.object.getUnwindRecord(index);
1167 try writer.print("{d}", .{index});
1168 if (!rec.alive) try writer.writeAll("([*])");
1169 if (i < extra.unwind_index + extra.unwind_count - 1) try writer.writeAll(", ");
1170 }1148 }
1171 try writer.writeAll(" }");
1172 }1149 }
1173}1150};
11741151
1175pub const Index = u32;1152pub const Index = u32;
11761153
...@@ -1205,19 +1182,20 @@ pub const Extra = struct {...@@ -1205,19 +1182,20 @@ pub const Extra = struct {
12051182
1206pub const Alignment = @import("../../InternPool.zig").Alignment;1183pub const Alignment = @import("../../InternPool.zig").Alignment;
12071184
1208const aarch64 = @import("../aarch64.zig");1185const std = @import("std");
1209const assert = std.debug.assert;1186const assert = std.debug.assert;
1210const macho = std.macho;1187const macho = std.macho;
1211const math = std.math;1188const math = std.math;
1212const mem = std.mem;1189const mem = std.mem;
1213const log = std.log.scoped(.link);1190const log = std.log.scoped(.link);
1214const relocs_log = std.log.scoped(.link_relocs);1191const relocs_log = std.log.scoped(.link_relocs);
1215const std = @import("std");1192const Writer = std.io.Writer;
1216const trace = @import("../../tracy.zig").trace;
1217
1218const Allocator = mem.Allocator;1193const Allocator = mem.Allocator;
1219const Atom = @This();
1220const AtomicBool = std.atomic.Value(bool);1194const AtomicBool = std.atomic.Value(bool);
1195
1196const aarch64 = @import("../aarch64.zig");
1197const trace = @import("../../tracy.zig").trace;
1198const Atom = @This();
1221const File = @import("file.zig").File;1199const File = @import("file.zig").File;
1222const MachO = @import("../MachO.zig");1200const MachO = @import("../MachO.zig");
1223const Object = @import("Object.zig");1201const Object = @import("Object.zig");
src/link/MachO/DebugSymbols.zig+1
...@@ -460,6 +460,7 @@ const math = std.math;...@@ -460,6 +460,7 @@ const math = std.math;
460const mem = std.mem;460const mem = std.mem;
461const padToIdeal = MachO.padToIdeal;461const padToIdeal = MachO.padToIdeal;
462const trace = @import("../../tracy.zig").trace;462const trace = @import("../../tracy.zig").trace;
463const Writer = std.io.Writer;
463464
464const Allocator = mem.Allocator;465const Allocator = mem.Allocator;
465const MachO = @import("../MachO.zig");466const MachO = @import("../MachO.zig");
src/link/MachO/Dylib.zig+24-43
...@@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
61 const file = macho_file.getFileHandle(self.file_handle);61 const file = macho_file.getFileHandle(self.file_handle);
62 const offset = self.offset;62 const offset = self.offset;
6363
64 log.debug("parsing dylib from binary: {}", .{@as(Path, self.path)});64 log.debug("parsing dylib from binary: {f}", .{@as(Path, self.path)});
6565
66 var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined;66 var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined;
67 {67 {
...@@ -140,7 +140,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -140,7 +140,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
140140
141 if (self.platform) |platform| {141 if (self.platform) |platform| {
142 if (!macho_file.platform.eqlTarget(platform)) {142 if (!macho_file.platform.eqlTarget(platform)) {
143 try macho_file.reportParseError2(self.index, "invalid platform: {}", .{143 try macho_file.reportParseError2(self.index, "invalid platform: {f}", .{
144 platform.fmtTarget(macho_file.getTarget().cpu.arch),144 platform.fmtTarget(macho_file.getTarget().cpu.arch),
145 });145 });
146 return error.InvalidTarget;146 return error.InvalidTarget;
...@@ -148,7 +148,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -148,7 +148,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
148 // TODO: this can cause the CI to fail so I'm commenting this check out so that148 // TODO: this can cause the CI to fail so I'm commenting this check out so that
149 // I can work out the rest of the changes first149 // I can work out the rest of the changes first
150 // if (macho_file.platform.version.order(platform.version) == .lt) {150 // if (macho_file.platform.version.order(platform.version) == .lt) {
151 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {}: {} < {}", .{151 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {f}: {f} < {f}", .{
152 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),152 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),
153 // macho_file.platform.version,153 // macho_file.platform.version,
154 // platform.version,154 // platform.version,
...@@ -267,7 +267,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void {...@@ -267,7 +267,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void {
267267
268 const gpa = macho_file.base.comp.gpa;268 const gpa = macho_file.base.comp.gpa;
269269
270 log.debug("parsing dylib from stub: {}", .{self.path});270 log.debug("parsing dylib from stub: {f}", .{self.path});
271271
272 const file = macho_file.getFileHandle(self.file_handle);272 const file = macho_file.getFileHandle(self.file_handle);
273 var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| {273 var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| {
...@@ -691,52 +691,32 @@ pub fn setSymbolExtra(self: *Dylib, index: u32, extra: Symbol.Extra) void {...@@ -691,52 +691,32 @@ pub fn setSymbolExtra(self: *Dylib, index: u32, extra: Symbol.Extra) void {
691 }691 }
692}692}
693693
694pub fn format(694pub fn fmtSymtab(self: *Dylib, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) {
695 self: *Dylib,
696 comptime unused_fmt_string: []const u8,
697 options: std.fmt.FormatOptions,
698 writer: anytype,
699) !void {
700 _ = self;
701 _ = unused_fmt_string;
702 _ = options;
703 _ = writer;
704 @compileError("do not format dylib directly");
705}
706
707pub fn fmtSymtab(self: *Dylib, macho_file: *MachO) std.fmt.Formatter(formatSymtab) {
708 return .{ .data = .{695 return .{ .data = .{
709 .dylib = self,696 .dylib = self,
710 .macho_file = macho_file,697 .macho_file = macho_file,
711 } };698 } };
712}699}
713700
714const FormatContext = struct {701const Format = struct {
715 dylib: *Dylib,702 dylib: *Dylib,
716 macho_file: *MachO,703 macho_file: *MachO,
717};
718704
719fn formatSymtab(705 fn symtab(f: Format, w: *Writer) Writer.Error!void {
720 ctx: FormatContext,706 const dylib = f.dylib;
721 comptime unused_fmt_string: []const u8,707 const macho_file = f.macho_file;
722 options: std.fmt.FormatOptions,708 try w.writeAll(" globals\n");
723 writer: anytype,709 for (dylib.symbols.items, 0..) |sym, i| {
724) !void {710 const ref = dylib.getSymbolRef(@intCast(i), macho_file);
725 _ = unused_fmt_string;711 if (ref.getFile(macho_file) == null) {
726 _ = options;712 // TODO any better way of handling this?
727 const dylib = ctx.dylib;713 try w.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
728 const macho_file = ctx.macho_file;714 } else {
729 try writer.writeAll(" globals\n");715 try w.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
730 for (dylib.symbols.items, 0..) |sym, i| {716 }
731 const ref = dylib.getSymbolRef(@intCast(i), macho_file);
732 if (ref.getFile(macho_file) == null) {
733 // TODO any better way of handling this?
734 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
735 } else {
736 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
737 }717 }
738 }718 }
739}719};
740720
741pub const TargetMatcher = struct {721pub const TargetMatcher = struct {
742 allocator: Allocator,722 allocator: Allocator,
...@@ -948,19 +928,17 @@ const Export = struct {...@@ -948,19 +928,17 @@ const Export = struct {
948 };928 };
949};929};
950930
931const std = @import("std");
951const assert = std.debug.assert;932const assert = std.debug.assert;
952const fat = @import("fat.zig");
953const fs = std.fs;933const fs = std.fs;
954const fmt = std.fmt;934const fmt = std.fmt;
955const log = std.log.scoped(.link);935const log = std.log.scoped(.link);
956const macho = std.macho;936const macho = std.macho;
957const math = std.math;937const math = std.math;
958const mem = std.mem;938const mem = std.mem;
959const tapi = @import("../tapi.zig");
960const trace = @import("../../tracy.zig").trace;
961const std = @import("std");
962const Allocator = mem.Allocator;939const Allocator = mem.Allocator;
963const Path = std.Build.Cache.Path;940const Path = std.Build.Cache.Path;
941const Writer = std.io.Writer;
964942
965const Dylib = @This();943const Dylib = @This();
966const File = @import("file.zig").File;944const File = @import("file.zig").File;
...@@ -969,3 +947,6 @@ const LoadCommandIterator = macho.LoadCommandIterator;...@@ -969,3 +947,6 @@ const LoadCommandIterator = macho.LoadCommandIterator;
969const MachO = @import("../MachO.zig");947const MachO = @import("../MachO.zig");
970const Symbol = @import("Symbol.zig");948const Symbol = @import("Symbol.zig");
971const Tbd = tapi.Tbd;949const Tbd = tapi.Tbd;
950const fat = @import("fat.zig");
951const tapi = @import("../tapi.zig");
952const trace = @import("../../tracy.zig").trace;
src/link/MachO/InternalObject.zig+27-40
...@@ -836,62 +836,48 @@ fn needsObjcMsgsendSymbol(self: InternalObject) bool {...@@ -836,62 +836,48 @@ fn needsObjcMsgsendSymbol(self: InternalObject) bool {
836 return false;836 return false;
837}837}
838838
839const FormatContext = struct {839const Format = struct {
840 self: *InternalObject,840 self: *InternalObject,
841 macho_file: *MachO,841 macho_file: *MachO,
842
843 fn atoms(f: Format, w: *Writer) Writer.Error!void {
844 try w.writeAll(" atoms\n");
845 for (f.self.getAtoms()) |atom_index| {
846 const atom = f.self.getAtom(atom_index) orelse continue;
847 try w.print(" {f}\n", .{atom.fmt(f.macho_file)});
848 }
849 }
850
851 fn symtab(f: Format, w: *Writer) Writer.Error!void {
852 const macho_file = f.macho_file;
853 const self = f.self;
854 try w.writeAll(" symbols\n");
855 for (self.symbols.items, 0..) |sym, i| {
856 const ref = self.getSymbolRef(@intCast(i), macho_file);
857 if (ref.getFile(macho_file) == null) {
858 // TODO any better way of handling this?
859 try w.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
860 } else {
861 try w.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
862 }
863 }
864 }
842};865};
843866
844pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(formatAtoms) {867pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.atoms) {
845 return .{ .data = .{868 return .{ .data = .{
846 .self = self,869 .self = self,
847 .macho_file = macho_file,870 .macho_file = macho_file,
848 } };871 } };
849}872}
850873
851fn formatAtoms(874pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) {
852 ctx: FormatContext,
853 comptime unused_fmt_string: []const u8,
854 options: std.fmt.FormatOptions,
855 writer: anytype,
856) !void {
857 _ = unused_fmt_string;
858 _ = options;
859 try writer.writeAll(" atoms\n");
860 for (ctx.self.getAtoms()) |atom_index| {
861 const atom = ctx.self.getAtom(atom_index) orelse continue;
862 try writer.print(" {}\n", .{atom.fmt(ctx.macho_file)});
863 }
864}
865
866pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(formatSymtab) {
867 return .{ .data = .{875 return .{ .data = .{
868 .self = self,876 .self = self,
869 .macho_file = macho_file,877 .macho_file = macho_file,
870 } };878 } };
871}879}
872880
873fn formatSymtab(
874 ctx: FormatContext,
875 comptime unused_fmt_string: []const u8,
876 options: std.fmt.FormatOptions,
877 writer: anytype,
878) !void {
879 _ = unused_fmt_string;
880 _ = options;
881 const macho_file = ctx.macho_file;
882 const self = ctx.self;
883 try writer.writeAll(" symbols\n");
884 for (self.symbols.items, 0..) |sym, i| {
885 const ref = self.getSymbolRef(@intCast(i), macho_file);
886 if (ref.getFile(macho_file) == null) {
887 // TODO any better way of handling this?
888 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
889 } else {
890 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
891 }
892 }
893}
894
895const Section = struct {881const Section = struct {
896 header: macho.section_64,882 header: macho.section_64,
897 relocs: std.ArrayListUnmanaged(Relocation) = .empty,883 relocs: std.ArrayListUnmanaged(Relocation) = .empty,
...@@ -908,6 +894,7 @@ const macho = std.macho;...@@ -908,6 +894,7 @@ const macho = std.macho;
908const mem = std.mem;894const mem = std.mem;
909const std = @import("std");895const std = @import("std");
910const trace = @import("../../tracy.zig").trace;896const trace = @import("../../tracy.zig").trace;
897const Writer = std.io.Writer;
911898
912const Allocator = std.mem.Allocator;899const Allocator = std.mem.Allocator;
913const Atom = @import("Atom.zig");900const Atom = @import("Atom.zig");
src/link/MachO/Object.zig+104-174
...@@ -72,7 +72,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -72,7 +72,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
72 const tracy = trace(@src());72 const tracy = trace(@src());
73 defer tracy.end();73 defer tracy.end();
7474
75 log.debug("parsing {}", .{self.fmtPath()});75 log.debug("parsing {f}", .{self.fmtPath()});
7676
77 const gpa = macho_file.base.comp.gpa;77 const gpa = macho_file.base.comp.gpa;
78 const handle = macho_file.getFileHandle(self.file_handle);78 const handle = macho_file.getFileHandle(self.file_handle);
...@@ -239,7 +239,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -239,7 +239,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
239239
240 if (self.platform) |platform| {240 if (self.platform) |platform| {
241 if (!macho_file.platform.eqlTarget(platform)) {241 if (!macho_file.platform.eqlTarget(platform)) {
242 try macho_file.reportParseError2(self.index, "invalid platform: {}", .{242 try macho_file.reportParseError2(self.index, "invalid platform: {f}", .{
243 platform.fmtTarget(cpu_arch),243 platform.fmtTarget(cpu_arch),
244 });244 });
245 return error.InvalidTarget;245 return error.InvalidTarget;
...@@ -247,7 +247,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -247,7 +247,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
247 // TODO: this causes the CI to fail so I'm commenting this check out so that247 // TODO: this causes the CI to fail so I'm commenting this check out so that
248 // I can work out the rest of the changes first248 // I can work out the rest of the changes first
249 // if (macho_file.platform.version.order(platform.version) == .lt) {249 // if (macho_file.platform.version.order(platform.version) == .lt) {
250 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {}: {} < {}", .{250 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {f}: {f} < {f}", .{
251 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),251 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),
252 // macho_file.platform.version,252 // macho_file.platform.version,
253 // platform.version,253 // platform.version,
...@@ -308,7 +308,9 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {...@@ -308,7 +308,9 @@ 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", .{
312 sect.segName(), sect.sectName(),
313 }, 0);
312 defer allocator.free(name);314 defer allocator.free(name);
313 const size = if (nlist_start == nlist_end) sect.size else nlists[nlist_start].nlist.n_value - sect.addr;315 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, .{316 const atom_index = try self.addAtom(allocator, .{
...@@ -364,7 +366,9 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {...@@ -364,7 +366,9 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void {
364 // which cannot be contained in any non-zero atom (since then this atom366 // which cannot be contained in any non-zero atom (since then this atom
365 // would exceed section boundaries). In order to facilitate this behaviour,367 // would exceed section boundaries). In order to facilitate this behaviour,
366 // we create a dummy zero-sized atom at section end (addr + size).368 // 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() });369 const name = try std.fmt.allocPrintSentinel(allocator, "{s}${s}$end", .{
370 sect.segName(), sect.sectName(),
371 }, 0);
368 defer allocator.free(name);372 defer allocator.free(name);
369 const atom_index = try self.addAtom(allocator, .{373 const atom_index = try self.addAtom(allocator, .{
370 .name = try self.addString(allocator, name),374 .name = try self.addString(allocator, name),
...@@ -394,7 +398,7 @@ fn initSections(self: *Object, allocator: Allocator, nlists: anytype) !void {...@@ -394,7 +398,7 @@ fn initSections(self: *Object, allocator: Allocator, nlists: anytype) !void {
394 if (isFixedSizeLiteral(sect)) continue;398 if (isFixedSizeLiteral(sect)) continue;
395 if (isPtrLiteral(sect)) continue;399 if (isPtrLiteral(sect)) continue;
396400
397 const name = try std.fmt.allocPrintZ(allocator, "{s}${s}", .{ sect.segName(), sect.sectName() });401 const name = try std.fmt.allocPrintSentinel(allocator, "{s}${s}", .{ sect.segName(), sect.sectName() }, 0);
398 defer allocator.free(name);402 defer allocator.free(name);
399403
400 const atom_index = try self.addAtom(allocator, .{404 const atom_index = try self.addAtom(allocator, .{
...@@ -462,7 +466,7 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m...@@ -462,7 +466,7 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m
462 }466 }
463 end += 1;467 end += 1;
464468
465 const name = try std.fmt.allocPrintZ(allocator, "l._str{d}", .{count});469 const name = try std.fmt.allocPrintSentinel(allocator, "l._str{d}", .{count}, 0);
466 defer allocator.free(name);470 defer allocator.free(name);
467 const name_str = try self.addString(allocator, name);471 const name_str = try self.addString(allocator, name);
468472
...@@ -529,7 +533,7 @@ fn initFixedSizeLiterals(self: *Object, allocator: Allocator, macho_file: *MachO...@@ -529,7 +533,7 @@ fn initFixedSizeLiterals(self: *Object, allocator: Allocator, macho_file: *MachO
529 pos += rec_size;533 pos += rec_size;
530 count += 1;534 count += 1;
531 }) {535 }) {
532 const name = try std.fmt.allocPrintZ(allocator, "l._literal{d}", .{count});536 const name = try std.fmt.allocPrintSentinel(allocator, "l._literal{d}", .{count}, 0);
533 defer allocator.free(name);537 defer allocator.free(name);
534 const name_str = try self.addString(allocator, name);538 const name_str = try self.addString(allocator, name);
535539
...@@ -587,7 +591,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO)...@@ -587,7 +591,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO)
587 for (0..num_ptrs) |i| {591 for (0..num_ptrs) |i| {
588 const pos: u32 = @as(u32, @intCast(i)) * rec_size;592 const pos: u32 = @as(u32, @intCast(i)) * rec_size;
589593
590 const name = try std.fmt.allocPrintZ(allocator, "l._ptr{d}", .{i});594 const name = try std.fmt.allocPrintSentinel(allocator, "l._ptr{d}", .{i}, 0);
591 defer allocator.free(name);595 defer allocator.free(name);
592 const name_str = try self.addString(allocator, name);596 const name_str = try self.addString(allocator, name);
593597
...@@ -1558,7 +1562,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {...@@ -1558,7 +1562,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {
1558 const nlist = &self.symtab.items(.nlist)[nlist_idx];1562 const nlist = &self.symtab.items(.nlist)[nlist_idx];
1559 const nlist_atom = &self.symtab.items(.atom)[nlist_idx];1563 const nlist_atom = &self.symtab.items(.atom)[nlist_idx];
15601564
1561 const name = try std.fmt.allocPrintZ(gpa, "__DATA$__common${s}", .{sym.getName(macho_file)});1565 const name = try std.fmt.allocPrintSentinel(gpa, "__DATA$__common${s}", .{sym.getName(macho_file)}, 0);
1562 defer gpa.free(name);1566 defer gpa.free(name);
15631567
1564 const alignment = (nlist.n_desc >> 8) & 0x0f;1568 const alignment = (nlist.n_desc >> 8) & 0x0f;
...@@ -2512,172 +2516,114 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_...@@ -2512,172 +2516,114 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_
2512 return data;2516 return data;
2513}2517}
25142518
2515pub fn format(2519const Format = struct {
2516 self: *Object,
2517 comptime unused_fmt_string: []const u8,
2518 options: std.fmt.FormatOptions,
2519 writer: anytype,
2520) !void {
2521 _ = self;
2522 _ = unused_fmt_string;
2523 _ = options;
2524 _ = writer;
2525 @compileError("do not format objects directly");
2526}
2527
2528const FormatContext = struct {
2529 object: *Object,2520 object: *Object,
2530 macho_file: *MachO,2521 macho_file: *MachO,
2522
2523 fn atoms(f: Format, w: *Writer) Writer.Error!void {
2524 const object = f.object;
2525 const macho_file = f.macho_file;
2526 try w.writeAll(" atoms\n");
2527 for (object.getAtoms()) |atom_index| {
2528 const atom = object.getAtom(atom_index) orelse continue;
2529 try w.print(" {f}\n", .{atom.fmt(macho_file)});
2530 }
2531 }
2532 fn cies(f: Format, w: *Writer) Writer.Error!void {
2533 const object = f.object;
2534 try w.writeAll(" cies\n");
2535 for (object.cies.items, 0..) |cie, i| {
2536 try w.print(" cie({d}) : {f}\n", .{ i, cie.fmt(f.macho_file) });
2537 }
2538 }
2539 fn fdes(f: Format, w: *Writer) Writer.Error!void {
2540 const object = f.object;
2541 try w.writeAll(" fdes\n");
2542 for (object.fdes.items, 0..) |fde, i| {
2543 try w.print(" fde({d}) : {f}\n", .{ i, fde.fmt(f.macho_file) });
2544 }
2545 }
2546 fn unwindRecords(f: Format, w: *Writer) Writer.Error!void {
2547 const object = f.object;
2548 const macho_file = f.macho_file;
2549 try w.writeAll(" unwind records\n");
2550 for (object.unwind_records_indexes.items) |rec| {
2551 try w.print(" rec({d}) : {f}\n", .{ rec, object.getUnwindRecord(rec).fmt(macho_file) });
2552 }
2553 }
2554
2555 fn symtab(f: Format, w: *Writer) Writer.Error!void {
2556 const object = f.object;
2557 const macho_file = f.macho_file;
2558 try w.writeAll(" symbols\n");
2559 for (object.symbols.items, 0..) |sym, i| {
2560 const ref = object.getSymbolRef(@intCast(i), macho_file);
2561 if (ref.getFile(macho_file) == null) {
2562 // TODO any better way of handling this?
2563 try w.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
2564 } else {
2565 try w.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
2566 }
2567 }
2568 for (object.stab_files.items) |sf| {
2569 try w.print(" stabs({s},{s},{s})\n", .{
2570 sf.getCompDir(object.*),
2571 sf.getTuName(object.*),
2572 sf.getOsoPath(object.*),
2573 });
2574 for (sf.stabs.items) |stab| {
2575 try w.print(" {f}", .{stab.fmt(object.*)});
2576 }
2577 }
2578 }
2531};2579};
25322580
2533pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatAtoms) {2581pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.atoms) {
2534 return .{ .data = .{2582 return .{ .data = .{
2535 .object = self,2583 .object = self,
2536 .macho_file = macho_file,2584 .macho_file = macho_file,
2537 } };2585 } };
2538}2586}
25392587
2540fn formatAtoms(2588pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.cies) {
2541 ctx: FormatContext,
2542 comptime unused_fmt_string: []const u8,
2543 options: std.fmt.FormatOptions,
2544 writer: anytype,
2545) !void {
2546 _ = unused_fmt_string;
2547 _ = options;
2548 const object = ctx.object;
2549 const macho_file = ctx.macho_file;
2550 try writer.writeAll(" atoms\n");
2551 for (object.getAtoms()) |atom_index| {
2552 const atom = object.getAtom(atom_index) orelse continue;
2553 try writer.print(" {}\n", .{atom.fmt(macho_file)});
2554 }
2555}
2556
2557pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatCies) {
2558 return .{ .data = .{2589 return .{ .data = .{
2559 .object = self,2590 .object = self,
2560 .macho_file = macho_file,2591 .macho_file = macho_file,
2561 } };2592 } };
2562}2593}
25632594
2564fn formatCies(2595pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.fdes) {
2565 ctx: FormatContext,
2566 comptime unused_fmt_string: []const u8,
2567 options: std.fmt.FormatOptions,
2568 writer: anytype,
2569) !void {
2570 _ = unused_fmt_string;
2571 _ = options;
2572 const object = ctx.object;
2573 try writer.writeAll(" cies\n");
2574 for (object.cies.items, 0..) |cie, i| {
2575 try writer.print(" cie({d}) : {}\n", .{ i, cie.fmt(ctx.macho_file) });
2576 }
2577}
2578
2579pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatFdes) {
2580 return .{ .data = .{2596 return .{ .data = .{
2581 .object = self,2597 .object = self,
2582 .macho_file = macho_file,2598 .macho_file = macho_file,
2583 } };2599 } };
2584}2600}
25852601
2586fn formatFdes(2602pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.unwindRecords) {
2587 ctx: FormatContext,
2588 comptime unused_fmt_string: []const u8,
2589 options: std.fmt.FormatOptions,
2590 writer: anytype,
2591) !void {
2592 _ = unused_fmt_string;
2593 _ = options;
2594 const object = ctx.object;
2595 try writer.writeAll(" fdes\n");
2596 for (object.fdes.items, 0..) |fde, i| {
2597 try writer.print(" fde({d}) : {}\n", .{ i, fde.fmt(ctx.macho_file) });
2598 }
2599}
2600
2601pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatUnwindRecords) {
2602 return .{ .data = .{2603 return .{ .data = .{
2603 .object = self,2604 .object = self,
2604 .macho_file = macho_file,2605 .macho_file = macho_file,
2605 } };2606 } };
2606}2607}
26072608
2608fn formatUnwindRecords(2609pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) {
2609 ctx: FormatContext,
2610 comptime unused_fmt_string: []const u8,
2611 options: std.fmt.FormatOptions,
2612 writer: anytype,
2613) !void {
2614 _ = unused_fmt_string;
2615 _ = options;
2616 const object = ctx.object;
2617 const macho_file = ctx.macho_file;
2618 try writer.writeAll(" unwind records\n");
2619 for (object.unwind_records_indexes.items) |rec| {
2620 try writer.print(" rec({d}) : {}\n", .{ rec, object.getUnwindRecord(rec).fmt(macho_file) });
2621 }
2622}
2623
2624pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatSymtab) {
2625 return .{ .data = .{2610 return .{ .data = .{
2626 .object = self,2611 .object = self,
2627 .macho_file = macho_file,2612 .macho_file = macho_file,
2628 } };2613 } };
2629}2614}
26302615
2631fn formatSymtab(2616pub fn fmtPath(self: Object) std.fmt.Formatter(Object, formatPath) {
2632 ctx: FormatContext,
2633 comptime unused_fmt_string: []const u8,
2634 options: std.fmt.FormatOptions,
2635 writer: anytype,
2636) !void {
2637 _ = unused_fmt_string;
2638 _ = options;
2639 const object = ctx.object;
2640 const macho_file = ctx.macho_file;
2641 try writer.writeAll(" symbols\n");
2642 for (object.symbols.items, 0..) |sym, i| {
2643 const ref = object.getSymbolRef(@intCast(i), macho_file);
2644 if (ref.getFile(macho_file) == null) {
2645 // TODO any better way of handling this?
2646 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
2647 } else {
2648 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
2649 }
2650 }
2651 for (object.stab_files.items) |sf| {
2652 try writer.print(" stabs({s},{s},{s})\n", .{
2653 sf.getCompDir(object.*),
2654 sf.getTuName(object.*),
2655 sf.getOsoPath(object.*),
2656 });
2657 for (sf.stabs.items) |stab| {
2658 try writer.print(" {}", .{stab.fmt(object.*)});
2659 }
2660 }
2661}
2662
2663pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {
2664 return .{ .data = self };2617 return .{ .data = self };
2665}2618}
26662619
2667fn formatPath(2620fn formatPath(object: Object, w: *Writer) Writer.Error!void {
2668 object: Object,
2669 comptime unused_fmt_string: []const u8,
2670 options: std.fmt.FormatOptions,
2671 writer: anytype,
2672) !void {
2673 _ = unused_fmt_string;
2674 _ = options;
2675 if (object.in_archive) |ar| {2621 if (object.in_archive) |ar| {
2676 try writer.print("{}({s})", .{2622 try w.print("{f}({s})", .{
2677 @as(Path, ar.path), object.path.basename(),2623 ar.path, object.path.basename(),
2678 });2624 });
2679 } else {2625 } else {
2680 try writer.print("{}", .{@as(Path, object.path)});2626 try w.print("{f}", .{object.path});
2681 }2627 }
2682}2628}
26832629
...@@ -2731,42 +2677,25 @@ const StabFile = struct {...@@ -2731,42 +2677,25 @@ const StabFile = struct {
2731 return object.symbols.items[index];2677 return object.symbols.items[index];
2732 }2678 }
27332679
2734 pub fn format(2680 const Format = struct {
2735 stab: Stab,2681 stab: Stab,
2736 comptime unused_fmt_string: []const u8,2682 object: Object,
2737 options: std.fmt.FormatOptions,2683
2738 writer: anytype,2684 fn default(f: Stab.Format, w: *Writer) Writer.Error!void {
2739 ) !void {2685 const stab = f.stab;
2740 _ = stab;2686 const sym = stab.getSymbol(f.object).?;
2741 _ = unused_fmt_string;2687 if (stab.is_func) {
2742 _ = options;2688 try w.print("func({d})", .{stab.index.?});
2743 _ = writer;2689 } else if (sym.visibility == .global) {
2744 @compileError("do not format stabs directly");2690 try w.print("gsym({d})", .{stab.index.?});
2745 }2691 } else {
27462692 try w.print("stsym({d})", .{stab.index.?});
2747 const StabFormatContext = struct { Stab, Object };2693 }
2748
2749 pub fn fmt(stab: Stab, object: Object) std.fmt.Formatter(format2) {
2750 return .{ .data = .{ stab, object } };
2751 }
2752
2753 fn format2(
2754 ctx: StabFormatContext,
2755 comptime unused_fmt_string: []const u8,
2756 options: std.fmt.FormatOptions,
2757 writer: anytype,
2758 ) !void {
2759 _ = unused_fmt_string;
2760 _ = options;
2761 const stab, const object = ctx;
2762 const sym = stab.getSymbol(object).?;
2763 if (stab.is_func) {
2764 try writer.print("func({d})", .{stab.index.?});
2765 } else if (sym.visibility == .global) {
2766 try writer.print("gsym({d})", .{stab.index.?});
2767 } else {
2768 try writer.print("stsym({d})", .{stab.index.?});
2769 }2694 }
2695 };
2696
2697 pub fn fmt(stab: Stab, object: Object) std.fmt.Formatter(Stab.Format, Stab.Format.default) {
2698 return .{ .data = .{ .stab = stab, .object = object } };
2770 }2699 }
2771 };2700 };
2772};2701};
...@@ -3157,17 +3086,18 @@ const aarch64 = struct {...@@ -3157,17 +3086,18 @@ const aarch64 = struct {
3157 }3086 }
3158};3087};
31593088
3089const std = @import("std");
3160const assert = std.debug.assert;3090const assert = std.debug.assert;
3161const eh_frame = @import("eh_frame.zig");
3162const log = std.log.scoped(.link);3091const log = std.log.scoped(.link);
3163const macho = std.macho;3092const macho = std.macho;
3164const math = std.math;3093const math = std.math;
3165const mem = std.mem;3094const mem = std.mem;
3166const trace = @import("../../tracy.zig").trace;
3167const std = @import("std");
3168const Path = std.Build.Cache.Path;3095const Path = std.Build.Cache.Path;
3096const Allocator = std.mem.Allocator;
3097const Writer = std.io.Writer;
31693098
3170const Allocator = mem.Allocator;3099const eh_frame = @import("eh_frame.zig");
3100const trace = @import("../../tracy.zig").trace;
3171const Archive = @import("Archive.zig");3101const Archive = @import("Archive.zig");
3172const Atom = @import("Atom.zig");3102const Atom = @import("Atom.zig");
3173const Cie = eh_frame.Cie;3103const Cie = eh_frame.Cie;
src/link/MachO/Relocation.zig+45-50
...@@ -70,57 +70,51 @@ pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool {...@@ -70,57 +70,51 @@ pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool {
70 return lhs.offset < rhs.offset;70 return lhs.offset < rhs.offset;
71}71}
7272
73const FormatCtx = struct { Relocation, std.Target.Cpu.Arch };73pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(Format, Format.pretty) {
7474 return .{ .data = .{ .relocation = rel, .arch = cpu_arch } };
75pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(formatPretty) {
76 return .{ .data = .{ rel, cpu_arch } };
77}75}
7876
79fn formatPretty(77const Format = struct {
80 ctx: FormatCtx,78 relocation: Relocation,
81 comptime unused_fmt_string: []const u8,79 arch: std.Target.Cpu.Arch,
82 options: std.fmt.FormatOptions,80
83 writer: anytype,81 fn pretty(f: Format, w: *Writer) Writer.Error!void {
84) !void {82 try w.writeAll(switch (f.relocation.type) {
85 _ = options;83 .signed => "X86_64_RELOC_SIGNED",
86 _ = unused_fmt_string;84 .signed1 => "X86_64_RELOC_SIGNED_1",
87 const rel, const cpu_arch = ctx;85 .signed2 => "X86_64_RELOC_SIGNED_2",
88 const str = switch (rel.type) {86 .signed4 => "X86_64_RELOC_SIGNED_4",
89 .signed => "X86_64_RELOC_SIGNED",87 .got_load => "X86_64_RELOC_GOT_LOAD",
90 .signed1 => "X86_64_RELOC_SIGNED_1",88 .tlv => "X86_64_RELOC_TLV",
91 .signed2 => "X86_64_RELOC_SIGNED_2",89 .page => "ARM64_RELOC_PAGE21",
92 .signed4 => "X86_64_RELOC_SIGNED_4",90 .pageoff => "ARM64_RELOC_PAGEOFF12",
93 .got_load => "X86_64_RELOC_GOT_LOAD",91 .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21",
94 .tlv => "X86_64_RELOC_TLV",92 .got_load_pageoff => "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
95 .page => "ARM64_RELOC_PAGE21",93 .tlvp_page => "ARM64_RELOC_TLVP_LOAD_PAGE21",
96 .pageoff => "ARM64_RELOC_PAGEOFF12",94 .tlvp_pageoff => "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
97 .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21",95 .branch => switch (f.arch) {
98 .got_load_pageoff => "ARM64_RELOC_GOT_LOAD_PAGEOFF12",96 .x86_64 => "X86_64_RELOC_BRANCH",
99 .tlvp_page => "ARM64_RELOC_TLVP_LOAD_PAGE21",97 .aarch64 => "ARM64_RELOC_BRANCH26",
100 .tlvp_pageoff => "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",98 else => unreachable,
101 .branch => switch (cpu_arch) {99 },
102 .x86_64 => "X86_64_RELOC_BRANCH",100 .got => switch (f.arch) {
103 .aarch64 => "ARM64_RELOC_BRANCH26",101 .x86_64 => "X86_64_RELOC_GOT",
104 else => unreachable,102 .aarch64 => "ARM64_RELOC_POINTER_TO_GOT",
105 },103 else => unreachable,
106 .got => switch (cpu_arch) {104 },
107 .x86_64 => "X86_64_RELOC_GOT",105 .subtractor => switch (f.arch) {
108 .aarch64 => "ARM64_RELOC_POINTER_TO_GOT",106 .x86_64 => "X86_64_RELOC_SUBTRACTOR",
109 else => unreachable,107 .aarch64 => "ARM64_RELOC_SUBTRACTOR",
110 },108 else => unreachable,
111 .subtractor => switch (cpu_arch) {109 },
112 .x86_64 => "X86_64_RELOC_SUBTRACTOR",110 .unsigned => switch (f.arch) {
113 .aarch64 => "ARM64_RELOC_SUBTRACTOR",111 .x86_64 => "X86_64_RELOC_UNSIGNED",
114 else => unreachable,112 .aarch64 => "ARM64_RELOC_UNSIGNED",
115 },113 else => unreachable,
116 .unsigned => switch (cpu_arch) {114 },
117 .x86_64 => "X86_64_RELOC_UNSIGNED",115 });
118 .aarch64 => "ARM64_RELOC_UNSIGNED",116 }
119 else => unreachable,117};
120 },
121 };
122 try writer.writeAll(str);
123}
124118
125pub const Type = enum {119pub const Type = enum {
126 // x86_64120 // x86_64
...@@ -164,10 +158,11 @@ pub const Type = enum {...@@ -164,10 +158,11 @@ pub const Type = enum {
164158
165const Tag = enum { local, @"extern" };159const Tag = enum { local, @"extern" };
166160
161const std = @import("std");
167const assert = std.debug.assert;162const assert = std.debug.assert;
168const macho = std.macho;163const macho = std.macho;
169const math = std.math;164const math = std.math;
170const std = @import("std");165const Writer = std.io.Writer;
171166
172const Atom = @import("Atom.zig");167const Atom = @import("Atom.zig");
173const MachO = @import("../MachO.zig");168const MachO = @import("../MachO.zig");
src/link/MachO/Symbol.zig+40-59
...@@ -286,71 +286,51 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo...@@ -286,71 +286,51 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo
286 }286 }
287}287}
288288
289pub fn format(289pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) {
290 symbol: Symbol,
291 comptime unused_fmt_string: []const u8,
292 options: std.fmt.FormatOptions,
293 writer: anytype,
294) !void {
295 _ = symbol;
296 _ = unused_fmt_string;
297 _ = options;
298 _ = writer;
299 @compileError("do not format symbols directly");
300}
301
302const FormatContext = struct {
303 symbol: Symbol,
304 macho_file: *MachO,
305};
306
307pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(format2) {
308 return .{ .data = .{290 return .{ .data = .{
309 .symbol = symbol,291 .symbol = symbol,
310 .macho_file = macho_file,292 .macho_file = macho_file,
311 } };293 } };
312}294}
313295
314fn format2(296const Format = struct {
315 ctx: FormatContext,297 symbol: Symbol,
316 comptime unused_fmt_string: []const u8,298 macho_file: *MachO,
317 options: std.fmt.FormatOptions,299
318 writer: anytype,300 fn default(f: Format, w: *Writer) Writer.Error!void {
319) !void {301 const symbol = f.symbol;
320 _ = options;302 try w.print("%{d} : {s} : @{x}", .{
321 _ = unused_fmt_string;303 symbol.nlist_idx,
322 const symbol = ctx.symbol;304 symbol.getName(f.macho_file),
323 try writer.print("%{d} : {s} : @{x}", .{305 symbol.getAddress(.{}, f.macho_file),
324 symbol.nlist_idx,306 });
325 symbol.getName(ctx.macho_file),307 if (symbol.getFile(f.macho_file)) |file| {
326 symbol.getAddress(.{}, ctx.macho_file),308 if (symbol.getOutputSectionIndex(f.macho_file) != 0) {
327 });309 try w.print(" : sect({d})", .{symbol.getOutputSectionIndex(f.macho_file)});
328 if (symbol.getFile(ctx.macho_file)) |file| {310 }
329 if (symbol.getOutputSectionIndex(ctx.macho_file) != 0) {311 if (symbol.getAtom(f.macho_file)) |atom| {
330 try writer.print(" : sect({d})", .{symbol.getOutputSectionIndex(ctx.macho_file)});312 try w.print(" : atom({d})", .{atom.atom_index});
331 }313 }
332 if (symbol.getAtom(ctx.macho_file)) |atom| {314 var buf: [3]u8 = .{'_'} ** 3;
333 try writer.print(" : atom({d})", .{atom.atom_index});315 if (symbol.flags.@"export") buf[0] = 'E';
334 }316 if (symbol.flags.import) buf[1] = 'I';
335 var buf: [3]u8 = .{'_'} ** 3;317 switch (symbol.visibility) {
336 if (symbol.flags.@"export") buf[0] = 'E';318 .local => buf[2] = 'L',
337 if (symbol.flags.import) buf[1] = 'I';319 .hidden => buf[2] = 'H',
338 switch (symbol.visibility) {320 .global => buf[2] = 'G',
339 .local => buf[2] = 'L',321 }
340 .hidden => buf[2] = 'H',322 try w.print(" : {s}", .{&buf});
341 .global => buf[2] = 'G',323 if (symbol.flags.weak) try w.writeAll(" : weak");
342 }324 if (symbol.isSymbolStab(f.macho_file)) try w.writeAll(" : stab");
343 try writer.print(" : {s}", .{&buf});325 switch (file) {
344 if (symbol.flags.weak) try writer.writeAll(" : weak");326 .zig_object => |x| try w.print(" : zig_object({d})", .{x.index}),
345 if (symbol.isSymbolStab(ctx.macho_file)) try writer.writeAll(" : stab");327 .internal => |x| try w.print(" : internal({d})", .{x.index}),
346 switch (file) {328 .object => |x| try w.print(" : object({d})", .{x.index}),
347 .zig_object => |x| try writer.print(" : zig_object({d})", .{x.index}),329 .dylib => |x| try w.print(" : dylib({d})", .{x.index}),
348 .internal => |x| try writer.print(" : internal({d})", .{x.index}),330 }
349 .object => |x| try writer.print(" : object({d})", .{x.index}),331 } else try w.writeAll(" : unresolved");
350 .dylib => |x| try writer.print(" : dylib({d})", .{x.index}),332 }
351 }333};
352 } else try writer.writeAll(" : unresolved");
353}
354334
355pub const Flags = packed struct {335pub const Flags = packed struct {
356 /// Whether the symbol is imported at runtime.336 /// Whether the symbol is imported at runtime.
...@@ -437,6 +417,7 @@ pub const Index = u32;...@@ -437,6 +417,7 @@ pub const Index = u32;
437const assert = std.debug.assert;417const assert = std.debug.assert;
438const macho = std.macho;418const macho = std.macho;
439const std = @import("std");419const std = @import("std");
420const Writer = std.io.Writer;
440421
441const Atom = @import("Atom.zig");422const Atom = @import("Atom.zig");
442const File = @import("file.zig").File;423const File = @import("file.zig").File;
src/link/MachO/Thunk.zig+12-31
...@@ -61,47 +61,27 @@ pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {...@@ -61,47 +61,27 @@ pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {
61 }61 }
62}62}
6363
64pub fn format(64pub fn fmt(thunk: Thunk, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) {
65 thunk: Thunk,
66 comptime unused_fmt_string: []const u8,
67 options: std.fmt.FormatOptions,
68 writer: anytype,
69) !void {
70 _ = thunk;
71 _ = unused_fmt_string;
72 _ = options;
73 _ = writer;
74 @compileError("do not format Thunk directly");
75}
76
77pub fn fmt(thunk: Thunk, macho_file: *MachO) std.fmt.Formatter(format2) {
78 return .{ .data = .{65 return .{ .data = .{
79 .thunk = thunk,66 .thunk = thunk,
80 .macho_file = macho_file,67 .macho_file = macho_file,
81 } };68 } };
82}69}
8370
84const FormatContext = struct {71const Format = struct {
85 thunk: Thunk,72 thunk: Thunk,
86 macho_file: *MachO,73 macho_file: *MachO,
87};
8874
89fn format2(75 fn default(f: Format, w: *Writer) Writer.Error!void {
90 ctx: FormatContext,76 const thunk = f.thunk;
91 comptime unused_fmt_string: []const u8,77 const macho_file = f.macho_file;
92 options: std.fmt.FormatOptions,78 try w.print("@{x} : size({x})\n", .{ thunk.value, thunk.size() });
93 writer: anytype,79 for (thunk.symbols.keys()) |ref| {
94) !void {80 const sym = ref.getSymbol(macho_file).?;
95 _ = options;81 try w.print(" {f} : {s} : @{x}\n", .{ ref, sym.getName(macho_file), sym.value });
96 _ = unused_fmt_string;82 }
97 const thunk = ctx.thunk;
98 const macho_file = ctx.macho_file;
99 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size() });
100 for (thunk.symbols.keys()) |ref| {
101 const sym = ref.getSymbol(macho_file).?;
102 try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.getName(macho_file), sym.value });
103 }83 }
104}84};
10585
106const trampoline_size = 3 * @sizeOf(u32);86const trampoline_size = 3 * @sizeOf(u32);
10787
...@@ -115,6 +95,7 @@ const math = std.math;...@@ -115,6 +95,7 @@ const math = std.math;
115const mem = std.mem;95const mem = std.mem;
116const std = @import("std");96const std = @import("std");
117const trace = @import("../../tracy.zig").trace;97const trace = @import("../../tracy.zig").trace;
98const Writer = std.io.Writer;
11899
119const Allocator = mem.Allocator;100const Allocator = mem.Allocator;
120const Atom = @import("Atom.zig");101const Atom = @import("Atom.zig");
src/link/MachO/UnwindInfo.zig+33-79
...@@ -133,7 +133,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -133,7 +133,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
133 for (info.records.items) |ref| {133 for (info.records.items) |ref| {
134 const rec = ref.getUnwindRecord(macho_file);134 const rec = ref.getUnwindRecord(macho_file);
135 const atom = rec.getAtom(macho_file);135 const atom = rec.getAtom(macho_file);
136 log.debug("@{x}-{x} : {s} : rec({d}) : object({d}) : {}", .{136 log.debug("@{x}-{x} : {s} : rec({d}) : object({d}) : {f}", .{
137 rec.getAtomAddress(macho_file),137 rec.getAtomAddress(macho_file),
138 rec.getAtomAddress(macho_file) + rec.length,138 rec.getAtomAddress(macho_file) + rec.length,
139 atom.getName(macho_file),139 atom.getName(macho_file),
...@@ -202,7 +202,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -202,7 +202,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
202 if (i >= max_common_encodings) break;202 if (i >= max_common_encodings) break;
203 if (slice[i].count < 2) continue;203 if (slice[i].count < 2) continue;
204 info.appendCommonEncoding(slice[i].enc);204 info.appendCommonEncoding(slice[i].enc);
205 log.debug("adding common encoding: {d} => {}", .{ i, slice[i].enc });205 log.debug("adding common encoding: {d} => {f}", .{ i, slice[i].enc });
206 }206 }
207 }207 }
208208
...@@ -255,7 +255,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -255,7 +255,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
255 page.kind = .compressed;255 page.kind = .compressed;
256 }256 }
257257
258 log.debug("{}", .{page.fmt(info.*)});258 log.debug("{f}", .{page.fmt(info.*)});
259259
260 try info.pages.append(gpa, page);260 try info.pages.append(gpa, page);
261 }261 }
...@@ -455,15 +455,8 @@ pub const Encoding = extern struct {...@@ -455,15 +455,8 @@ pub const Encoding = extern struct {
455 return enc.enc == other.enc;455 return enc.enc == other.enc;
456 }456 }
457457
458 pub fn format(458 pub fn format(enc: Encoding, w: *Writer) Writer.Error!void {
459 enc: Encoding,459 try w.print("0x{x:0>8}", .{enc.enc});
460 comptime unused_fmt_string: []const u8,
461 options: std.fmt.FormatOptions,
462 writer: anytype,
463 ) !void {
464 _ = unused_fmt_string;
465 _ = options;
466 try writer.print("0x{x:0>8}", .{enc.enc});
467 }460 }
468};461};
469462
...@@ -517,48 +510,28 @@ pub const Record = struct {...@@ -517,48 +510,28 @@ pub const Record = struct {
517 return lsda.getAddress(macho_file) + rec.lsda_offset;510 return lsda.getAddress(macho_file) + rec.lsda_offset;
518 }511 }
519512
520 pub fn format(513 pub fn fmt(rec: Record, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) {
521 rec: Record,
522 comptime unused_fmt_string: []const u8,
523 options: std.fmt.FormatOptions,
524 writer: anytype,
525 ) !void {
526 _ = rec;
527 _ = unused_fmt_string;
528 _ = options;
529 _ = writer;
530 @compileError("do not format UnwindInfo.Records directly");
531 }
532
533 pub fn fmt(rec: Record, macho_file: *MachO) std.fmt.Formatter(format2) {
534 return .{ .data = .{514 return .{ .data = .{
535 .rec = rec,515 .rec = rec,
536 .macho_file = macho_file,516 .macho_file = macho_file,
537 } };517 } };
538 }518 }
539519
540 const FormatContext = struct {520 const Format = struct {
541 rec: Record,521 rec: Record,
542 macho_file: *MachO,522 macho_file: *MachO,
543 };
544523
545 fn format2(524 fn default(f: Format, w: *Writer) Writer.Error!void {
546 ctx: FormatContext,525 const rec = f.rec;
547 comptime unused_fmt_string: []const u8,526 const macho_file = f.macho_file;
548 options: std.fmt.FormatOptions,527 try w.print("{x} : len({x})", .{
549 writer: anytype,528 rec.enc.enc, rec.length,
550 ) !void {529 });
551 _ = unused_fmt_string;530 if (rec.enc.isDwarf(macho_file)) try w.print(" : fde({d})", .{rec.fde});
552 _ = options;531 try w.print(" : {s}", .{rec.getAtom(macho_file).getName(macho_file)});
553 const rec = ctx.rec;532 if (!rec.alive) try w.writeAll(" : [*]");
554 const macho_file = ctx.macho_file;533 }
555 try writer.print("{x} : len({x})", .{534 };
556 rec.enc.enc, rec.length,
557 });
558 if (rec.enc.isDwarf(macho_file)) try writer.print(" : fde({d})", .{rec.fde});
559 try writer.print(" : {s}", .{rec.getAtom(macho_file).getName(macho_file)});
560 if (!rec.alive) try writer.writeAll(" : [*]");
561 }
562535
563 pub const Index = u32;536 pub const Index = u32;
564537
...@@ -613,45 +586,25 @@ const Page = struct {...@@ -613,45 +586,25 @@ const Page = struct {
613 return null;586 return null;
614 }587 }
615588
616 fn format(589 const Format = struct {
617 page: *const Page,
618 comptime unused_format_string: []const u8,
619 options: std.fmt.FormatOptions,
620 writer: anytype,
621 ) !void {
622 _ = page;
623 _ = unused_format_string;
624 _ = options;
625 _ = writer;
626 @compileError("do not format Page directly; use page.fmt()");
627 }
628
629 const FormatPageContext = struct {
630 page: Page,590 page: Page,
631 info: UnwindInfo,591 info: UnwindInfo,
632 };
633592
634 fn format2(593 fn default(f: Format, w: *Writer) Writer.Error!void {
635 ctx: FormatPageContext,594 try w.writeAll("Page:\n");
636 comptime unused_format_string: []const u8,595 try w.print(" kind: {s}\n", .{@tagName(f.page.kind)});
637 options: std.fmt.FormatOptions,596 try w.print(" entries: {d} - {d}\n", .{
638 writer: anytype,597 f.page.start,
639 ) @TypeOf(writer).Error!void {598 f.page.start + f.page.count,
640 _ = options;599 });
641 _ = unused_format_string;600 try w.print(" encodings (count = {d})\n", .{f.page.page_encodings_count});
642 try writer.writeAll("Page:\n");601 for (f.page.page_encodings[0..f.page.page_encodings_count], 0..) |enc, i| {
643 try writer.print(" kind: {s}\n", .{@tagName(ctx.page.kind)});602 try w.print(" {d}: {f}\n", .{ f.info.common_encodings_count + i, enc });
644 try writer.print(" entries: {d} - {d}\n", .{603 }
645 ctx.page.start,
646 ctx.page.start + ctx.page.count,
647 });
648 try writer.print(" encodings (count = {d})\n", .{ctx.page.page_encodings_count});
649 for (ctx.page.page_encodings[0..ctx.page.page_encodings_count], 0..) |enc, i| {
650 try writer.print(" {d}: {}\n", .{ ctx.info.common_encodings_count + i, enc });
651 }604 }
652 }605 };
653606
654 fn fmt(page: Page, info: UnwindInfo) std.fmt.Formatter(format2) {607 fn fmt(page: Page, info: UnwindInfo) std.fmt.Formatter(Format, Format.default) {
655 return .{ .data = .{608 return .{ .data = .{
656 .page = page,609 .page = page,
657 .info = info,610 .info = info,
...@@ -720,6 +673,7 @@ const macho = std.macho;...@@ -720,6 +673,7 @@ const macho = std.macho;
720const math = std.math;673const math = std.math;
721const mem = std.mem;674const mem = std.mem;
722const trace = @import("../../tracy.zig").trace;675const trace = @import("../../tracy.zig").trace;
676const Writer = std.io.Writer;
723677
724const Allocator = mem.Allocator;678const Allocator = mem.Allocator;
725const Atom = @import("Atom.zig");679const Atom = @import("Atom.zig");
src/link/MachO/ZigObject.zig+34-47
...@@ -618,7 +618,7 @@ pub fn getNavVAddr(...@@ -618,7 +618,7 @@ pub fn getNavVAddr(
618 const zcu = pt.zcu;618 const zcu = pt.zcu;
619 const ip = &zcu.intern_pool;619 const ip = &zcu.intern_pool;
620 const nav = ip.getNav(nav_index);620 const nav = ip.getNav(nav_index);
621 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });621 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
622 const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(622 const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(
623 macho_file,623 macho_file,
624 nav.name.toSlice(ip),624 nav.name.toSlice(ip),
...@@ -943,7 +943,7 @@ fn updateNavCode(...@@ -943,7 +943,7 @@ fn updateNavCode(
943 const ip = &zcu.intern_pool;943 const ip = &zcu.intern_pool;
944 const nav = ip.getNav(nav_index);944 const nav = ip.getNav(nav_index);
945945
946 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });946 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
947947
948 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;948 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
949 const required_alignment = switch (pt.navAlignment(nav_index)) {949 const required_alignment = switch (pt.navAlignment(nav_index)) {
...@@ -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);
...@@ -981,7 +981,7 @@ fn updateNavCode(...@@ -981,7 +981,7 @@ fn updateNavCode(
981 if (need_realloc) {981 if (need_realloc) {
982 atom.grow(macho_file) catch |err|982 atom.grow(macho_file) catch |err|
983 return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});983 return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});
984 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });984 log.debug("growing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });
985 if (old_vaddr != atom.value) {985 if (old_vaddr != atom.value) {
986 sym.value = 0;986 sym.value = 0;
987 nlist.n_value = 0;987 nlist.n_value = 0;
...@@ -1023,7 +1023,7 @@ fn updateTlv(...@@ -1023,7 +1023,7 @@ fn updateTlv(
1023 const ip = &pt.zcu.intern_pool;1023 const ip = &pt.zcu.intern_pool;
1024 const nav = ip.getNav(nav_index);1024 const nav = ip.getNav(nav_index);
10251025
1026 log.debug("updateTlv {} (0x{x})", .{ nav.fqn.fmt(ip), nav_index });1026 log.debug("updateTlv {f} (0x{x})", .{ nav.fqn.fmt(ip), nav_index });
10271027
1028 // 1. Lower TLV initializer1028 // 1. Lower TLV initializer
1029 const init_sym_index = try self.createTlvInitializer(1029 const init_sym_index = try self.createTlvInitializer(
...@@ -1351,7 +1351,7 @@ fn updateLazySymbol(...@@ -1351,7 +1351,7 @@ fn updateLazySymbol(
1351 defer code_buffer.deinit(gpa);1351 defer code_buffer.deinit(gpa);
13521352
1353 const name_str = blk: {1353 const name_str = blk: {
1354 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{1354 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
1355 @tagName(lazy_sym.kind),1355 @tagName(lazy_sym.kind),
1356 Type.fromInterned(lazy_sym.ty).fmt(pt),1356 Type.fromInterned(lazy_sym.ty).fmt(pt),
1357 });1357 });
...@@ -1430,7 +1430,7 @@ pub fn deleteExport(...@@ -1430,7 +1430,7 @@ pub fn deleteExport(
1430 } orelse return;1430 } orelse return;
1431 const nlist_index = metadata.@"export"(self, name.toSlice(&zcu.intern_pool)) orelse return;1431 const nlist_index = metadata.@"export"(self, name.toSlice(&zcu.intern_pool)) orelse return;
14321432
1433 log.debug("deleting export '{}'", .{name.fmt(&zcu.intern_pool)});1433 log.debug("deleting export '{f}'", .{name.fmt(&zcu.intern_pool)});
14341434
1435 const nlist = &self.symtab.items(.nlist)[nlist_index.*];1435 const nlist = &self.symtab.items(.nlist)[nlist_index.*];
1436 self.symtab.items(.size)[nlist_index.*] = 0;1436 self.symtab.items(.size)[nlist_index.*] = 0;
...@@ -1678,64 +1678,50 @@ pub fn asFile(self: *ZigObject) File {...@@ -1678,64 +1678,50 @@ pub fn asFile(self: *ZigObject) File {
1678 return .{ .zig_object = self };1678 return .{ .zig_object = self };
1679}1679}
16801680
1681pub fn fmtSymtab(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatSymtab) {1681pub fn fmtSymtab(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) {
1682 return .{ .data = .{1682 return .{ .data = .{
1683 .self = self,1683 .self = self,
1684 .macho_file = macho_file,1684 .macho_file = macho_file,
1685 } };1685 } };
1686}1686}
16871687
1688const FormatContext = struct {1688const Format = struct {
1689 self: *ZigObject,1689 self: *ZigObject,
1690 macho_file: *MachO,1690 macho_file: *MachO,
1691};
16921691
1693fn formatSymtab(1692 fn symtab(f: Format, w: *Writer) Writer.Error!void {
1694 ctx: FormatContext,1693 try w.writeAll(" symbols\n");
1695 comptime unused_fmt_string: []const u8,1694 const self = f.self;
1696 options: std.fmt.FormatOptions,1695 const macho_file = f.macho_file;
1697 writer: anytype,1696 for (self.symbols.items, 0..) |sym, i| {
1698) !void {1697 const ref = self.getSymbolRef(@intCast(i), macho_file);
1699 _ = unused_fmt_string;1698 if (ref.getFile(macho_file) == null) {
1700 _ = options;1699 // TODO any better way of handling this?
1701 try writer.writeAll(" symbols\n");1700 try w.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
1702 const self = ctx.self;1701 } else {
1703 const macho_file = ctx.macho_file;1702 try w.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
1704 for (self.symbols.items, 0..) |sym, i| {1703 }
1705 const ref = self.getSymbolRef(@intCast(i), macho_file);
1706 if (ref.getFile(macho_file) == null) {
1707 // TODO any better way of handling this?
1708 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
1709 } else {
1710 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
1711 }1704 }
1712 }1705 }
1713}
17141706
1715pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatAtoms) {1707 fn atoms(f: Format, w: *Writer) Writer.Error!void {
1708 const self = f.self;
1709 const macho_file = f.macho_file;
1710 try w.writeAll(" atoms\n");
1711 for (self.getAtoms()) |atom_index| {
1712 const atom = self.getAtom(atom_index) orelse continue;
1713 try w.print(" {f}\n", .{atom.fmt(macho_file)});
1714 }
1715 }
1716};
1717
1718pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.atoms) {
1716 return .{ .data = .{1719 return .{ .data = .{
1717 .self = self,1720 .self = self,
1718 .macho_file = macho_file,1721 .macho_file = macho_file,
1719 } };1722 } };
1720}1723}
17211724
1722fn formatAtoms(
1723 ctx: FormatContext,
1724 comptime unused_fmt_string: []const u8,
1725 options: std.fmt.FormatOptions,
1726 writer: anytype,
1727) !void {
1728 _ = unused_fmt_string;
1729 _ = options;
1730 const self = ctx.self;
1731 const macho_file = ctx.macho_file;
1732 try writer.writeAll(" atoms\n");
1733 for (self.getAtoms()) |atom_index| {
1734 const atom = self.getAtom(atom_index) orelse continue;
1735 try writer.print(" {}\n", .{atom.fmt(macho_file)});
1736 }
1737}
1738
1739const AvMetadata = struct {1725const AvMetadata = struct {
1740 symbol_index: Symbol.Index,1726 symbol_index: Symbol.Index,
1741 /// A list of all exports aliases of this Av.1727 /// A list of all exports aliases of this Av.
...@@ -1797,6 +1783,7 @@ const mem = std.mem;...@@ -1797,6 +1783,7 @@ const mem = std.mem;
1797const target_util = @import("../../target.zig");1783const target_util = @import("../../target.zig");
1798const trace = @import("../../tracy.zig").trace;1784const trace = @import("../../tracy.zig").trace;
1799const std = @import("std");1785const std = @import("std");
1786const Writer = std.io.Writer;
18001787
1801const Allocator = std.mem.Allocator;1788const Allocator = std.mem.Allocator;
1802const Archive = @import("Archive.zig");1789const Archive = @import("Archive.zig");
src/link/MachO/dead_strip.zig+4-10
...@@ -117,7 +117,7 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {...@@ -117,7 +117,7 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
117fn markLive(atom: *Atom, macho_file: *MachO) void {117fn markLive(atom: *Atom, macho_file: *MachO) void {
118 assert(atom.visited.load(.seq_cst));118 assert(atom.visited.load(.seq_cst));
119 atom.setAlive(true);119 atom.setAlive(true);
120 track_live_log.debug("{}marking live atom({d},{s})", .{120 track_live_log.debug("{f}marking live atom({d},{s})", .{
121 track_live_level,121 track_live_level,
122 atom.atom_index,122 atom.atom_index,
123 atom.getName(macho_file),123 atom.getName(macho_file),
...@@ -196,15 +196,8 @@ const Level = struct {...@@ -196,15 +196,8 @@ const Level = struct {
196 self.value += 1;196 self.value += 1;
197 }197 }
198198
199 pub fn format(199 pub fn format(self: *const @This(), w: *Writer) Writer.Error!void {
200 self: *const @This(),200 try w.splatByteAll(' ', self.value);
201 comptime unused_fmt_string: []const u8,
202 options: std.fmt.FormatOptions,
203 writer: anytype,
204 ) !void {
205 _ = unused_fmt_string;
206 _ = options;
207 try writer.writeByteNTimes(' ', self.value);
208 }201 }
209};202};
210203
...@@ -219,6 +212,7 @@ const mem = std.mem;...@@ -219,6 +212,7 @@ const mem = std.mem;
219const trace = @import("../../tracy.zig").trace;212const trace = @import("../../tracy.zig").trace;
220const track_live_log = std.log.scoped(.dead_strip_track_live);213const track_live_log = std.log.scoped(.dead_strip_track_live);
221const std = @import("std");214const std = @import("std");
215const Writer = std.io.Writer;
222216
223const Allocator = mem.Allocator;217const Allocator = mem.Allocator;
224const Atom = @import("Atom.zig");218const Atom = @import("Atom.zig");
src/link/MachO/dyld_info/Rebase.zig+3-2
...@@ -654,9 +654,10 @@ const log = std.log.scoped(.link_dyld_info);...@@ -654,9 +654,10 @@ const log = std.log.scoped(.link_dyld_info);
654const macho = std.macho;654const macho = std.macho;
655const mem = std.mem;655const mem = std.mem;
656const testing = std.testing;656const testing = std.testing;
657const trace = @import("../../../tracy.zig").trace;
658
659const Allocator = mem.Allocator;657const Allocator = mem.Allocator;
658const Writer = std.io.Writer;
659
660const trace = @import("../../../tracy.zig").trace;
660const File = @import("../file.zig").File;661const File = @import("../file.zig").File;
661const MachO = @import("../../MachO.zig");662const MachO = @import("../../MachO.zig");
662const Rebase = @This();663const Rebase = @This();
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/MachO/dyld_info/bind.zig+2-2
...@@ -205,7 +205,7 @@ pub const Bind = struct {...@@ -205,7 +205,7 @@ pub const Bind = struct {
205 }205 }
206 }206 }
207207
208 log.debug("{x}, {d}, {x}, {?x}, {s}", .{ offset, count, skip, addend, @tagName(state) });208 log.debug("{x}, {d}, {x}, {x}, {s}", .{ offset, count, skip, addend, @tagName(state) });
209 log.debug(" => {x}", .{current.offset});209 log.debug(" => {x}", .{current.offset});
210 switch (state) {210 switch (state) {
211 .start => {211 .start => {
...@@ -447,7 +447,7 @@ pub const WeakBind = struct {...@@ -447,7 +447,7 @@ pub const WeakBind = struct {
447 }447 }
448 }448 }
449449
450 log.debug("{x}, {d}, {x}, {?x}, {s}", .{ offset, count, skip, addend, @tagName(state) });450 log.debug("{x}, {d}, {x}, {x}, {s}", .{ offset, count, skip, addend, @tagName(state) });
451 log.debug(" => {x}", .{current.offset});451 log.debug(" => {x}", .{current.offset});
452 switch (state) {452 switch (state) {
453 .start => {453 .start => {
src/link/MachO/eh_frame.zig+26-65
...@@ -81,46 +81,26 @@ pub const Cie = struct {...@@ -81,46 +81,26 @@ pub const Cie = struct {
81 return true;81 return true;
82 }82 }
8383
84 pub fn format(84 pub fn fmt(cie: Cie, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) {
85 cie: Cie,
86 comptime unused_fmt_string: []const u8,
87 options: std.fmt.FormatOptions,
88 writer: anytype,
89 ) !void {
90 _ = cie;
91 _ = unused_fmt_string;
92 _ = options;
93 _ = writer;
94 @compileError("do not format CIEs directly");
95 }
96
97 pub fn fmt(cie: Cie, macho_file: *MachO) std.fmt.Formatter(format2) {
98 return .{ .data = .{85 return .{ .data = .{
99 .cie = cie,86 .cie = cie,
100 .macho_file = macho_file,87 .macho_file = macho_file,
101 } };88 } };
102 }89 }
10390
104 const FormatContext = struct {91 const Format = struct {
105 cie: Cie,92 cie: Cie,
106 macho_file: *MachO,93 macho_file: *MachO,
107 };
10894
109 fn format2(95 fn default(f: Format, w: *Writer) Writer.Error!void {
110 ctx: FormatContext,96 const cie = f.cie;
111 comptime unused_fmt_string: []const u8,97 try w.print("@{x} : size({x})", .{
112 options: std.fmt.FormatOptions,98 cie.offset,
113 writer: anytype,99 cie.getSize(),
114 ) !void {100 });
115 _ = unused_fmt_string;101 if (!cie.alive) try w.writeAll(" : [*]");
116 _ = options;102 }
117 const cie = ctx.cie;103 };
118 try writer.print("@{x} : size({x})", .{
119 cie.offset,
120 cie.getSize(),
121 });
122 if (!cie.alive) try writer.writeAll(" : [*]");
123 }
124104
125 pub const Index = u32;105 pub const Index = u32;
126106
...@@ -231,49 +211,29 @@ pub const Fde = struct {...@@ -231,49 +211,29 @@ pub const Fde = struct {
231 return fde.getObject(macho_file).getAtom(fde.lsda);211 return fde.getObject(macho_file).getAtom(fde.lsda);
232 }212 }
233213
234 pub fn format(214 pub fn fmt(fde: Fde, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) {
235 fde: Fde,
236 comptime unused_fmt_string: []const u8,
237 options: std.fmt.FormatOptions,
238 writer: anytype,
239 ) !void {
240 _ = fde;
241 _ = unused_fmt_string;
242 _ = options;
243 _ = writer;
244 @compileError("do not format FDEs directly");
245 }
246
247 pub fn fmt(fde: Fde, macho_file: *MachO) std.fmt.Formatter(format2) {
248 return .{ .data = .{215 return .{ .data = .{
249 .fde = fde,216 .fde = fde,
250 .macho_file = macho_file,217 .macho_file = macho_file,
251 } };218 } };
252 }219 }
253220
254 const FormatContext = struct {221 const Format = struct {
255 fde: Fde,222 fde: Fde,
256 macho_file: *MachO,223 macho_file: *MachO,
257 };
258224
259 fn format2(225 fn default(f: Format, writer: *Writer) Writer.Error!void {
260 ctx: FormatContext,226 const fde = f.fde;
261 comptime unused_fmt_string: []const u8,227 const macho_file = f.macho_file;
262 options: std.fmt.FormatOptions,228 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{
263 writer: anytype,229 fde.offset,
264 ) !void {230 fde.getSize(),
265 _ = unused_fmt_string;231 fde.cie,
266 _ = options;232 fde.getAtom(macho_file).getName(macho_file),
267 const fde = ctx.fde;233 });
268 const macho_file = ctx.macho_file;234 if (!fde.alive) try writer.writeAll(" : [*]");
269 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{235 }
270 fde.offset,236 };
271 fde.getSize(),
272 fde.cie,
273 fde.getAtom(macho_file).getName(macho_file),
274 });
275 if (!fde.alive) try writer.writeAll(" : [*]");
276 }
277237
278 pub const Index = u32;238 pub const Index = u32;
279};239};
...@@ -545,6 +505,7 @@ const math = std.math;...@@ -545,6 +505,7 @@ const math = std.math;
545const mem = std.mem;505const mem = std.mem;
546const std = @import("std");506const std = @import("std");
547const trace = @import("../../tracy.zig").trace;507const trace = @import("../../tracy.zig").trace;
508const Writer = std.io.Writer;
548509
549const Allocator = std.mem.Allocator;510const Allocator = std.mem.Allocator;
550const Atom = @import("Atom.zig");511const Atom = @import("Atom.zig");
src/link/MachO/file.zig+7-13
...@@ -10,23 +10,16 @@ pub const File = union(enum) {...@@ -10,23 +10,16 @@ pub const File = union(enum) {
10 };10 };
11 }11 }
1212
13 pub fn fmtPath(file: File) std.fmt.Formatter(formatPath) {13 pub fn fmtPath(file: File) std.fmt.Formatter(File, formatPath) {
14 return .{ .data = file };14 return .{ .data = file };
15 }15 }
1616
17 fn formatPath(17 fn formatPath(file: File, w: *Writer) Writer.Error!void {
18 file: File,
19 comptime unused_fmt_string: []const u8,
20 options: std.fmt.FormatOptions,
21 writer: anytype,
22 ) !void {
23 _ = unused_fmt_string;
24 _ = options;
25 switch (file) {18 switch (file) {
26 .zig_object => |zo| try writer.writeAll(zo.basename),19 .zig_object => |zo| try w.writeAll(zo.basename),
27 .internal => try writer.writeAll("internal"),20 .internal => try w.writeAll("internal"),
28 .object => |x| try writer.print("{}", .{x.fmtPath()}),21 .object => |x| try w.print("{f}", .{x.fmtPath()}),
29 .dylib => |dl| try writer.print("{}", .{@as(Path, dl.path)}),22 .dylib => |dl| try w.print("{f}", .{@as(Path, dl.path)}),
30 }23 }
31 }24 }
3225
...@@ -371,6 +364,7 @@ const log = std.log.scoped(.link);...@@ -371,6 +364,7 @@ const log = std.log.scoped(.link);
371const macho = std.macho;364const macho = std.macho;
372const Allocator = std.mem.Allocator;365const Allocator = std.mem.Allocator;
373const Path = std.Build.Cache.Path;366const Path = std.Build.Cache.Path;
367const Writer = std.io.Writer;
374368
375const trace = @import("../../tracy.zig").trace;369const trace = @import("../../tracy.zig").trace;
376const Archive = @import("Archive.zig");370const Archive = @import("Archive.zig");
src/link/MachO/load_commands.zig+1
...@@ -3,6 +3,7 @@ const assert = std.debug.assert;...@@ -3,6 +3,7 @@ const assert = std.debug.assert;
3const log = std.log.scoped(.link);3const log = std.log.scoped(.link);
4const macho = std.macho;4const macho = std.macho;
5const mem = std.mem;5const mem = std.mem;
6const Writer = std.io.Writer;
67
7const Allocator = mem.Allocator;8const Allocator = mem.Allocator;
8const DebugSymbols = @import("DebugSymbols.zig");9const DebugSymbols = @import("DebugSymbols.zig");
src/link/MachO/relocatable.zig+8-7
...@@ -20,13 +20,13 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -20,13 +20,13 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
20 // the *only* input file over.20 // the *only* input file over.
21 const path = positionals.items[0].path().?;21 const path = positionals.items[0].path().?;
22 const in_file = path.root_dir.handle.openFile(path.sub_path, .{}) catch |err|22 const in_file = path.root_dir.handle.openFile(path.sub_path, .{}) catch |err|
23 return diags.fail("failed to open {}: {s}", .{ path, @errorName(err) });23 return diags.fail("failed to open {f}: {s}", .{ path, @errorName(err) });
24 const stat = in_file.stat() catch |err|24 const stat = in_file.stat() catch |err|
25 return diags.fail("failed to stat {}: {s}", .{ path, @errorName(err) });25 return diags.fail("failed to stat {f}: {s}", .{ path, @errorName(err) });
26 const amt = in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size) catch |err|26 const amt = in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size) catch |err|
27 return diags.fail("failed to copy range of file {}: {s}", .{ path, @errorName(err) });27 return diags.fail("failed to copy range of file {f}: {s}", .{ path, @errorName(err) });
28 if (amt != stat.size)28 if (amt != stat.size)
29 return diags.fail("unexpected short write in copy range of file {}", .{path});29 return diags.fail("unexpected short write in copy range of file {f}", .{path});
30 return;30 return;
31 }31 }
3232
...@@ -62,7 +62,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -62,7 +62,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
62 allocateSegment(macho_file);62 allocateSegment(macho_file);
6363
64 if (build_options.enable_logging) {64 if (build_options.enable_logging) {
65 state_log.debug("{}", .{macho_file.dumpState()});65 state_log.debug("{f}", .{macho_file.dumpState()});
66 }66 }
6767
68 try writeSections(macho_file);68 try writeSections(macho_file);
...@@ -126,7 +126,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -126,7 +126,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
126 allocateSegment(macho_file);126 allocateSegment(macho_file);
127127
128 if (build_options.enable_logging) {128 if (build_options.enable_logging) {
129 state_log.debug("{}", .{macho_file.dumpState()});129 state_log.debug("{f}", .{macho_file.dumpState()});
130 }130 }
131131
132 try writeSections(macho_file);132 try writeSections(macho_file);
...@@ -202,7 +202,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -202,7 +202,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
202 };202 };
203203
204 if (build_options.enable_logging) {204 if (build_options.enable_logging) {
205 state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(macho_file)});205 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});
206 }206 }
207207
208 var buffer = std.ArrayList(u8).init(gpa);208 var buffer = std.ArrayList(u8).init(gpa);
...@@ -784,6 +784,7 @@ const macho = std.macho;...@@ -784,6 +784,7 @@ const macho = std.macho;
784const math = std.math;784const math = std.math;
785const mem = std.mem;785const mem = std.mem;
786const state_log = std.log.scoped(.link_state);786const state_log = std.log.scoped(.link_state);
787const Writer = std.io.Writer;
787788
788const Archive = @import("Archive.zig");789const Archive = @import("Archive.zig");
789const Atom = @import("Atom.zig");790const Atom = @import("Atom.zig");
src/link/MachO/synthetic.zig+70-97
...@@ -37,34 +37,27 @@ pub const GotSection = struct {...@@ -37,34 +37,27 @@ pub const GotSection = struct {
37 }37 }
38 }38 }
3939
40 const FormatCtx = struct {40 const Format = struct {
41 got: GotSection,41 got: GotSection,
42 macho_file: *MachO,42 macho_file: *MachO,
43
44 pub fn print(f: Format, w: *Writer) Writer.Error!void {
45 for (f.got.symbols.items, 0..) |ref, i| {
46 const symbol = ref.getSymbol(f.macho_file).?;
47 try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
48 i,
49 symbol.getGotAddress(f.macho_file),
50 ref,
51 symbol.getAddress(.{}, f.macho_file),
52 symbol.getName(f.macho_file),
53 });
54 }
55 }
43 };56 };
4457
45 pub fn fmt(got: GotSection, macho_file: *MachO) std.fmt.Formatter(format2) {58 pub fn fmt(got: GotSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) {
46 return .{ .data = .{ .got = got, .macho_file = macho_file } };59 return .{ .data = .{ .got = got, .macho_file = macho_file } };
47 }60 }
48
49 pub fn format2(
50 ctx: FormatCtx,
51 comptime unused_fmt_string: []const u8,
52 options: std.fmt.FormatOptions,
53 writer: anytype,
54 ) !void {
55 _ = options;
56 _ = unused_fmt_string;
57 for (ctx.got.symbols.items, 0..) |ref, i| {
58 const symbol = ref.getSymbol(ctx.macho_file).?;
59 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
60 i,
61 symbol.getGotAddress(ctx.macho_file),
62 ref,
63 symbol.getAddress(.{}, ctx.macho_file),
64 symbol.getName(ctx.macho_file),
65 });
66 }
67 }
68};61};
6962
70pub const StubsSection = struct {63pub const StubsSection = struct {
...@@ -128,34 +121,27 @@ pub const StubsSection = struct {...@@ -128,34 +121,27 @@ pub const StubsSection = struct {
128 }121 }
129 }122 }
130123
131 const FormatCtx = struct {124 pub fn fmt(stubs: StubsSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) {
132 stubs: StubsSection,
133 macho_file: *MachO,
134 };
135
136 pub fn fmt(stubs: StubsSection, macho_file: *MachO) std.fmt.Formatter(format2) {
137 return .{ .data = .{ .stubs = stubs, .macho_file = macho_file } };125 return .{ .data = .{ .stubs = stubs, .macho_file = macho_file } };
138 }126 }
139127
140 pub fn format2(128 const Format = struct {
141 ctx: FormatCtx,129 stubs: StubsSection,
142 comptime unused_fmt_string: []const u8,130 macho_file: *MachO,
143 options: std.fmt.FormatOptions,131
144 writer: anytype,132 pub fn print(f: Format, w: *Writer) Writer.Error!void {
145 ) !void {133 for (f.stubs.symbols.items, 0..) |ref, i| {
146 _ = options;134 const symbol = ref.getSymbol(f.macho_file).?;
147 _ = unused_fmt_string;135 try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
148 for (ctx.stubs.symbols.items, 0..) |ref, i| {136 i,
149 const symbol = ref.getSymbol(ctx.macho_file).?;137 symbol.getStubsAddress(f.macho_file),
150 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{138 ref,
151 i,139 symbol.getAddress(.{}, f.macho_file),
152 symbol.getStubsAddress(ctx.macho_file),140 symbol.getName(f.macho_file),
153 ref,141 });
154 symbol.getAddress(.{}, ctx.macho_file),142 }
155 symbol.getName(ctx.macho_file),
156 });
157 }143 }
158 }144 };
159};145};
160146
161pub const StubsHelperSection = struct {147pub const StubsHelperSection = struct {
...@@ -357,34 +343,27 @@ pub const TlvPtrSection = struct {...@@ -357,34 +343,27 @@ pub const TlvPtrSection = struct {
357 }343 }
358 }344 }
359345
360 const FormatCtx = struct {346 pub fn fmt(tlv: TlvPtrSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) {
361 tlv: TlvPtrSection,
362 macho_file: *MachO,
363 };
364
365 pub fn fmt(tlv: TlvPtrSection, macho_file: *MachO) std.fmt.Formatter(format2) {
366 return .{ .data = .{ .tlv = tlv, .macho_file = macho_file } };347 return .{ .data = .{ .tlv = tlv, .macho_file = macho_file } };
367 }348 }
368349
369 pub fn format2(350 const Format = struct {
370 ctx: FormatCtx,351 tlv: TlvPtrSection,
371 comptime unused_fmt_string: []const u8,352 macho_file: *MachO,
372 options: std.fmt.FormatOptions,353
373 writer: anytype,354 pub fn print(f: Format, w: *Writer) Writer.Error!void {
374 ) !void {355 for (f.tlv.symbols.items, 0..) |ref, i| {
375 _ = options;356 const symbol = ref.getSymbol(f.macho_file).?;
376 _ = unused_fmt_string;357 try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
377 for (ctx.tlv.symbols.items, 0..) |ref, i| {358 i,
378 const symbol = ref.getSymbol(ctx.macho_file).?;359 symbol.getTlvPtrAddress(f.macho_file),
379 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{360 ref,
380 i,361 symbol.getAddress(.{}, f.macho_file),
381 symbol.getTlvPtrAddress(ctx.macho_file),362 symbol.getName(f.macho_file),
382 ref,363 });
383 symbol.getAddress(.{}, ctx.macho_file),364 }
384 symbol.getName(ctx.macho_file),
385 });
386 }365 }
387 }366 };
388};367};
389368
390pub const ObjcStubsSection = struct {369pub const ObjcStubsSection = struct {
...@@ -482,34 +461,27 @@ pub const ObjcStubsSection = struct {...@@ -482,34 +461,27 @@ pub const ObjcStubsSection = struct {
482 }461 }
483 }462 }
484463
485 const FormatCtx = struct {464 pub fn fmt(objc: ObjcStubsSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) {
486 objc: ObjcStubsSection,
487 macho_file: *MachO,
488 };
489
490 pub fn fmt(objc: ObjcStubsSection, macho_file: *MachO) std.fmt.Formatter(format2) {
491 return .{ .data = .{ .objc = objc, .macho_file = macho_file } };465 return .{ .data = .{ .objc = objc, .macho_file = macho_file } };
492 }466 }
493467
494 pub fn format2(468 const Format = struct {
495 ctx: FormatCtx,469 objc: ObjcStubsSection,
496 comptime unused_fmt_string: []const u8,470 macho_file: *MachO,
497 options: std.fmt.FormatOptions,471
498 writer: anytype,472 pub fn print(f: Format, w: *Writer) Writer.Error!void {
499 ) !void {473 for (f.objc.symbols.items, 0..) |ref, i| {
500 _ = options;474 const symbol = ref.getSymbol(f.macho_file).?;
501 _ = unused_fmt_string;475 try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
502 for (ctx.objc.symbols.items, 0..) |ref, i| {476 i,
503 const symbol = ref.getSymbol(ctx.macho_file).?;477 symbol.getObjcStubsAddress(f.macho_file),
504 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{478 ref,
505 i,479 symbol.getAddress(.{}, f.macho_file),
506 symbol.getObjcStubsAddress(ctx.macho_file),480 symbol.getName(f.macho_file),
507 ref,481 });
508 symbol.getAddress(.{}, ctx.macho_file),482 }
509 symbol.getName(ctx.macho_file),
510 });
511 }483 }
512 }484 };
513485
514 pub const Index = u32;486 pub const Index = u32;
515};487};
...@@ -625,13 +597,14 @@ pub const DataInCode = struct {...@@ -625,13 +597,14 @@ pub const DataInCode = struct {
625 };597 };
626};598};
627599
600const std = @import("std");
628const aarch64 = @import("../aarch64.zig");601const aarch64 = @import("../aarch64.zig");
629const assert = std.debug.assert;602const assert = std.debug.assert;
630const macho = std.macho;603const macho = std.macho;
631const math = std.math;604const math = std.math;
632const std = @import("std");
633const trace = @import("../../tracy.zig").trace;
634
635const Allocator = std.mem.Allocator;605const Allocator = std.mem.Allocator;
606const Writer = std.io.Writer;
607
608const trace = @import("../../tracy.zig").trace;
636const MachO = @import("../MachO.zig");609const MachO = @import("../MachO.zig");
637const Symbol = @import("Symbol.zig");610const Symbol = @import("Symbol.zig");
src/link/Plan9.zig+6-6
...@@ -445,7 +445,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -445,7 +445,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
445 .func => return,445 .func => return,
446 .variable => |variable| Value.fromInterned(variable.init),446 .variable => |variable| Value.fromInterned(variable.init),
447 .@"extern" => {447 .@"extern" => {
448 log.debug("found extern decl: {}", .{nav.name.fmt(ip)});448 log.debug("found extern decl: {f}", .{nav.name.fmt(ip)});
449 return;449 return;
450 },450 },
451 else => nav_val,451 else => nav_val,
...@@ -675,7 +675,7 @@ pub fn flush(...@@ -675,7 +675,7 @@ pub fn flush(
675 const off = self.getAddr(text_i, .t);675 const off = self.getAddr(text_i, .t);
676 text_i += out.code.len;676 text_i += out.code.len;
677 atom.offset = off;677 atom.offset = off;
678 log.debug("write text nav 0x{x} ({}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ nav_index, nav.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off });678 log.debug("write text nav 0x{x} ({f}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ nav_index, nav.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off });
679 if (!self.sixtyfour_bit) {679 if (!self.sixtyfour_bit) {
680 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian());680 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian());
681 } else {681 } else {
...@@ -974,11 +974,11 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -974,11 +974,11 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
974 self.etext_edata_end_atom_indices[2] = atom_idx;974 self.etext_edata_end_atom_indices[2] = atom_idx;
975 }975 }
976 try self.updateFinish(pt, nav_index);976 try self.updateFinish(pt, nav_index);
977 log.debug("seeNav(extern) for {} (got_addr=0x{x})", .{977 log.debug("seeNav(extern) for {f} (got_addr=0x{x})", .{
978 nav.name.fmt(ip),978 nav.name.fmt(ip),
979 self.getAtom(atom_idx).getOffsetTableAddress(self),979 self.getAtom(atom_idx).getOffsetTableAddress(self),
980 });980 });
981 } else log.debug("seeNav for {}", .{nav.name.fmt(ip)});981 } else log.debug("seeNav for {f}", .{nav.name.fmt(ip)});
982 return atom_idx;982 return atom_idx;
983}983}
984984
...@@ -1043,7 +1043,7 @@ fn updateLazySymbolAtom(...@@ -1043,7 +1043,7 @@ fn updateLazySymbolAtom(
1043 defer code_buffer.deinit(gpa);1043 defer code_buffer.deinit(gpa);
10441044
1045 // create the symbol for the name1045 // create the symbol for the name
1046 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{1046 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
1047 @tagName(sym.kind),1047 @tagName(sym.kind),
1048 Type.fromInterned(sym.ty).fmt(pt),1048 Type.fromInterned(sym.ty).fmt(pt),
1049 });1049 });
...@@ -1314,7 +1314,7 @@ pub fn getNavVAddr(...@@ -1314,7 +1314,7 @@ pub fn getNavVAddr(
1314) !u64 {1314) !u64 {
1315 const ip = &pt.zcu.intern_pool;1315 const ip = &pt.zcu.intern_pool;
1316 const nav = ip.getNav(nav_index);1316 const nav = ip.getNav(nav_index);
1317 log.debug("getDeclVAddr for {}", .{nav.name.fmt(ip)});1317 log.debug("getDeclVAddr for {f}", .{nav.name.fmt(ip)});
1318 if (nav.getExtern(ip) != null) {1318 if (nav.getExtern(ip) != null) {
1319 if (nav.name.eqlSlice("etext", ip)) {1319 if (nav.name.eqlSlice("etext", ip)) {
1320 try self.addReloc(reloc_info.parent.atom_index, .{1320 try self.addReloc(reloc_info.parent.atom_index, .{
src/link/SpirV.zig+8-8
...@@ -117,7 +117,7 @@ pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin...@@ -117,7 +117,7 @@ pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin
117 }117 }
118118
119 const ip = &pt.zcu.intern_pool;119 const ip = &pt.zcu.intern_pool;
120 log.debug("lowering nav {}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });120 log.debug("lowering nav {f}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });
121121
122 try self.object.updateNav(pt, nav);122 try self.object.updateNav(pt, nav);
123}123}
...@@ -203,10 +203,10 @@ pub fn flush(...@@ -203,10 +203,10 @@ pub fn flush(
203 // We need to export the list of error names somewhere so that we can pretty-print them in the203 // We need to export the list of error names somewhere so that we can pretty-print them in the
204 // executor. This is not really an important thing though, so we can just dump it in any old204 // executor. This is not really an important thing though, so we can just dump it in any old
205 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.205 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.
206 var error_info = std.ArrayList(u8).init(self.object.gpa);206 var error_info: std.io.Writer.Allocating = .init(self.object.gpa);
207 defer error_info.deinit();207 defer error_info.deinit();
208208
209 try error_info.appendSlice("zig_errors:");209 error_info.writer.writeAll("zig_errors:") catch return error.OutOfMemory;
210 const ip = &self.base.comp.zcu.?.intern_pool;210 const ip = &self.base.comp.zcu.?.intern_pool;
211 for (ip.global_error_set.getNamesFromMainThread()) |name| {211 for (ip.global_error_set.getNamesFromMainThread()) |name| {
212 // Errors can contain pretty much any character - to encode them in a string we must escape212 // Errors can contain pretty much any character - to encode them in a string we must escape
...@@ -214,9 +214,9 @@ pub fn flush(...@@ -214,9 +214,9 @@ pub fn flush(
214 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.214 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.
215 // We're using : as separator, which is a reserved character.215 // We're using : as separator, which is a reserved character.
216216
217 try error_info.append(':');217 error_info.writer.writeByte(':') catch return error.OutOfMemory;
218 try std.Uri.Component.percentEncode(218 std.Uri.Component.percentEncode(
219 error_info.writer(),219 &error_info.writer,
220 name.toSlice(ip),220 name.toSlice(ip),
221 struct {221 struct {
222 fn isValidChar(c: u8) bool {222 fn isValidChar(c: u8) bool {
...@@ -226,10 +226,10 @@ pub fn flush(...@@ -226,10 +226,10 @@ pub fn flush(
226 };226 };
227 }227 }
228 }.isValidChar,228 }.isValidChar,
229 );229 ) catch return error.OutOfMemory;
230 }230 }
231 try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{231 try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{
232 .extension = error_info.items,232 .extension = error_info.getWritten(),
233 });233 });
234234
235 const module = try spv.finalize(arena);235 const module = try spv.finalize(arena);
src/link/SpirV/deduplicate.zig+1-1
...@@ -110,7 +110,7 @@ const ModuleInfo = struct {...@@ -110,7 +110,7 @@ const ModuleInfo = struct {
110 .TypeDeclaration, .ConstantCreation => {110 .TypeDeclaration, .ConstantCreation => {
111 const entry = try entities.getOrPut(result_id);111 const entry = try entities.getOrPut(result_id);
112 if (entry.found_existing) {112 if (entry.found_existing) {
113 log.err("type or constant {} has duplicate definition", .{result_id});113 log.err("type or constant {f} has duplicate definition", .{result_id});
114 return error.DuplicateId;114 return error.DuplicateId;
115 }115 }
116 entry.value_ptr.* = entity;116 entry.value_ptr.* = entity;
src/link/SpirV/lower_invocation_globals.zig+9-9
...@@ -92,7 +92,7 @@ const ModuleInfo = struct {...@@ -92,7 +92,7 @@ const ModuleInfo = struct {
92 const entry_point: ResultId = @enumFromInt(inst.operands[1]);92 const entry_point: ResultId = @enumFromInt(inst.operands[1]);
93 const entry = try entry_points.getOrPut(entry_point);93 const entry = try entry_points.getOrPut(entry_point);
94 if (entry.found_existing) {94 if (entry.found_existing) {
95 log.err("Entry point type {} has duplicate definition", .{entry_point});95 log.err("Entry point type {f} has duplicate definition", .{entry_point});
96 return error.DuplicateId;96 return error.DuplicateId;
97 }97 }
98 },98 },
...@@ -103,7 +103,7 @@ const ModuleInfo = struct {...@@ -103,7 +103,7 @@ const ModuleInfo = struct {
103103
104 const entry = try fn_types.getOrPut(fn_type);104 const entry = try fn_types.getOrPut(fn_type);
105 if (entry.found_existing) {105 if (entry.found_existing) {
106 log.err("Function type {} has duplicate definition", .{fn_type});106 log.err("Function type {f} has duplicate definition", .{fn_type});
107 return error.DuplicateId;107 return error.DuplicateId;
108 }108 }
109109
...@@ -135,7 +135,7 @@ const ModuleInfo = struct {...@@ -135,7 +135,7 @@ const ModuleInfo = struct {
135 },135 },
136 .OpFunction => {136 .OpFunction => {
137 if (maybe_current_function) |current_function| {137 if (maybe_current_function) |current_function| {
138 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});138 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
139 return error.InvalidPhysicalFormat;139 return error.InvalidPhysicalFormat;
140 }140 }
141141
...@@ -154,7 +154,7 @@ const ModuleInfo = struct {...@@ -154,7 +154,7 @@ const ModuleInfo = struct {
154 };154 };
155 const entry = try functions.getOrPut(current_function);155 const entry = try functions.getOrPut(current_function);
156 if (entry.found_existing) {156 if (entry.found_existing) {
157 log.err("Function {} has duplicate definition", .{current_function});157 log.err("Function {f} has duplicate definition", .{current_function});
158 return error.DuplicateId;158 return error.DuplicateId;
159 }159 }
160160
...@@ -162,7 +162,7 @@ const ModuleInfo = struct {...@@ -162,7 +162,7 @@ const ModuleInfo = struct {
162 try callee_store.appendSlice(calls.keys());162 try callee_store.appendSlice(calls.keys());
163163
164 const fn_type = fn_types.get(fn_ty_id) orelse {164 const fn_type = fn_types.get(fn_ty_id) orelse {
165 log.err("Function {} has invalid OpFunction type", .{current_function});165 log.err("Function {f} has invalid OpFunction type", .{current_function});
166 return error.InvalidId;166 return error.InvalidId;
167 };167 };
168168
...@@ -187,7 +187,7 @@ const ModuleInfo = struct {...@@ -187,7 +187,7 @@ const ModuleInfo = struct {
187 }187 }
188188
189 if (maybe_current_function) |current_function| {189 if (maybe_current_function) |current_function| {
190 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});190 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
191 return error.InvalidPhysicalFormat;191 return error.InvalidPhysicalFormat;
192 }192 }
193193
...@@ -222,7 +222,7 @@ const ModuleInfo = struct {...@@ -222,7 +222,7 @@ const ModuleInfo = struct {
222 seen: *std.DynamicBitSetUnmanaged,222 seen: *std.DynamicBitSetUnmanaged,
223 ) !void {223 ) !void {
224 const index = self.functions.getIndex(id) orelse {224 const index = self.functions.getIndex(id) orelse {
225 log.err("function calls invalid function {}", .{id});225 log.err("function calls invalid function {f}", .{id});
226 return error.InvalidId;226 return error.InvalidId;
227 };227 };
228228
...@@ -261,7 +261,7 @@ const ModuleInfo = struct {...@@ -261,7 +261,7 @@ const ModuleInfo = struct {
261 seen: *std.DynamicBitSetUnmanaged,261 seen: *std.DynamicBitSetUnmanaged,
262 ) !void {262 ) !void {
263 const index = self.invocation_globals.getIndex(id) orelse {263 const index = self.invocation_globals.getIndex(id) orelse {
264 log.err("invalid invocation global {}", .{id});264 log.err("invalid invocation global {f}", .{id});
265 return error.InvalidId;265 return error.InvalidId;
266 };266 };
267267
...@@ -276,7 +276,7 @@ const ModuleInfo = struct {...@@ -276,7 +276,7 @@ const ModuleInfo = struct {
276 }276 }
277277
278 const initializer = self.functions.get(info.initializer) orelse {278 const initializer = self.functions.get(info.initializer) orelse {
279 log.err("invocation global {} has invalid initializer {}", .{ id, info.initializer });279 log.err("invocation global {f} has invalid initializer {f}", .{ id, info.initializer });
280 return error.InvalidId;280 return error.InvalidId;
281 };281 };
282282
src/link/SpirV/prune_unused.zig+4-4
...@@ -128,7 +128,7 @@ const ModuleInfo = struct {...@@ -128,7 +128,7 @@ const ModuleInfo = struct {
128 switch (inst.opcode) {128 switch (inst.opcode) {
129 .OpFunction => {129 .OpFunction => {
130 if (maybe_current_function) |current_function| {130 if (maybe_current_function) |current_function| {
131 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});131 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
132 return error.InvalidPhysicalFormat;132 return error.InvalidPhysicalFormat;
133 }133 }
134134
...@@ -145,7 +145,7 @@ const ModuleInfo = struct {...@@ -145,7 +145,7 @@ const ModuleInfo = struct {
145 };145 };
146 const entry = try functions.getOrPut(current_function);146 const entry = try functions.getOrPut(current_function);
147 if (entry.found_existing) {147 if (entry.found_existing) {
148 log.err("Function {} has duplicate definition", .{current_function});148 log.err("Function {f} has duplicate definition", .{current_function});
149 return error.DuplicateId;149 return error.DuplicateId;
150 }150 }
151151
...@@ -163,7 +163,7 @@ const ModuleInfo = struct {...@@ -163,7 +163,7 @@ const ModuleInfo = struct {
163 }163 }
164164
165 if (maybe_current_function) |current_function| {165 if (maybe_current_function) |current_function| {
166 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});166 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
167 return error.InvalidPhysicalFormat;167 return error.InvalidPhysicalFormat;
168 }168 }
169169
...@@ -184,7 +184,7 @@ const AliveMarker = struct {...@@ -184,7 +184,7 @@ const AliveMarker = struct {
184184
185 fn markAlive(self: *AliveMarker, result_id: ResultId) BinaryModule.ParseError!void {185 fn markAlive(self: *AliveMarker, result_id: ResultId) BinaryModule.ParseError!void {
186 const index = self.info.result_id_to_code_offset.getIndex(result_id) orelse {186 const index = self.info.result_id_to_code_offset.getIndex(result_id) orelse {
187 log.err("undefined result-id {}", .{result_id});187 log.err("undefined result-id {f}", .{result_id});
188 return error.InvalidId;188 return error.InvalidId;
189 };189 };
190190
src/link/Wasm.zig+10-19
...@@ -547,7 +547,7 @@ pub const SourceLocation = enum(u32) {...@@ -547,7 +547,7 @@ pub const SourceLocation = enum(u32) {
547 switch (sl.unpack(wasm)) {547 switch (sl.unpack(wasm)) {
548 .none => unreachable,548 .none => unreachable,
549 .zig_object_nofile => diags.addError("zig compilation unit: " ++ f, args),549 .zig_object_nofile => diags.addError("zig compilation unit: " ++ f, args),
550 .object_index => |i| diags.addError("{}: " ++ f, .{i.ptr(wasm).path} ++ args),550 .object_index => |i| diags.addError("{f}: " ++ f, .{i.ptr(wasm).path} ++ args),
551 .source_location_index => @panic("TODO"),551 .source_location_index => @panic("TODO"),
552 }552 }
553 }553 }
...@@ -579,9 +579,9 @@ pub const SourceLocation = enum(u32) {...@@ -579,9 +579,9 @@ pub const SourceLocation = enum(u32) {
579 .object_index => |i| {579 .object_index => |i| {
580 const obj = i.ptr(wasm);580 const obj = i.ptr(wasm);
581 return if (obj.archive_member_name.slice(wasm)) |obj_name|581 return if (obj.archive_member_name.slice(wasm)) |obj_name|
582 try bundle.printString("{} ({s}): {s}", .{ obj.path, std.fs.path.basename(obj_name), msg })582 try bundle.printString("{f} ({s}): {s}", .{ obj.path, std.fs.path.basename(obj_name), msg })
583 else583 else
584 try bundle.printString("{}: {s}", .{ obj.path, msg });584 try bundle.printString("{f}: {s}", .{ obj.path, msg });
585 },585 },
586 .source_location_index => @panic("TODO"),586 .source_location_index => @panic("TODO"),
587 };587 };
...@@ -2126,14 +2126,7 @@ pub const FunctionType = extern struct {...@@ -2126,14 +2126,7 @@ pub const FunctionType = extern struct {
2126 wasm: *const Wasm,2126 wasm: *const Wasm,
2127 ft: FunctionType,2127 ft: FunctionType,
21282128
2129 pub fn format(2129 pub fn format(self: Formatter, writer: *std.io.Writer) std.io.Writer.Error!void {
2130 self: Formatter,
2131 comptime format_string: []const u8,
2132 options: std.fmt.FormatOptions,
2133 writer: anytype,
2134 ) !void {
2135 if (format_string.len != 0) std.fmt.invalidFmtError(format_string, self);
2136 _ = options;
2137 const params = self.ft.params.slice(self.wasm);2130 const params = self.ft.params.slice(self.wasm);
2138 const returns = self.ft.returns.slice(self.wasm);2131 const returns = self.ft.returns.slice(self.wasm);
21392132
...@@ -2912,9 +2905,7 @@ pub const Feature = packed struct(u8) {...@@ -2912,9 +2905,7 @@ pub const Feature = packed struct(u8) {
2912 @"=",2905 @"=",
2913 };2906 };
29142907
2915 pub fn format(feature: Feature, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void {2908 pub fn format(feature: Feature, writer: *std.io.Writer) std.io.Writer.Error!void {
2916 _ = opt;
2917 _ = fmt;
2918 try writer.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) });2909 try writer.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) });
2919 }2910 }
29202911
...@@ -3036,7 +3027,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {...@@ -3036,7 +3027,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {
3036}3027}
30373028
3038fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {3029fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
3039 log.debug("parseObject {}", .{obj.path});3030 log.debug("parseObject {f}", .{obj.path});
3040 const gpa = wasm.base.comp.gpa;3031 const gpa = wasm.base.comp.gpa;
3041 const gc_sections = wasm.base.gc_sections;3032 const gc_sections = wasm.base.gc_sections;
30423033
...@@ -3060,7 +3051,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {...@@ -3060,7 +3051,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
3060}3051}
30613052
3062fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {3053fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
3063 log.debug("parseArchive {}", .{obj.path});3054 log.debug("parseArchive {f}", .{obj.path});
3064 const gpa = wasm.base.comp.gpa;3055 const gpa = wasm.base.comp.gpa;
3065 const gc_sections = wasm.base.gc_sections;3056 const gc_sections = wasm.base.gc_sections;
30663057
...@@ -3196,7 +3187,7 @@ pub fn updateFunc(...@@ -3196,7 +3187,7 @@ pub fn updateFunc(
3196 const is_obj = zcu.comp.config.output_mode == .Obj;3187 const is_obj = zcu.comp.config.output_mode == .Obj;
3197 const target = &zcu.comp.root_mod.resolved_target.result;3188 const target = &zcu.comp.root_mod.resolved_target.result;
3198 const owner_nav = zcu.funcInfo(func_index).owner_nav;3189 const owner_nav = zcu.funcInfo(func_index).owner_nav;
3199 log.debug("updateFunc {}", .{ip.getNav(owner_nav).fqn.fmt(ip)});3190 log.debug("updateFunc {f}", .{ip.getNav(owner_nav).fqn.fmt(ip)});
32003191
3201 // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`,3192 // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`,
3202 // after garbage collection, which can affect function and global indexes, which affects the3193 // after garbage collection, which can affect function and global indexes, which affects the
...@@ -3307,7 +3298,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -3307,7 +3298,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
3307 .variable => |variable| .{ variable.init, variable.owner_nav },3298 .variable => |variable| .{ variable.init, variable.owner_nav },
3308 else => .{ nav.status.fully_resolved.val, nav_index },3299 else => .{ nav.status.fully_resolved.val, nav_index },
3309 };3300 };
3310 //log.debug("updateNav {} {d}", .{ nav.fqn.fmt(ip), chased_nav_index });3301 //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), chased_nav_index });
3311 assert(!wasm.imports.contains(chased_nav_index));3302 assert(!wasm.imports.contains(chased_nav_index));
33123303
3313 if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {3304 if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {
...@@ -4347,7 +4338,7 @@ fn resolveFunctionSynthetic(...@@ -4347,7 +4338,7 @@ fn resolveFunctionSynthetic(
4347 });4338 });
4348 if (import.type != correct_func_type) {4339 if (import.type != correct_func_type) {
4349 const diags = &wasm.base.comp.link_diags;4340 const diags = &wasm.base.comp.link_diags;
4350 return import.source_location.fail(diags, "synthetic function {s} {} imported with incorrect signature {}", .{4341 return import.source_location.fail(diags, "synthetic function {s} {f} imported with incorrect signature {f}", .{
4351 @tagName(res), correct_func_type.fmt(wasm), import.type.fmt(wasm),4342 @tagName(res), correct_func_type.fmt(wasm), import.type.fmt(wasm),
4352 });4343 });
4353 }4344 }
src/link/Wasm/Flush.zig+4-10
...@@ -534,7 +534,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -534,7 +534,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
534 wasm.memories.limits.max = @intCast(max_memory / page_size);534 wasm.memories.limits.max = @intCast(max_memory / page_size);
535 wasm.memories.limits.flags.has_max = true;535 wasm.memories.limits.flags.has_max = true;
536 if (shared_memory) wasm.memories.limits.flags.is_shared = true;536 if (shared_memory) wasm.memories.limits.flags.is_shared = true;
537 log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max});537 log.debug("maximum memory pages: {d}", .{wasm.memories.limits.max});
538 }538 }
539 f.memory_layout_finished = true;539 f.memory_layout_finished = true;
540540
...@@ -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/Wasm/Object.zig+7-7
...@@ -856,7 +856,7 @@ pub fn parse(...@@ -856,7 +856,7 @@ pub fn parse(
856 start_function = @enumFromInt(functions_start + index);856 start_function = @enumFromInt(functions_start + index);
857 },857 },
858 .element => {858 .element => {
859 log.warn("unimplemented: element section in {} {?s}", .{ path, archive_member_name });859 log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name });
860 pos = section_end;860 pos = section_end;
861 },861 },
862 .code => {862 .code => {
...@@ -984,10 +984,10 @@ pub fn parse(...@@ -984,10 +984,10 @@ pub fn parse(
984 if (gop.value_ptr.type != fn_ty_index) {984 if (gop.value_ptr.type != fn_ty_index) {
985 var err = try diags.addErrorWithNotes(2);985 var err = try diags.addErrorWithNotes(2);
986 try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)});986 try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)});
987 gop.value_ptr.source_location.addNote(&err, "imported as {} here", .{987 gop.value_ptr.source_location.addNote(&err, "imported as {f} here", .{
988 gop.value_ptr.type.fmt(wasm),988 gop.value_ptr.type.fmt(wasm),
989 });989 });
990 source_location.addNote(&err, "imported as {} here", .{fn_ty_index.fmt(wasm)});990 source_location.addNote(&err, "imported as {f} here", .{fn_ty_index.fmt(wasm)});
991 continue;991 continue;
992 }992 }
993 if (gop.value_ptr.module_name != ptr.module_name.toOptional()) {993 if (gop.value_ptr.module_name != ptr.module_name.toOptional()) {
...@@ -1155,11 +1155,11 @@ pub fn parse(...@@ -1155,11 +1155,11 @@ pub fn parse(
1155 if (gop.value_ptr.type != ptr.type_index) {1155 if (gop.value_ptr.type != ptr.type_index) {
1156 var err = try diags.addErrorWithNotes(2);1156 var err = try diags.addErrorWithNotes(2);
1157 try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)});1157 try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)});
1158 gop.value_ptr.source_location.addNote(&err, "exported as {} here", .{1158 gop.value_ptr.source_location.addNote(&err, "exported as {f} here", .{
1159 ptr.type_index.fmt(wasm),1159 ptr.type_index.fmt(wasm),
1160 });1160 });
1161 const word = if (gop.value_ptr.resolution == .unresolved) "imported" else "exported";1161 const word = if (gop.value_ptr.resolution == .unresolved) "imported" else "exported";
1162 source_location.addNote(&err, "{s} as {} here", .{ word, gop.value_ptr.type.fmt(wasm) });1162 source_location.addNote(&err, "{s} as {f} here", .{ word, gop.value_ptr.type.fmt(wasm) });
1163 continue;1163 continue;
1164 }1164 }
1165 if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) {1165 if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) {
...@@ -1176,8 +1176,8 @@ pub fn parse(...@@ -1176,8 +1176,8 @@ pub fn parse(
1176 }1176 }
1177 var err = try diags.addErrorWithNotes(2);1177 var err = try diags.addErrorWithNotes(2);
1178 try err.addMsg("symbol collision: {s}", .{name.slice(wasm)});1178 try err.addMsg("symbol collision: {s}", .{name.slice(wasm)});
1179 gop.value_ptr.source_location.addNote(&err, "exported as {} here", .{ptr.type_index.fmt(wasm)});1179 gop.value_ptr.source_location.addNote(&err, "exported as {f} here", .{ptr.type_index.fmt(wasm)});
1180 source_location.addNote(&err, "exported as {} here", .{gop.value_ptr.type.fmt(wasm)});1180 source_location.addNote(&err, "exported as {f} here", .{gop.value_ptr.type.fmt(wasm)});
1181 continue;1181 continue;
1182 } else {1182 } else {
1183 gop.value_ptr.* = .{1183 gop.value_ptr.* = .{
src/link/table_section.zig+1-8
...@@ -39,14 +39,7 @@ pub fn TableSection(comptime Entry: type) type {...@@ -39,14 +39,7 @@ pub fn TableSection(comptime Entry: type) type {
39 return self.entries.items.len;39 return self.entries.items.len;
40 }40 }
4141
42 pub fn format(42 pub fn format(self: Self, writer: *std.io.Writer) std.io.Writer.Error!void {
43 self: Self,
44 comptime unused_format_string: []const u8,
45 options: std.fmt.FormatOptions,
46 writer: anytype,
47 ) !void {
48 _ = options;
49 comptime assert(unused_format_string.len == 0);
50 try writer.writeAll("TableSection:\n");43 try writer.writeAll("TableSection:\n");
51 for (self.entries.items, 0..) |entry, i| {44 for (self.entries.items, 0..) |entry, i| {
52 try writer.print(" {d} => {}\n", .{ i, entry });45 try writer.print(" {d} => {}\n", .{ i, entry });
src/link/tapi/parse.zig+10-43
...@@ -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) 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),
68 }63 }
69 }64 }
7065
...@@ -86,24 +81,17 @@ pub const Node = struct {...@@ -86,24 +81,17 @@ pub const Node = struct {
86 }81 }
87 }82 }
8883
89 pub fn format(84 pub fn format(self: *const Doc, writer: *std.io.Writer) std.io.Writer.Error!void {
90 self: *const Doc,
91 comptime fmt: []const u8,
92 options: std.fmt.FormatOptions,
93 writer: anytype,
94 ) !void {
95 _ = options;
96 _ = fmt;
97 if (self.directive) |id| {85 if (self.directive) |id| {
98 try std.fmt.format(writer, "{{ ", .{});86 try writer.print("{{ ", .{});
99 const directive = self.base.tree.getRaw(id, id);87 const directive = self.base.tree.getRaw(id, id);
100 try std.fmt.format(writer, ".directive = {s}, ", .{directive});88 try writer.print(".directive = {s}, ", .{directive});
101 }89 }
102 if (self.value) |node| {90 if (self.value) |node| {
103 try std.fmt.format(writer, "{}", .{node});91 try writer.print("{}", .{node});
104 }92 }
105 if (self.directive != null) {93 if (self.directive != null) {
106 try std.fmt.format(writer, " }}", .{});94 try writer.print(" }}", .{});
107 }95 }
108 }96 }
109 };97 };
...@@ -133,14 +121,7 @@ pub const Node = struct {...@@ -133,14 +121,7 @@ pub const Node = struct {
133 self.values.deinit(allocator);121 self.values.deinit(allocator);
134 }122 }
135123
136 pub fn format(124 pub fn format(self: *const Map, writer: *std.io.Writer) std.io.Writer.Error!void {
137 self: *const Map,
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, "{{ ", .{});125 try std.fmt.format(writer, "{{ ", .{});
145 for (self.values.items) |entry| {126 for (self.values.items) |entry| {
146 const key = self.base.tree.getRaw(entry.key, entry.key);127 const key = self.base.tree.getRaw(entry.key, entry.key);
...@@ -172,14 +153,7 @@ pub const Node = struct {...@@ -172,14 +153,7 @@ pub const Node = struct {
172 self.values.deinit(allocator);153 self.values.deinit(allocator);
173 }154 }
174155
175 pub fn format(156 pub fn format(self: *const List, writer: *std.io.Writer) std.io.Writer.Error!void {
176 self: *const List,
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, "[ ", .{});157 try std.fmt.format(writer, "[ ", .{});
184 for (self.values.items) |node| {158 for (self.values.items) |node| {
185 try std.fmt.format(writer, "{}, ", .{node});159 try std.fmt.format(writer, "{}, ", .{node});
...@@ -203,14 +177,7 @@ pub const Node = struct {...@@ -203,14 +177,7 @@ pub const Node = struct {
203 self.string_value.deinit(allocator);177 self.string_value.deinit(allocator);
204 }178 }
205179
206 pub fn format(180 pub fn format(self: *const Value, writer: *std.io.Writer) std.io.Writer.Error!void {
207 self: *const Value,
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);181 const raw = self.base.tree.getRaw(self.base.start, self.base.end);
215 return std.fmt.format(writer, "{s}", .{raw});182 return std.fmt.format(writer, "{s}", .{raw});
216 }183 }
src/main.zig+108-99
...@@ -65,6 +65,9 @@ pub fn wasi_cwd() std.os.wasi.fd_t {...@@ -65,6 +65,9 @@ pub fn wasi_cwd() std.os.wasi.fd_t {
6565
66const fatal = std.process.fatal;66const fatal = std.process.fatal;
6767
68/// This can be global since stdout is a singleton.
69var stdio_buffer: [4096]u8 = undefined;
70
68/// Shaming all the locations that inappropriately use an O(N) search algorithm.71/// Shaming all the locations that inappropriately use an O(N) search algorithm.
69/// Please delete this and fix the compilation errors!72/// Please delete this and fix the compilation errors!
70pub const @"bad O(N)" = void;73pub const @"bad O(N)" = void;
...@@ -340,11 +343,11 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -340,11 +343,11 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
340 } else if (mem.eql(u8, cmd, "targets")) {343 } else if (mem.eql(u8, cmd, "targets")) {
341 dev.check(.targets_command);344 dev.check(.targets_command);
342 const host = std.zig.resolveTargetQueryOrFatal(.{});345 const host = std.zig.resolveTargetQueryOrFatal(.{});
343 const stdout = io.getStdOut().writer();346 const stdout = fs.File.stdout().deprecatedWriter();
344 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host);347 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host);
345 } else if (mem.eql(u8, cmd, "version")) {348 } else if (mem.eql(u8, cmd, "version")) {
346 dev.check(.version_command);349 dev.check(.version_command);
347 try std.io.getStdOut().writeAll(build_options.version ++ "\n");350 try fs.File.stdout().writeAll(build_options.version ++ "\n");
348 // Check libc++ linkage to make sure Zig was built correctly, but only351 // Check libc++ linkage to make sure Zig was built correctly, but only
349 // for "env" and "version" to avoid affecting the startup time for352 // for "env" and "version" to avoid affecting the startup time for
350 // build-critical commands (check takes about ~10 μs)353 // build-critical commands (check takes about ~10 μs)
...@@ -352,7 +355,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -352,7 +355,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
352 } else if (mem.eql(u8, cmd, "env")) {355 } else if (mem.eql(u8, cmd, "env")) {
353 dev.check(.env_command);356 dev.check(.env_command);
354 verifyLibcxxCorrectlyLinked();357 verifyLibcxxCorrectlyLinked();
355 return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());358 return @import("print_env.zig").cmdEnv(arena, cmd_args);
356 } else if (mem.eql(u8, cmd, "reduce")) {359 } else if (mem.eql(u8, cmd, "reduce")) {
357 return jitCmd(gpa, arena, cmd_args, .{360 return jitCmd(gpa, arena, cmd_args, .{
358 .cmd_name = "reduce",361 .cmd_name = "reduce",
...@@ -360,10 +363,10 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -360,10 +363,10 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
360 });363 });
361 } else if (mem.eql(u8, cmd, "zen")) {364 } else if (mem.eql(u8, cmd, "zen")) {
362 dev.check(.zen_command);365 dev.check(.zen_command);
363 return io.getStdOut().writeAll(info_zen);366 return fs.File.stdout().writeAll(info_zen);
364 } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {367 } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {
365 dev.check(.help_command);368 dev.check(.help_command);
366 return io.getStdOut().writeAll(usage);369 return fs.File.stdout().writeAll(usage);
367 } else if (mem.eql(u8, cmd, "ast-check")) {370 } else if (mem.eql(u8, cmd, "ast-check")) {
368 return cmdAstCheck(arena, cmd_args);371 return cmdAstCheck(arena, cmd_args);
369 } else if (mem.eql(u8, cmd, "detect-cpu")) {372 } else if (mem.eql(u8, cmd, "detect-cpu")) {
...@@ -1038,7 +1041,7 @@ fn buildOutputType(...@@ -1038,7 +1041,7 @@ fn buildOutputType(
1038 };1041 };
1039 } else if (mem.startsWith(u8, arg, "-")) {1042 } else if (mem.startsWith(u8, arg, "-")) {
1040 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {1043 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
1041 try io.getStdOut().writeAll(usage_build_generic);1044 try fs.File.stdout().writeAll(usage_build_generic);
1042 return cleanExit();1045 return cleanExit();
1043 } else if (mem.eql(u8, arg, "--")) {1046 } else if (mem.eql(u8, arg, "--")) {
1044 if (arg_mode == .run) {1047 if (arg_mode == .run) {
...@@ -1806,6 +1809,7 @@ fn buildOutputType(...@@ -1806,6 +1809,7 @@ fn buildOutputType(
1806 } else manifest_file = arg;1809 } else manifest_file = arg;
1807 },1810 },
1808 .assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => {1811 .assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => {
1812 dev.check(.c_compiler);
1809 try create_module.c_source_files.append(arena, .{1813 try create_module.c_source_files.append(arena, .{
1810 // Populated after module creation.1814 // Populated after module creation.
1811 .owner = undefined,1815 .owner = undefined,
...@@ -1816,6 +1820,7 @@ fn buildOutputType(...@@ -1816,6 +1820,7 @@ fn buildOutputType(
1816 });1820 });
1817 },1821 },
1818 .rc => {1822 .rc => {
1823 dev.check(.win32_resource);
1819 try create_module.rc_source_files.append(arena, .{1824 try create_module.rc_source_files.append(arena, .{
1820 // Populated after module creation.1825 // Populated after module creation.
1821 .owner = undefined,1826 .owner = undefined,
...@@ -2766,9 +2771,9 @@ fn buildOutputType(...@@ -2766,9 +2771,9 @@ fn buildOutputType(
2766 } else if (mem.eql(u8, arg, "-V")) {2771 } else if (mem.eql(u8, arg, "-V")) {
2767 warn("ignoring request for supported emulations: unimplemented", .{});2772 warn("ignoring request for supported emulations: unimplemented", .{});
2768 } else if (mem.eql(u8, arg, "-v")) {2773 } else if (mem.eql(u8, arg, "-v")) {
2769 try std.io.getStdOut().writeAll("zig ld " ++ build_options.version ++ "\n");2774 try fs.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n");
2770 } else if (mem.eql(u8, arg, "--version")) {2775 } else if (mem.eql(u8, arg, "--version")) {
2771 try std.io.getStdOut().writeAll("zig ld " ++ build_options.version ++ "\n");2776 try fs.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n");
2772 process.exit(0);2777 process.exit(0);
2773 } else {2778 } else {
2774 fatal("unsupported linker arg: {s}", .{arg});2779 fatal("unsupported linker arg: {s}", .{arg});
...@@ -3301,6 +3306,7 @@ fn buildOutputType(...@@ -3301,6 +3306,7 @@ fn buildOutputType(
3301 defer thread_pool.deinit();3306 defer thread_pool.deinit();
33023307
3303 for (create_module.c_source_files.items) |*src| {3308 for (create_module.c_source_files.items) |*src| {
3309 dev.check(.c_compiler);
3304 if (!mem.eql(u8, src.src_path, "-")) continue;3310 if (!mem.eql(u8, src.src_path, "-")) continue;
33053311
3306 const ext = src.ext orelse3312 const ext = src.ext orelse
...@@ -3325,17 +3331,20 @@ fn buildOutputType(...@@ -3325,17 +3331,20 @@ fn buildOutputType(
3325 // for the hashing algorithm here and in the cache are the same.3331 // for the hashing algorithm here and in the cache are the same.
3326 // We are providing our own cache key, because this file has nothing3332 // We are providing our own cache key, because this file has nothing
3327 // to do with the cache manifest.3333 // to do with the cache manifest.
3328 var hasher = Cache.Hasher.init("0123456789abcdef");3334 var file_writer = f.writer(&.{});
3329 var w = io.multiWriter(.{ f.writer(), hasher.writer() });3335 var buffer: [1000]u8 = undefined;
3330 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();3336 var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer);
3331 try fifo.pump(io.getStdIn().reader(), w.writer());3337 var stdin_reader = fs.File.stdin().readerStreaming(&.{});
3338 _ = hasher.writer.sendFileAll(&stdin_reader, .unlimited) catch |err| switch (err) {
3339 error.WriteFailed => fatal("failed to write {s}: {t}", .{ dump_path, file_writer.err.? }),
3340 else => fatal("failed to pipe stdin to {s}: {t}", .{ dump_path, err }),
3341 };
3342 try hasher.writer.flush();
33323343
3333 var bin_digest: Cache.BinDigest = undefined;3344 const bin_digest: Cache.BinDigest = hasher.hasher.finalResult();
3334 hasher.final(&bin_digest);
33353345
3336 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{s}-stdin{s}", .{3346 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
3337 std.fmt.fmtSliceHexLower(&bin_digest),3347 &bin_digest, ext.canonicalName(target),
3338 ext.canonicalName(target),
3339 });3348 });
3340 try dirs.local_cache.handle.rename(dump_path, sub_path);3349 try dirs.local_cache.handle.rename(dump_path, sub_path);
33413350
...@@ -3506,7 +3515,7 @@ fn buildOutputType(...@@ -3506,7 +3515,7 @@ fn buildOutputType(
3506 if (t.arch == target.cpu.arch and t.os == target.os.tag) {3515 if (t.arch == target.cpu.arch and t.os == target.os.tag) {
3507 // If there's a `glibc_min`, there's also an `os_ver`.3516 // If there's a `glibc_min`, there's also an `os_ver`.
3508 if (t.glibc_min) |glibc_min| {3517 if (t.glibc_min) |glibc_min| {
3509 std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}.{d}.{d}", .{3518 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{
3510 @tagName(t.arch),3519 @tagName(t.arch),
3511 @tagName(t.os),3520 @tagName(t.os),
3512 t.os_ver.?,3521 t.os_ver.?,
...@@ -3515,7 +3524,7 @@ fn buildOutputType(...@@ -3515,7 +3524,7 @@ fn buildOutputType(
3515 glibc_min.minor,3524 glibc_min.minor,
3516 });3525 });
3517 } else if (t.os_ver) |os_ver| {3526 } else if (t.os_ver) |os_ver| {
3518 std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}", .{3527 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{
3519 @tagName(t.arch),3528 @tagName(t.arch),
3520 @tagName(t.os),3529 @tagName(t.os),
3521 os_ver,3530 os_ver,
...@@ -3546,15 +3555,15 @@ fn buildOutputType(...@@ -3546,15 +3555,15 @@ fn buildOutputType(
3546 if (show_builtin) {3555 if (show_builtin) {
3547 const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config);3556 const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config);
3548 const source = try builtin_opts.generate(arena);3557 const source = try builtin_opts.generate(arena);
3549 return std.io.getStdOut().writeAll(source);3558 return fs.File.stdout().writeAll(source);
3550 }3559 }
3551 switch (listen) {3560 switch (listen) {
3552 .none => {},3561 .none => {},
3553 .stdio => {3562 .stdio => {
3554 try serve(3563 try serve(
3555 comp,3564 comp,
3556 std.io.getStdIn(),3565 .stdin(),
3557 std.io.getStdOut(),3566 .stdout(),
3558 test_exec_args.items,3567 test_exec_args.items,
3559 self_exe_path,3568 self_exe_path,
3560 arg_mode,3569 arg_mode,
...@@ -4606,7 +4615,7 @@ fn cmdTranslateC(...@@ -4606,7 +4615,7 @@ fn cmdTranslateC(
4606 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });4615 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });
4607 };4616 };
4608 defer zig_file.close();4617 defer zig_file.close();
4609 try io.getStdOut().writeFileAll(zig_file, .{});4618 try fs.File.stdout().writeFileAll(zig_file, .{});
4610 return cleanExit();4619 return cleanExit();
4611 }4620 }
4612}4621}
...@@ -4636,7 +4645,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4636,7 +4645,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4636 if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip")) {4645 if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip")) {
4637 strip = true;4646 strip = true;
4638 } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {4647 } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
4639 try io.getStdOut().writeAll(usage_init);4648 try fs.File.stdout().writeAll(usage_init);
4640 return cleanExit();4649 return cleanExit();
4641 } else {4650 } else {
4642 fatal("unrecognized parameter: '{s}'", .{arg});4651 fatal("unrecognized parameter: '{s}'", .{arg});
...@@ -5287,7 +5296,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5287,7 +5296,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5287 const s = fs.path.sep_str;5296 const s = fs.path.sep_str;
5288 const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce;5297 const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce;
5289 const stdout = dirs.local_cache.handle.readFileAlloc(arena, tmp_sub_path, 50 * 1024 * 1024) catch |err| {5298 const stdout = dirs.local_cache.handle.readFileAlloc(arena, tmp_sub_path, 50 * 1024 * 1024) catch |err| {
5290 fatal("unable to read results of configure phase from '{}{s}': {s}", .{5299 fatal("unable to read results of configure phase from '{f}{s}': {s}", .{
5291 dirs.local_cache, tmp_sub_path, @errorName(err),5300 dirs.local_cache, tmp_sub_path, @errorName(err),
5292 });5301 });
5293 };5302 };
...@@ -5481,8 +5490,8 @@ fn jitCmd(...@@ -5481,8 +5490,8 @@ fn jitCmd(
5481 defer comp.destroy();5490 defer comp.destroy();
54825491
5483 if (options.server) {5492 if (options.server) {
5484 var server = std.zig.Server{5493 var server: std.zig.Server = .{
5485 .out = std.io.getStdOut(),5494 .out = fs.File.stdout(),
5486 .in = undefined, // won't be receiving messages5495 .in = undefined, // won't be receiving messages
5487 .receive_fifo = undefined, // won't be receiving messages5496 .receive_fifo = undefined, // won't be receiving messages
5488 };5497 };
...@@ -6015,7 +6024,7 @@ fn cmdAstCheck(...@@ -6015,7 +6024,7 @@ fn cmdAstCheck(
6015 const arg = args[i];6024 const arg = args[i];
6016 if (mem.startsWith(u8, arg, "-")) {6025 if (mem.startsWith(u8, arg, "-")) {
6017 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6026 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6018 try io.getStdOut().writeAll(usage_ast_check);6027 try fs.File.stdout().writeAll(usage_ast_check);
6019 return cleanExit();6028 return cleanExit();
6020 } else if (mem.eql(u8, arg, "-t")) {6029 } else if (mem.eql(u8, arg, "-t")) {
6021 want_output_text = true;6030 want_output_text = true;
...@@ -6046,7 +6055,7 @@ fn cmdAstCheck(...@@ -6046,7 +6055,7 @@ fn cmdAstCheck(
6046 break :file fs.cwd().openFile(p, .{}) catch |err| {6055 break :file fs.cwd().openFile(p, .{}) catch |err| {
6047 fatal("unable to open file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });6056 fatal("unable to open file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
6048 };6057 };
6049 } else io.getStdIn();6058 } else fs.File.stdin();
6050 defer if (zig_source_path != null) f.close();6059 defer if (zig_source_path != null) f.close();
6051 break :s std.zig.readSourceFileToEndAlloc(arena, f, null) catch |err| {6060 break :s std.zig.readSourceFileToEndAlloc(arena, f, null) catch |err| {
6052 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });6061 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
...@@ -6065,6 +6074,8 @@ fn cmdAstCheck(...@@ -6065,6 +6074,8 @@ fn cmdAstCheck(
60656074
6066 const tree = try Ast.parse(arena, source, mode);6075 const tree = try Ast.parse(arena, source, mode);
60676076
6077 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
6078 const stdout_bw = &stdout_writer.interface;
6068 switch (mode) {6079 switch (mode) {
6069 .zig => {6080 .zig => {
6070 const zir = try AstGen.generate(arena, tree);6081 const zir = try AstGen.generate(arena, tree);
...@@ -6107,31 +6118,30 @@ fn cmdAstCheck(...@@ -6107,31 +6118,30 @@ fn cmdAstCheck(
6107 const extra_bytes = zir.extra.len * @sizeOf(u32);6118 const extra_bytes = zir.extra.len * @sizeOf(u32);
6108 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +6119 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
6109 zir.string_bytes.len * @sizeOf(u8);6120 zir.string_bytes.len * @sizeOf(u8);
6110 const stdout = io.getStdOut();
6111 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
6112 // zig fmt: off6121 // zig fmt: off
6113 try stdout.writer().print(6122 try stdout_bw.print(
6114 \\# Source bytes: {}6123 \\# Source bytes: {Bi}
6115 \\# Tokens: {} ({})6124 \\# Tokens: {} ({Bi})
6116 \\# AST Nodes: {} ({})6125 \\# AST Nodes: {} ({Bi})
6117 \\# Total ZIR bytes: {}6126 \\# Total ZIR bytes: {Bi}
6118 \\# Instructions: {d} ({})6127 \\# Instructions: {d} ({Bi})
6119 \\# String Table Bytes: {}6128 \\# String Table Bytes: {}
6120 \\# Extra Data Items: {d} ({})6129 \\# Extra Data Items: {d} ({Bi})
6121 \\6130 \\
6122 , .{6131 , .{
6123 fmtIntSizeBin(source.len),6132 source.len,
6124 tree.tokens.len, fmtIntSizeBin(token_bytes),6133 tree.tokens.len, token_bytes,
6125 tree.nodes.len, fmtIntSizeBin(tree_bytes),6134 tree.nodes.len, tree_bytes,
6126 fmtIntSizeBin(total_bytes),6135 total_bytes,
6127 zir.instructions.len, fmtIntSizeBin(instruction_bytes),6136 zir.instructions.len, instruction_bytes,
6128 fmtIntSizeBin(zir.string_bytes.len),6137 zir.string_bytes.len,
6129 zir.extra.len, fmtIntSizeBin(extra_bytes),6138 zir.extra.len, extra_bytes,
6130 });6139 });
6131 // zig fmt: on6140 // zig fmt: on
6132 }6141 }
61336142
6134 try @import("print_zir.zig").renderAsTextToFile(arena, tree, zir, io.getStdOut());6143 try @import("print_zir.zig").renderAsText(arena, tree, zir, stdout_bw);
6144 try stdout_bw.flush();
61356145
6136 if (zir.hasCompileErrors()) {6146 if (zir.hasCompileErrors()) {
6137 process.exit(1);6147 process.exit(1);
...@@ -6158,7 +6168,8 @@ fn cmdAstCheck(...@@ -6158,7 +6168,8 @@ fn cmdAstCheck(
6158 fatal("-t option only available in builds of zig with debug extensions", .{});6168 fatal("-t option only available in builds of zig with debug extensions", .{});
6159 }6169 }
61606170
6161 try @import("print_zoir.zig").renderToFile(zoir, arena, io.getStdOut());6171 try @import("print_zoir.zig").renderToWriter(zoir, arena, stdout_bw);
6172 try stdout_bw.flush();
6162 return cleanExit();6173 return cleanExit();
6163 },6174 },
6164 }6175 }
...@@ -6186,8 +6197,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {...@@ -6186,8 +6197,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {
6186 const arg = args[i];6197 const arg = args[i];
6187 if (mem.startsWith(u8, arg, "-")) {6198 if (mem.startsWith(u8, arg, "-")) {
6188 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6199 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6189 const stdout = io.getStdOut().writer();6200 try fs.File.stdout().writeAll(detect_cpu_usage);
6190 try stdout.writeAll(detect_cpu_usage);
6191 return cleanExit();6201 return cleanExit();
6192 } else if (mem.eql(u8, arg, "--llvm")) {6202 } else if (mem.eql(u8, arg, "--llvm")) {
6193 use_llvm = true;6203 use_llvm = true;
...@@ -6279,11 +6289,11 @@ fn detectNativeCpuWithLLVM(...@@ -6279,11 +6289,11 @@ fn detectNativeCpuWithLLVM(
6279}6289}
62806290
6281fn printCpu(cpu: std.Target.Cpu) !void {6291fn printCpu(cpu: std.Target.Cpu) !void {
6282 var bw = io.bufferedWriter(io.getStdOut().writer());6292 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
6283 const stdout = bw.writer();6293 const stdout_bw = &stdout_writer.interface;
62846294
6285 if (cpu.model.llvm_name) |llvm_name| {6295 if (cpu.model.llvm_name) |llvm_name| {
6286 try stdout.print("{s}\n", .{llvm_name});6296 try stdout_bw.print("{s}\n", .{llvm_name});
6287 }6297 }
62886298
6289 const all_features = cpu.arch.allFeaturesList();6299 const all_features = cpu.arch.allFeaturesList();
...@@ -6292,10 +6302,10 @@ fn printCpu(cpu: std.Target.Cpu) !void {...@@ -6292,10 +6302,10 @@ fn printCpu(cpu: std.Target.Cpu) !void {
6292 const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);6302 const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);
6293 const is_enabled = cpu.features.isEnabled(index);6303 const is_enabled = cpu.features.isEnabled(index);
6294 const plus_or_minus = "-+"[@intFromBool(is_enabled)];6304 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
6295 try stdout.print("{c}{s}\n", .{ plus_or_minus, llvm_name });6305 try stdout_bw.print("{c}{s}\n", .{ plus_or_minus, llvm_name });
6296 }6306 }
62976307
6298 try bw.flush();6308 try stdout_bw.flush();
6299}6309}
63006310
6301fn cmdDumpLlvmInts(6311fn cmdDumpLlvmInts(
...@@ -6328,16 +6338,14 @@ fn cmdDumpLlvmInts(...@@ -6328,16 +6338,14 @@ fn cmdDumpLlvmInts(
6328 const dl = tm.createTargetDataLayout();6338 const dl = tm.createTargetDataLayout();
6329 const context = llvm.Context.create();6339 const context = llvm.Context.create();
63306340
6331 var bw = io.bufferedWriter(io.getStdOut().writer());6341 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
6332 const stdout = bw.writer();6342 const stdout_bw = &stdout_writer.interface;
6333
6334 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {6343 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
6335 const int_type = context.intType(bits);6344 const int_type = context.intType(bits);
6336 const alignment = dl.abiAlignmentOfType(int_type);6345 const alignment = dl.abiAlignmentOfType(int_type);
6337 try stdout.print("LLVMABIAlignmentOfType(i{d}) == {d}\n", .{ bits, alignment });6346 try stdout_bw.print("LLVMABIAlignmentOfType(i{d}) == {d}\n", .{ bits, alignment });
6338 }6347 }
63396348 try stdout_bw.flush();
6340 try bw.flush();
63416349
6342 return cleanExit();6350 return cleanExit();
6343}6351}
...@@ -6359,6 +6367,8 @@ fn cmdDumpZir(...@@ -6359,6 +6367,8 @@ fn cmdDumpZir(
6359 defer f.close();6367 defer f.close();
63606368
6361 const zir = try Zcu.loadZirCache(arena, f);6369 const zir = try Zcu.loadZirCache(arena, f);
6370 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
6371 const stdout_bw = &stdout_writer.interface;
63626372
6363 {6373 {
6364 const instruction_bytes = zir.instructions.len *6374 const instruction_bytes = zir.instructions.len *
...@@ -6368,25 +6378,24 @@ fn cmdDumpZir(...@@ -6368,25 +6378,24 @@ fn cmdDumpZir(
6368 const extra_bytes = zir.extra.len * @sizeOf(u32);6378 const extra_bytes = zir.extra.len * @sizeOf(u32);
6369 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +6379 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
6370 zir.string_bytes.len * @sizeOf(u8);6380 zir.string_bytes.len * @sizeOf(u8);
6371 const stdout = io.getStdOut();
6372 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
6373 // zig fmt: off6381 // zig fmt: off
6374 try stdout.writer().print(6382 try stdout_bw.print(
6375 \\# Total ZIR bytes: {}6383 \\# Total ZIR bytes: {Bi}
6376 \\# Instructions: {d} ({})6384 \\# Instructions: {d} ({Bi})
6377 \\# String Table Bytes: {}6385 \\# String Table Bytes: {Bi}
6378 \\# Extra Data Items: {d} ({})6386 \\# Extra Data Items: {d} ({Bi})
6379 \\6387 \\
6380 , .{6388 , .{
6381 fmtIntSizeBin(total_bytes),6389 total_bytes,
6382 zir.instructions.len, fmtIntSizeBin(instruction_bytes),6390 zir.instructions.len, instruction_bytes,
6383 fmtIntSizeBin(zir.string_bytes.len),6391 zir.string_bytes.len,
6384 zir.extra.len, fmtIntSizeBin(extra_bytes),6392 zir.extra.len, extra_bytes,
6385 });6393 });
6386 // zig fmt: on6394 // zig fmt: on
6387 }6395 }
63886396
6389 return @import("print_zir.zig").renderAsTextToFile(arena, null, zir, io.getStdOut());6397 try @import("print_zir.zig").renderAsText(arena, null, zir, stdout_bw);
6398 try stdout_bw.flush();
6390}6399}
63916400
6392/// This is only enabled for debug builds.6401/// This is only enabled for debug builds.
...@@ -6444,19 +6453,19 @@ fn cmdChangelist(...@@ -6444,19 +6453,19 @@ fn cmdChangelist(
6444 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;6453 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
6445 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);6454 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
64466455
6447 var bw = io.bufferedWriter(io.getStdOut().writer());6456 var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer);
6448 const stdout = bw.writer();6457 const stdout_bw = &stdout_writer.interface;
6449 {6458 {
6450 try stdout.print("Instruction mappings:\n", .{});6459 try stdout_bw.print("Instruction mappings:\n", .{});
6451 var it = inst_map.iterator();6460 var it = inst_map.iterator();
6452 while (it.next()) |entry| {6461 while (it.next()) |entry| {
6453 try stdout.print(" %{d} => %{d}\n", .{6462 try stdout_bw.print(" %{d} => %{d}\n", .{
6454 @intFromEnum(entry.key_ptr.*),6463 @intFromEnum(entry.key_ptr.*),
6455 @intFromEnum(entry.value_ptr.*),6464 @intFromEnum(entry.value_ptr.*),
6456 });6465 });
6457 }6466 }
6458 }6467 }
6459 try bw.flush();6468 try stdout_bw.flush();
6460}6469}
64616470
6462fn eatIntPrefix(arg: []const u8, base: u8) []const u8 {6471fn eatIntPrefix(arg: []const u8, base: u8) []const u8 {
...@@ -6718,13 +6727,10 @@ fn accessFrameworkPath(...@@ -6718,13 +6727,10 @@ fn accessFrameworkPath(
67186727
6719 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {6728 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
6720 test_path.clearRetainingCapacity();6729 test_path.clearRetainingCapacity();
6721 try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{6730 try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{
6722 framework_dir_path,6731 framework_dir_path, framework_name, framework_name, ext,
6723 framework_name,
6724 framework_name,
6725 ext,
6726 });6732 });
6727 try checked_paths.writer().print("\n {s}", .{test_path.items});6733 try checked_paths.print("\n {s}", .{test_path.items});
6728 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {6734 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
6729 error.FileNotFound => continue,6735 error.FileNotFound => continue,
6730 else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{6736 else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{
...@@ -6794,8 +6800,7 @@ fn cmdFetch(...@@ -6794,8 +6800,7 @@ fn cmdFetch(
6794 const arg = args[i];6800 const arg = args[i];
6795 if (mem.startsWith(u8, arg, "-")) {6801 if (mem.startsWith(u8, arg, "-")) {
6796 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6802 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6797 const stdout = io.getStdOut().writer();6803 try fs.File.stdout().writeAll(usage_fetch);
6798 try stdout.writeAll(usage_fetch);
6799 return cleanExit();6804 return cleanExit();
6800 } else if (mem.eql(u8, arg, "--global-cache-dir")) {6805 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
6801 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});6806 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
...@@ -6908,7 +6913,9 @@ fn cmdFetch(...@@ -6908,7 +6913,9 @@ fn cmdFetch(
69086913
6909 const name = switch (save) {6914 const name = switch (save) {
6910 .no => {6915 .no => {
6911 try io.getStdOut().writer().print("{s}\n", .{package_hash_slice});6916 var stdout = fs.File.stdout().writerStreaming(&stdio_buffer);
6917 try stdout.interface.print("{s}\n", .{package_hash_slice});
6918 try stdout.interface.flush();
6912 return cleanExit();6919 return cleanExit();
6913 },6920 },
6914 .yes, .exact => |name| name: {6921 .yes, .exact => |name| name: {
...@@ -6944,7 +6951,7 @@ fn cmdFetch(...@@ -6944,7 +6951,7 @@ fn cmdFetch(
6944 var saved_path_or_url = path_or_url;6951 var saved_path_or_url = path_or_url;
69456952
6946 if (fetch.latest_commit) |latest_commit| resolved: {6953 if (fetch.latest_commit) |latest_commit| resolved: {
6947 const latest_commit_hex = try std.fmt.allocPrint(arena, "{}", .{latest_commit});6954 const latest_commit_hex = try std.fmt.allocPrint(arena, "{f}", .{latest_commit});
69486955
6949 var uri = try std.Uri.parse(path_or_url);6956 var uri = try std.Uri.parse(path_or_url);
69506957
...@@ -6957,7 +6964,9 @@ fn cmdFetch(...@@ -6957,7 +6964,9 @@ fn cmdFetch(
6957 std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex });6964 std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex });
69586965
6959 // include the original refspec in a query parameter, could be used to check for updates6966 // include the original refspec in a query parameter, could be used to check for updates
6960 uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={%}", .{fragment}) };6967 uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={f}", .{
6968 std.fmt.alt(fragment, .formatEscaped),
6969 }) };
6961 } else {6970 } else {
6962 std.log.info("resolved to commit {s}", .{latest_commit_hex});6971 std.log.info("resolved to commit {s}", .{latest_commit_hex});
6963 }6972 }
...@@ -6966,23 +6975,23 @@ fn cmdFetch(...@@ -6966,23 +6975,23 @@ fn cmdFetch(
6966 uri.fragment = .{ .raw = latest_commit_hex };6975 uri.fragment = .{ .raw = latest_commit_hex };
69676976
6968 switch (save) {6977 switch (save) {
6969 .yes => saved_path_or_url = try std.fmt.allocPrint(arena, "{}", .{uri}),6978 .yes => saved_path_or_url = try std.fmt.allocPrint(arena, "{f}", .{uri}),
6970 .no, .exact => {}, // keep the original URL6979 .no, .exact => {}, // keep the original URL
6971 }6980 }
6972 }6981 }
69736982
6974 const new_node_init = try std.fmt.allocPrint(arena,6983 const new_node_init = try std.fmt.allocPrint(arena,
6975 \\.{{6984 \\.{{
6976 \\ .url = "{}",6985 \\ .url = "{f}",
6977 \\ .hash = "{}",6986 \\ .hash = "{f}",
6978 \\ }}6987 \\ }}
6979 , .{6988 , .{
6980 std.zig.fmtEscapes(saved_path_or_url),6989 std.zig.fmtString(saved_path_or_url),
6981 std.zig.fmtEscapes(package_hash_slice),6990 std.zig.fmtString(package_hash_slice),
6982 });6991 });
69836992
6984 const new_node_text = try std.fmt.allocPrint(arena, ".{p_} = {s},\n", .{6993 const new_node_text = try std.fmt.allocPrint(arena, ".{f} = {s},\n", .{
6985 std.zig.fmtId(name), new_node_init,6994 std.zig.fmtIdPU(name), new_node_init,
6986 });6995 });
69876996
6988 const dependencies_init = try std.fmt.allocPrint(arena, ".{{\n {s} }}", .{6997 const dependencies_init = try std.fmt.allocPrint(arena, ".{{\n {s} }}", .{
...@@ -7008,13 +7017,13 @@ fn cmdFetch(...@@ -7008,13 +7017,13 @@ fn cmdFetch(
70087017
7009 const location_replace = try std.fmt.allocPrint(7018 const location_replace = try std.fmt.allocPrint(
7010 arena,7019 arena,
7011 "\"{}\"",7020 "\"{f}\"",
7012 .{std.zig.fmtEscapes(saved_path_or_url)},7021 .{std.zig.fmtString(saved_path_or_url)},
7013 );7022 );
7014 const hash_replace = try std.fmt.allocPrint(7023 const hash_replace = try std.fmt.allocPrint(
7015 arena,7024 arena,
7016 "\"{}\"",7025 "\"{f}\"",
7017 .{std.zig.fmtEscapes(package_hash_slice)},7026 .{std.zig.fmtString(package_hash_slice)},
7018 );7027 );
70197028
7020 warn("overwriting existing dependency named '{s}'", .{name});7029 warn("overwriting existing dependency named '{s}'", .{name});
src/print_env.zig+2-2
...@@ -4,7 +4,7 @@ const introspect = @import("introspect.zig");...@@ -4,7 +4,7 @@ const introspect = @import("introspect.zig");
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const fatal = std.process.fatal;5const fatal = std.process.fatal;
66
7pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void {7pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void {
8 _ = args;8 _ = args;
9 const cwd_path = try introspect.getResolvedCwd(arena);9 const cwd_path = try introspect.getResolvedCwd(arena);
10 const self_exe_path = try std.fs.selfExePathAlloc(arena);10 const self_exe_path = try std.fs.selfExePathAlloc(arena);
...@@ -21,7 +21,7 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Wr...@@ -21,7 +21,7 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Wr
21 const host = try std.zig.system.resolveTargetQuery(.{});21 const host = try std.zig.system.resolveTargetQuery(.{});
22 const triple = try host.zigTriple(arena);22 const triple = try host.zigTriple(arena);
2323
24 var bw = std.io.bufferedWriter(stdout);24 var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
25 const w = bw.writer();25 const w = bw.writer();
2626
27 var jws = std.json.writeStream(w, .{ .whitespace = .indent_1 });27 var jws = std.json.writeStream(w, .{ .whitespace = .indent_1 });
src/print_targets.zig+1-1
...@@ -64,7 +64,7 @@ pub fn cmdTargets(...@@ -64,7 +64,7 @@ pub fn cmdTargets(
64 {64 {
65 var glibc_obj = try root_obj.beginTupleField("glibc", .{});65 var glibc_obj = try root_obj.beginTupleField("glibc", .{});
66 for (glibc_abi.all_versions) |ver| {66 for (glibc_abi.all_versions) |ver| {
67 const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});67 const tmp = try std.fmt.allocPrint(allocator, "{f}", .{ver});
68 defer allocator.free(tmp);68 defer allocator.free(tmp);
69 try glibc_obj.field(tmp, .{});69 try glibc_obj.field(tmp, .{});
70 }70 }
src/print_value.zig+34-47
...@@ -20,15 +20,8 @@ pub const FormatContext = struct {...@@ -20,15 +20,8 @@ pub const FormatContext = struct {
20 depth: u8,20 depth: u8,
21};21};
2222
23pub fn formatSema(23pub fn formatSema(ctx: FormatContext, writer: *std.io.Writer) std.io.Writer.Error!void {
24 ctx: FormatContext,
25 comptime fmt: []const u8,
26 options: std.fmt.FormatOptions,
27 writer: anytype,
28) !void {
29 _ = options;
30 const sema = ctx.opt_sema.?;24 const sema = ctx.opt_sema.?;
31 comptime std.debug.assert(fmt.len == 0);
32 return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) {25 return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) {
33 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function26 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
34 error.ComptimeBreak, error.ComptimeReturn => unreachable,27 error.ComptimeBreak, error.ComptimeReturn => unreachable,
...@@ -37,15 +30,8 @@ pub fn formatSema(...@@ -37,15 +30,8 @@ pub fn formatSema(
37 };30 };
38}31}
3932
40pub fn format(33pub fn format(ctx: FormatContext, writer: *std.io.Writer) std.io.Writer.Error!void {
41 ctx: FormatContext,
42 comptime fmt: []const u8,
43 options: std.fmt.FormatOptions,
44 writer: anytype,
45) !void {
46 _ = options;
47 std.debug.assert(ctx.opt_sema == null);34 std.debug.assert(ctx.opt_sema == null);
48 comptime std.debug.assert(fmt.len == 0);
49 return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) {35 return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) {
50 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function36 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
51 error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable,37 error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable,
...@@ -55,11 +41,11 @@ pub fn format(...@@ -55,11 +41,11 @@ pub fn format(
5541
56pub fn print(42pub fn print(
57 val: Value,43 val: Value,
58 writer: anytype,44 writer: *std.io.Writer,
59 level: u8,45 level: u8,
60 pt: Zcu.PerThread,46 pt: Zcu.PerThread,
61 opt_sema: ?*Sema,47 opt_sema: ?*Sema,
62) (@TypeOf(writer).Error || Zcu.CompileError)!void {48) (std.io.Writer.Error || Zcu.CompileError)!void {
63 const zcu = pt.zcu;49 const zcu = pt.zcu;
64 const ip = &zcu.intern_pool;50 const ip = &zcu.intern_pool;
65 switch (ip.indexToKey(val.toIntern())) {51 switch (ip.indexToKey(val.toIntern())) {
...@@ -87,35 +73,36 @@ pub fn print(...@@ -87,35 +73,36 @@ pub fn print(
87 else => try writer.writeAll(@tagName(simple_value)),73 else => try writer.writeAll(@tagName(simple_value)),
88 },74 },
89 .variable => try writer.writeAll("(variable)"),75 .variable => try writer.writeAll("(variable)"),
90 .@"extern" => |e| try writer.print("(extern '{}')", .{e.name.fmt(ip)}),76 .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}),
91 .func => |func| try writer.print("(function '{}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),77 .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),
92 .int => |int| switch (int.storage) {78 .int => |int| switch (int.storage) {
93 inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}),79 inline .u64, .i64 => |x| try writer.print("{d}", .{x}),
80 .big_int => |x| try writer.print("{d}", .{x}),
94 .lazy_align => |ty| if (opt_sema != null) {81 .lazy_align => |ty| if (opt_sema != null) {
95 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);82 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);
96 try writer.print("{}", .{a.toByteUnits() orelse 0});83 try writer.print("{d}", .{a.toByteUnits() orelse 0});
97 } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(pt)}),84 } else try writer.print("@alignOf({f})", .{Type.fromInterned(ty).fmt(pt)}),
98 .lazy_size => |ty| if (opt_sema != null) {85 .lazy_size => |ty| if (opt_sema != null) {
99 const s = try Type.fromInterned(ty).abiSizeSema(pt);86 const s = try Type.fromInterned(ty).abiSizeSema(pt);
100 try writer.print("{}", .{s});87 try writer.print("{d}", .{s});
101 } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(pt)}),88 } else try writer.print("@sizeOf({f})", .{Type.fromInterned(ty).fmt(pt)}),
102 },89 },
103 .err => |err| try writer.print("error.{}", .{90 .err => |err| try writer.print("error.{f}", .{
104 err.name.fmt(ip),91 err.name.fmt(ip),
105 }),92 }),
106 .error_union => |error_union| switch (error_union.val) {93 .error_union => |error_union| switch (error_union.val) {
107 .err_name => |err_name| try writer.print("error.{}", .{94 .err_name => |err_name| try writer.print("error.{f}", .{
108 err_name.fmt(ip),95 err_name.fmt(ip),
109 }),96 }),
110 .payload => |payload| try print(Value.fromInterned(payload), writer, level, pt, opt_sema),97 .payload => |payload| try print(Value.fromInterned(payload), writer, level, pt, opt_sema),
111 },98 },
112 .enum_literal => |enum_literal| try writer.print(".{}", .{99 .enum_literal => |enum_literal| try writer.print(".{f}", .{
113 enum_literal.fmt(ip),100 enum_literal.fmt(ip),
114 }),101 }),
115 .enum_tag => |enum_tag| {102 .enum_tag => |enum_tag| {
116 const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern());103 const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern());
117 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {104 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
118 return writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});105 return writer.print(".{f}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
119 }106 }
120 if (level == 0) {107 if (level == 0) {
121 return writer.writeAll("@enumFromInt(...)");108 return writer.writeAll("@enumFromInt(...)");
...@@ -178,7 +165,7 @@ pub fn print(...@@ -178,7 +165,7 @@ pub fn print(
178 }165 }
179 if (un.tag == .none) {166 if (un.tag == .none) {
180 const backing_ty = try val.typeOf(zcu).unionBackingType(pt);167 const backing_ty = try val.typeOf(zcu).unionBackingType(pt);
181 try writer.print("@bitCast(@as({}, ", .{backing_ty.fmt(pt)});168 try writer.print("@bitCast(@as({f}, ", .{backing_ty.fmt(pt)});
182 try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema);169 try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema);
183 try writer.writeAll("))");170 try writer.writeAll("))");
184 } else {171 } else {
...@@ -197,11 +184,11 @@ fn printAggregate(...@@ -197,11 +184,11 @@ fn printAggregate(
197 val: Value,184 val: Value,
198 aggregate: InternPool.Key.Aggregate,185 aggregate: InternPool.Key.Aggregate,
199 is_ref: bool,186 is_ref: bool,
200 writer: anytype,187 writer: *std.io.Writer,
201 level: u8,188 level: u8,
202 pt: Zcu.PerThread,189 pt: Zcu.PerThread,
203 opt_sema: ?*Sema,190 opt_sema: ?*Sema,
204) (@TypeOf(writer).Error || Zcu.CompileError)!void {191) (std.io.Writer.Error || Zcu.CompileError)!void {
205 if (level == 0) {192 if (level == 0) {
206 if (is_ref) try writer.writeByte('&');193 if (is_ref) try writer.writeByte('&');
207 return writer.writeAll(".{ ... }");194 return writer.writeAll(".{ ... }");
...@@ -220,7 +207,7 @@ fn printAggregate(...@@ -220,7 +207,7 @@ fn printAggregate(
220 for (0..max_len) |i| {207 for (0..max_len) |i| {
221 if (i != 0) try writer.writeAll(", ");208 if (i != 0) try writer.writeAll(", ");
222 const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;209 const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;
223 try writer.print(".{i} = ", .{field_name.fmt(ip)});210 try writer.print(".{f} = ", .{field_name.fmt(ip)});
224 try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);211 try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);
225 }212 }
226 try writer.writeAll(" }");213 try writer.writeAll(" }");
...@@ -232,7 +219,7 @@ fn printAggregate(...@@ -232,7 +219,7 @@ fn printAggregate(
232 const len = ty.arrayLenIncludingSentinel(zcu);219 const len = ty.arrayLenIncludingSentinel(zcu);
233 if (len == 0) break :string;220 if (len == 0) break :string;
234 const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip);221 const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip);
235 try writer.print("\"{}\"", .{std.zig.fmtEscapes(slice)});222 try writer.print("\"{f}\"", .{std.zig.fmtString(slice)});
236 if (!is_ref) try writer.writeAll(".*");223 if (!is_ref) try writer.writeAll(".*");
237 return;224 return;
238 },225 },
...@@ -249,7 +236,7 @@ fn printAggregate(...@@ -249,7 +236,7 @@ fn printAggregate(
249 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);236 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);
250 if (elem_val.isUndef(zcu)) break :one_byte_str;237 if (elem_val.isUndef(zcu)) break :one_byte_str;
251 const byte = elem_val.toUnsignedInt(zcu);238 const byte = elem_val.toUnsignedInt(zcu);
252 try writer.print("\"{}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})});239 try writer.print("\"{f}\"", .{std.zig.fmtString(&.{@intCast(byte)})});
253 if (!is_ref) try writer.writeAll(".*");240 if (!is_ref) try writer.writeAll(".*");
254 return;241 return;
255 },242 },
...@@ -283,11 +270,11 @@ fn printPtr(...@@ -283,11 +270,11 @@ fn printPtr(
283 ptr_val: Value,270 ptr_val: Value,
284 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.271 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
285 want_kind: ?PrintPtrKind,272 want_kind: ?PrintPtrKind,
286 writer: anytype,273 writer: *std.io.Writer,
287 level: u8,274 level: u8,
288 pt: Zcu.PerThread,275 pt: Zcu.PerThread,
289 opt_sema: ?*Sema,276 opt_sema: ?*Sema,
290) (@TypeOf(writer).Error || Zcu.CompileError)!void {277) (std.io.Writer.Error || Zcu.CompileError)!void {
291 const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) {278 const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) {
292 .undef => return writer.writeAll("undefined"),279 .undef => return writer.writeAll("undefined"),
293 .ptr => |ptr| ptr,280 .ptr => |ptr| ptr,
...@@ -329,7 +316,7 @@ const PrintPtrKind = enum { lvalue, rvalue };...@@ -329,7 +316,7 @@ const PrintPtrKind = enum { lvalue, rvalue };
329/// Returns the root derivation, which may be ignored.316/// Returns the root derivation, which may be ignored.
330pub fn printPtrDerivation(317pub fn printPtrDerivation(
331 derivation: Value.PointerDeriveStep,318 derivation: Value.PointerDeriveStep,
332 writer: anytype,319 writer: *std.io.Writer,
333 pt: Zcu.PerThread,320 pt: Zcu.PerThread,
334 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.321 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
335 /// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as322 /// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as
...@@ -405,14 +392,14 @@ pub fn printPtrDerivation(...@@ -405,14 +392,14 @@ pub fn printPtrDerivation(
405 const agg_ty = (try field.parent.ptrType(pt)).childType(zcu);392 const agg_ty = (try field.parent.ptrType(pt)).childType(zcu);
406 switch (agg_ty.zigTypeTag(zcu)) {393 switch (agg_ty.zigTypeTag(zcu)) {
407 .@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| {394 .@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| {
408 try writer.print(".{i}", .{field_name.fmt(ip)});395 try writer.print(".{f}", .{field_name.fmt(ip)});
409 } else {396 } else {
410 try writer.print("[{d}]", .{field.field_idx});397 try writer.print("[{d}]", .{field.field_idx});
411 },398 },
412 .@"union" => {399 .@"union" => {
413 const tag_ty = agg_ty.unionTagTypeHypothetical(zcu);400 const tag_ty = agg_ty.unionTagTypeHypothetical(zcu);
414 const field_name = tag_ty.enumFieldName(field.field_idx, zcu);401 const field_name = tag_ty.enumFieldName(field.field_idx, zcu);
415 try writer.print(".{i}", .{field_name.fmt(ip)});402 try writer.print(".{f}", .{field_name.fmt(ip)});
416 },403 },
417 .pointer => switch (field.field_idx) {404 .pointer => switch (field.field_idx) {
418 Value.slice_ptr_index => try writer.writeAll(".ptr"),405 Value.slice_ptr_index => try writer.writeAll(".ptr"),
...@@ -430,12 +417,12 @@ pub fn printPtrDerivation(...@@ -430,12 +417,12 @@ pub fn printPtrDerivation(
430 },417 },
431418
432 .offset_and_cast => |oac| if (oac.byte_offset == 0) root: {419 .offset_and_cast => |oac| if (oac.byte_offset == 0) root: {
433 try writer.print("@as({}, @ptrCast(", .{oac.new_ptr_ty.fmt(pt)});420 try writer.print("@as({f}, @ptrCast(", .{oac.new_ptr_ty.fmt(pt)});
434 const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);421 const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);
435 try writer.writeAll("))");422 try writer.writeAll("))");
436 break :root root;423 break :root root;
437 } else root: {424 } else root: {
438 try writer.print("@as({}, @ptrFromInt(@intFromPtr(", .{oac.new_ptr_ty.fmt(pt)});425 try writer.print("@as({f}, @ptrFromInt(@intFromPtr(", .{oac.new_ptr_ty.fmt(pt)});
439 const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);426 const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);
440 try writer.print(") + {d}))", .{oac.byte_offset});427 try writer.print(") + {d}))", .{oac.byte_offset});
441 break :root root;428 break :root root;
...@@ -447,22 +434,22 @@ pub fn printPtrDerivation(...@@ -447,22 +434,22 @@ pub fn printPtrDerivation(
447 if (root_or_null == null) switch (root_strat) {434 if (root_or_null == null) switch (root_strat) {
448 .str => |x| try writer.writeAll(x),435 .str => |x| try writer.writeAll(x),
449 .print_val => |x| switch (derivation) {436 .print_val => |x| switch (derivation) {
450 .int => |int| try writer.print("@as({}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }),437 .int => |int| try writer.print("@as({f}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }),
451 .nav_ptr => |nav| try writer.print("{}", .{ip.getNav(nav).fqn.fmt(ip)}),438 .nav_ptr => |nav| try writer.print("{f}", .{ip.getNav(nav).fqn.fmt(ip)}),
452 .uav_ptr => |uav| {439 .uav_ptr => |uav| {
453 const ty = Value.fromInterned(uav.val).typeOf(zcu);440 const ty = Value.fromInterned(uav.val).typeOf(zcu);
454 try writer.print("@as({}, ", .{ty.fmt(pt)});441 try writer.print("@as({f}, ", .{ty.fmt(pt)});
455 try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema);442 try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema);
456 try writer.writeByte(')');443 try writer.writeByte(')');
457 },444 },
458 .comptime_alloc_ptr => |info| {445 .comptime_alloc_ptr => |info| {
459 try writer.print("@as({}, ", .{info.val.typeOf(zcu).fmt(pt)});446 try writer.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)});
460 try print(info.val, writer, x.level - 1, pt, x.opt_sema);447 try print(info.val, writer, x.level - 1, pt, x.opt_sema);
461 try writer.writeByte(')');448 try writer.writeByte(')');
462 },449 },
463 .comptime_field_ptr => |val| {450 .comptime_field_ptr => |val| {
464 const ty = val.typeOf(zcu);451 const ty = val.typeOf(zcu);
465 try writer.print("@as({}, ", .{ty.fmt(pt)});452 try writer.print("@as({f}, ", .{ty.fmt(pt)});
466 try print(val, writer, x.level - 1, pt, x.opt_sema);453 try print(val, writer, x.level - 1, pt, x.opt_sema);
467 try writer.writeByte(')');454 try writer.writeByte(')');
468 },455 },
src/print_zir.zig+185-195
...@@ -9,13 +9,8 @@ const Zir = std.zig.Zir;...@@ -9,13 +9,8 @@ const Zir = std.zig.Zir;
9const Zcu = @import("Zcu.zig");9const Zcu = @import("Zcu.zig");
10const LazySrcLoc = Zcu.LazySrcLoc;10const LazySrcLoc = Zcu.LazySrcLoc;
1111
12/// Write human-readable, debug formatted ZIR code to a file.12/// Write human-readable, debug formatted ZIR code.
13pub fn renderAsTextToFile(13pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.Writer) !void {
14 gpa: Allocator,
15 tree: ?Ast,
16 zir: Zir,
17 fs_file: std.fs.File,
18) !void {
19 var arena = std.heap.ArenaAllocator.init(gpa);14 var arena = std.heap.ArenaAllocator.init(gpa);
20 defer arena.deinit();15 defer arena.deinit();
2116
...@@ -30,16 +25,13 @@ pub fn renderAsTextToFile(...@@ -30,16 +25,13 @@ pub fn renderAsTextToFile(
30 .recurse_blocks = true,25 .recurse_blocks = true,
31 };26 };
3227
33 var raw_stream = std.io.bufferedWriter(fs_file.writer());
34 const stream = raw_stream.writer();
35
36 const main_struct_inst: Zir.Inst.Index = .main_struct_inst;28 const main_struct_inst: Zir.Inst.Index = .main_struct_inst;
37 try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)});29 try bw.print("%{d} ", .{@intFromEnum(main_struct_inst)});
38 try writer.writeInstToStream(stream, main_struct_inst);30 try writer.writeInstToStream(bw, main_struct_inst);
39 try stream.writeAll("\n");31 try bw.writeAll("\n");
40 const imports_index = zir.extra[@intFromEnum(Zir.ExtraIndex.imports)];32 const imports_index = zir.extra[@intFromEnum(Zir.ExtraIndex.imports)];
41 if (imports_index != 0) {33 if (imports_index != 0) {
42 try stream.writeAll("Imports:\n");34 try bw.writeAll("Imports:\n");
4335
44 const extra = zir.extraData(Zir.Inst.Imports, imports_index);36 const extra = zir.extraData(Zir.Inst.Imports, imports_index);
45 var extra_index = extra.end;37 var extra_index = extra.end;
...@@ -49,15 +41,13 @@ pub fn renderAsTextToFile(...@@ -49,15 +41,13 @@ pub fn renderAsTextToFile(
49 extra_index = item.end;41 extra_index = item.end;
5042
51 const import_path = zir.nullTerminatedString(item.data.name);43 const import_path = zir.nullTerminatedString(item.data.name);
52 try stream.print(" @import(\"{}\") ", .{44 try bw.print(" @import(\"{f}\") ", .{
53 std.zig.fmtEscapes(import_path),45 std.zig.fmtString(import_path),
54 });46 });
55 try writer.writeSrcTokAbs(stream, item.data.token);47 try writer.writeSrcTokAbs(bw, item.data.token);
56 try stream.writeAll("\n");48 try bw.writeAll("\n");
57 }49 }
58 }50 }
59
60 try raw_stream.flush();
61}51}
6252
63pub fn renderInstructionContext(53pub fn renderInstructionContext(
...@@ -67,7 +57,7 @@ pub fn renderInstructionContext(...@@ -67,7 +57,7 @@ pub fn renderInstructionContext(
67 scope_file: *Zcu.File,57 scope_file: *Zcu.File,
68 parent_decl_node: Ast.Node.Index,58 parent_decl_node: Ast.Node.Index,
69 indent: u32,59 indent: u32,
70 stream: anytype,60 bw: *std.io.Writer,
71) !void {61) !void {
72 var arena = std.heap.ArenaAllocator.init(gpa);62 var arena = std.heap.ArenaAllocator.init(gpa);
73 defer arena.deinit();63 defer arena.deinit();
...@@ -83,13 +73,13 @@ pub fn renderInstructionContext(...@@ -83,13 +73,13 @@ pub fn renderInstructionContext(
83 .recurse_blocks = true,73 .recurse_blocks = true,
84 };74 };
8575
86 try writer.writeBody(stream, block[0..block_index]);76 try writer.writeBody(bw, block[0..block_index]);
87 try stream.writeByteNTimes(' ', writer.indent - 2);77 try bw.splatByteAll(' ', writer.indent - 2);
88 try stream.print("> %{d} ", .{@intFromEnum(block[block_index])});78 try bw.print("> %{d} ", .{@intFromEnum(block[block_index])});
89 try writer.writeInstToStream(stream, block[block_index]);79 try writer.writeInstToStream(bw, block[block_index]);
90 try stream.writeByte('\n');80 try bw.writeByte('\n');
91 if (block_index + 1 < block.len) {81 if (block_index + 1 < block.len) {
92 try writer.writeBody(stream, block[block_index + 1 ..]);82 try writer.writeBody(bw, block[block_index + 1 ..]);
93 }83 }
94}84}
9585
...@@ -99,7 +89,7 @@ pub fn renderSingleInstruction(...@@ -99,7 +89,7 @@ pub fn renderSingleInstruction(
99 scope_file: *Zcu.File,89 scope_file: *Zcu.File,
100 parent_decl_node: Ast.Node.Index,90 parent_decl_node: Ast.Node.Index,
101 indent: u32,91 indent: u32,
102 stream: anytype,92 bw: *std.io.Writer,
103) !void {93) !void {
104 var arena = std.heap.ArenaAllocator.init(gpa);94 var arena = std.heap.ArenaAllocator.init(gpa);
105 defer arena.deinit();95 defer arena.deinit();
...@@ -115,8 +105,8 @@ pub fn renderSingleInstruction(...@@ -115,8 +105,8 @@ pub fn renderSingleInstruction(
115 .recurse_blocks = false,105 .recurse_blocks = false,
116 };106 };
117107
118 try stream.print("%{d} ", .{@intFromEnum(inst)});108 try bw.print("%{d} ", .{@intFromEnum(inst)});
119 try writer.writeInstToStream(stream, inst);109 try writer.writeInstToStream(bw, inst);
120}110}
121111
122const Writer = struct {112const Writer = struct {
...@@ -186,11 +176,13 @@ const Writer = struct {...@@ -186,11 +176,13 @@ const Writer = struct {
186 }176 }
187 } = .{},177 } = .{},
188178
179 const Error = std.io.Writer.Error || Allocator.Error;
180
189 fn writeInstToStream(181 fn writeInstToStream(
190 self: *Writer,182 self: *Writer,
191 stream: anytype,183 stream: *std.io.Writer,
192 inst: Zir.Inst.Index,184 inst: Zir.Inst.Index,
193 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {185 ) Error!void {
194 const tags = self.code.instructions.items(.tag);186 const tags = self.code.instructions.items(.tag);
195 const tag = tags[@intFromEnum(inst)];187 const tag = tags[@intFromEnum(inst)];
196 try stream.print("= {s}(", .{@tagName(tags[@intFromEnum(inst)])});188 try stream.print("= {s}(", .{@tagName(tags[@intFromEnum(inst)])});
...@@ -516,7 +508,7 @@ const Writer = struct {...@@ -516,7 +508,7 @@ const Writer = struct {
516 }508 }
517 }509 }
518510
519 fn writeExtended(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {511 fn writeExtended(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
520 const extended = self.code.instructions.items(.data)[@intFromEnum(inst)].extended;512 const extended = self.code.instructions.items(.data)[@intFromEnum(inst)].extended;
521 try stream.print("{s}(", .{@tagName(extended.opcode)});513 try stream.print("{s}(", .{@tagName(extended.opcode)});
522 switch (extended.opcode) {514 switch (extended.opcode) {
...@@ -623,13 +615,13 @@ const Writer = struct {...@@ -623,13 +615,13 @@ const Writer = struct {
623 }615 }
624 }616 }
625617
626 fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {618 fn writeExtNode(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
627 try stream.writeAll(")) ");619 try stream.writeAll(")) ");
628 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));620 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
629 try self.writeSrcNode(stream, src_node);621 try self.writeSrcNode(stream, src_node);
630 }622 }
631623
632 fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {624 fn writeArrayInitElemType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
633 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;625 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;
634 try self.writeInstRef(stream, inst_data.lhs);626 try self.writeInstRef(stream, inst_data.lhs);
635 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});627 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});
...@@ -637,9 +629,9 @@ const Writer = struct {...@@ -637,9 +629,9 @@ const Writer = struct {
637629
638 fn writeUnNode(630 fn writeUnNode(
639 self: *Writer,631 self: *Writer,
640 stream: anytype,632 stream: *std.io.Writer,
641 inst: Zir.Inst.Index,633 inst: Zir.Inst.Index,
642 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {634 ) Error!void {
643 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node;635 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
644 try self.writeInstRef(stream, inst_data.operand);636 try self.writeInstRef(stream, inst_data.operand);
645 try stream.writeAll(") ");637 try stream.writeAll(") ");
...@@ -648,9 +640,9 @@ const Writer = struct {...@@ -648,9 +640,9 @@ const Writer = struct {
648640
649 fn writeUnTok(641 fn writeUnTok(
650 self: *Writer,642 self: *Writer,
651 stream: anytype,643 stream: *std.io.Writer,
652 inst: Zir.Inst.Index,644 inst: Zir.Inst.Index,
653 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {645 ) Error!void {
654 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok;646 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok;
655 try self.writeInstRef(stream, inst_data.operand);647 try self.writeInstRef(stream, inst_data.operand);
656 try stream.writeAll(") ");648 try stream.writeAll(") ");
...@@ -659,9 +651,9 @@ const Writer = struct {...@@ -659,9 +651,9 @@ const Writer = struct {
659651
660 fn writeValidateDestructure(652 fn writeValidateDestructure(
661 self: *Writer,653 self: *Writer,
662 stream: anytype,654 stream: *std.io.Writer,
663 inst: Zir.Inst.Index,655 inst: Zir.Inst.Index,
664 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {656 ) Error!void {
665 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;657 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
666 const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data;658 const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data;
667 try self.writeInstRef(stream, extra.operand);659 try self.writeInstRef(stream, extra.operand);
...@@ -673,9 +665,9 @@ const Writer = struct {...@@ -673,9 +665,9 @@ const Writer = struct {
673665
674 fn writeValidateArrayInitTy(666 fn writeValidateArrayInitTy(
675 self: *Writer,667 self: *Writer,
676 stream: anytype,668 stream: *std.io.Writer,
677 inst: Zir.Inst.Index,669 inst: Zir.Inst.Index,
678 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {670 ) Error!void {
679 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;671 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
680 const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;672 const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
681 try self.writeInstRef(stream, extra.ty);673 try self.writeInstRef(stream, extra.ty);
...@@ -685,9 +677,9 @@ const Writer = struct {...@@ -685,9 +677,9 @@ const Writer = struct {
685677
686 fn writeArrayTypeSentinel(678 fn writeArrayTypeSentinel(
687 self: *Writer,679 self: *Writer,
688 stream: anytype,680 stream: *std.io.Writer,
689 inst: Zir.Inst.Index,681 inst: Zir.Inst.Index,
690 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {682 ) Error!void {
691 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;683 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
692 const extra = self.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;684 const extra = self.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
693 try self.writeInstRef(stream, extra.len);685 try self.writeInstRef(stream, extra.len);
...@@ -701,9 +693,9 @@ const Writer = struct {...@@ -701,9 +693,9 @@ const Writer = struct {
701693
702 fn writePtrType(694 fn writePtrType(
703 self: *Writer,695 self: *Writer,
704 stream: anytype,696 stream: *std.io.Writer,
705 inst: Zir.Inst.Index,697 inst: Zir.Inst.Index,
706 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {698 ) Error!void {
707 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;699 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;
708 const str_allowzero = if (inst_data.flags.is_allowzero) "allowzero, " else "";700 const str_allowzero = if (inst_data.flags.is_allowzero) "allowzero, " else "";
709 const str_const = if (!inst_data.flags.is_mutable) "const, " else "";701 const str_const = if (!inst_data.flags.is_mutable) "const, " else "";
...@@ -744,12 +736,12 @@ const Writer = struct {...@@ -744,12 +736,12 @@ const Writer = struct {
744 try self.writeSrcNode(stream, extra.data.src_node);736 try self.writeSrcNode(stream, extra.data.src_node);
745 }737 }
746738
747 fn writeInt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {739 fn writeInt(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
748 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int;740 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int;
749 try stream.print("{d})", .{inst_data});741 try stream.print("{d})", .{inst_data});
750 }742 }
751743
752 fn writeIntBig(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {744 fn writeIntBig(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
753 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;745 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
754 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);746 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);
755 const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count];747 const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count];
...@@ -768,12 +760,12 @@ const Writer = struct {...@@ -768,12 +760,12 @@ const Writer = struct {
768 try stream.print("{s})", .{as_string});760 try stream.print("{s})", .{as_string});
769 }761 }
770762
771 fn writeFloat(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {763 fn writeFloat(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
772 const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float;764 const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float;
773 try stream.print("{d})", .{number});765 try stream.print("{d})", .{number});
774 }766 }
775767
776 fn writeFloat128(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {768 fn writeFloat128(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
777 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;769 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
778 const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;770 const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
779 const number = extra.get();771 const number = extra.get();
...@@ -784,15 +776,15 @@ const Writer = struct {...@@ -784,15 +776,15 @@ const Writer = struct {
784776
785 fn writeStr(777 fn writeStr(
786 self: *Writer,778 self: *Writer,
787 stream: anytype,779 stream: *std.io.Writer,
788 inst: Zir.Inst.Index,780 inst: Zir.Inst.Index,
789 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {781 ) Error!void {
790 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;782 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
791 const str = inst_data.get(self.code);783 const str = inst_data.get(self.code);
792 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});784 try stream.print("\"{f}\")", .{std.zig.fmtString(str)});
793 }785 }
794786
795 fn writeSliceStart(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {787 fn writeSliceStart(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
796 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;788 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
797 const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;789 const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;
798 try self.writeInstRef(stream, extra.lhs);790 try self.writeInstRef(stream, extra.lhs);
...@@ -802,7 +794,7 @@ const Writer = struct {...@@ -802,7 +794,7 @@ const Writer = struct {
802 try self.writeSrcNode(stream, inst_data.src_node);794 try self.writeSrcNode(stream, inst_data.src_node);
803 }795 }
804796
805 fn writeSliceEnd(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {797 fn writeSliceEnd(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
806 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;798 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
807 const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;799 const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;
808 try self.writeInstRef(stream, extra.lhs);800 try self.writeInstRef(stream, extra.lhs);
...@@ -814,7 +806,7 @@ const Writer = struct {...@@ -814,7 +806,7 @@ const Writer = struct {
814 try self.writeSrcNode(stream, inst_data.src_node);806 try self.writeSrcNode(stream, inst_data.src_node);
815 }807 }
816808
817 fn writeSliceSentinel(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {809 fn writeSliceSentinel(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
818 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;810 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
819 const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;811 const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;
820 try self.writeInstRef(stream, extra.lhs);812 try self.writeInstRef(stream, extra.lhs);
...@@ -828,7 +820,7 @@ const Writer = struct {...@@ -828,7 +820,7 @@ const Writer = struct {
828 try self.writeSrcNode(stream, inst_data.src_node);820 try self.writeSrcNode(stream, inst_data.src_node);
829 }821 }
830822
831 fn writeSliceLength(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {823 fn writeSliceLength(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
832 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;824 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
833 const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;825 const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;
834 try self.writeInstRef(stream, extra.lhs);826 try self.writeInstRef(stream, extra.lhs);
...@@ -844,7 +836,7 @@ const Writer = struct {...@@ -844,7 +836,7 @@ const Writer = struct {
844 try self.writeSrcNode(stream, inst_data.src_node);836 try self.writeSrcNode(stream, inst_data.src_node);
845 }837 }
846838
847 fn writeUnionInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {839 fn writeUnionInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
848 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;840 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
849 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;841 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
850 try self.writeInstRef(stream, extra.union_type);842 try self.writeInstRef(stream, extra.union_type);
...@@ -856,7 +848,7 @@ const Writer = struct {...@@ -856,7 +848,7 @@ const Writer = struct {
856 try self.writeSrcNode(stream, inst_data.src_node);848 try self.writeSrcNode(stream, inst_data.src_node);
857 }849 }
858850
859 fn writeShuffle(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {851 fn writeShuffle(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
860 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;852 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
861 const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;853 const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;
862 try self.writeInstRef(stream, extra.elem_type);854 try self.writeInstRef(stream, extra.elem_type);
...@@ -870,7 +862,7 @@ const Writer = struct {...@@ -870,7 +862,7 @@ const Writer = struct {
870 try self.writeSrcNode(stream, inst_data.src_node);862 try self.writeSrcNode(stream, inst_data.src_node);
871 }863 }
872864
873 fn writeSelect(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {865 fn writeSelect(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
874 const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data;866 const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data;
875 try self.writeInstRef(stream, extra.elem_type);867 try self.writeInstRef(stream, extra.elem_type);
876 try stream.writeAll(", ");868 try stream.writeAll(", ");
...@@ -883,7 +875,7 @@ const Writer = struct {...@@ -883,7 +875,7 @@ const Writer = struct {
883 try self.writeSrcNode(stream, extra.node);875 try self.writeSrcNode(stream, extra.node);
884 }876 }
885877
886 fn writeMulAdd(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {878 fn writeMulAdd(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
887 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;879 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
888 const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data;880 const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data;
889 try self.writeInstRef(stream, extra.mulend1);881 try self.writeInstRef(stream, extra.mulend1);
...@@ -895,7 +887,7 @@ const Writer = struct {...@@ -895,7 +887,7 @@ const Writer = struct {
895 try self.writeSrcNode(stream, inst_data.src_node);887 try self.writeSrcNode(stream, inst_data.src_node);
896 }888 }
897889
898 fn writeBuiltinCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {890 fn writeBuiltinCall(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
899 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;891 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
900 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;892 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
901893
...@@ -911,7 +903,7 @@ const Writer = struct {...@@ -911,7 +903,7 @@ const Writer = struct {
911 try self.writeSrcNode(stream, inst_data.src_node);903 try self.writeSrcNode(stream, inst_data.src_node);
912 }904 }
913905
914 fn writeFieldParentPtr(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {906 fn writeFieldParentPtr(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
915 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;907 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
916 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;908 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
917 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));909 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
...@@ -928,12 +920,12 @@ const Writer = struct {...@@ -928,12 +920,12 @@ const Writer = struct {
928 try self.writeSrcNode(stream, extra.src_node);920 try self.writeSrcNode(stream, extra.src_node);
929 }921 }
930922
931 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {923 fn writeParam(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
932 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;924 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);925 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);926 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
935 try stream.print("\"{}\", ", .{927 try stream.print("\"{f}\", ", .{
936 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),928 std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)),
937 });929 });
938930
939 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");931 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
...@@ -943,7 +935,7 @@ const Writer = struct {...@@ -943,7 +935,7 @@ const Writer = struct {
943 try self.writeSrcTok(stream, inst_data.src_tok);935 try self.writeSrcTok(stream, inst_data.src_tok);
944 }936 }
945937
946 fn writePlNodeBin(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {938 fn writePlNodeBin(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
947 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;939 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
948 const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;940 const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
949 try self.writeInstRef(stream, extra.lhs);941 try self.writeInstRef(stream, extra.lhs);
...@@ -953,7 +945,7 @@ const Writer = struct {...@@ -953,7 +945,7 @@ const Writer = struct {
953 try self.writeSrcNode(stream, inst_data.src_node);945 try self.writeSrcNode(stream, inst_data.src_node);
954 }946 }
955947
956 fn writePlNodeMultiOp(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {948 fn writePlNodeMultiOp(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
957 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;949 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
958 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);950 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
959 const args = self.code.refSlice(extra.end, extra.data.operands_len);951 const args = self.code.refSlice(extra.end, extra.data.operands_len);
...@@ -966,7 +958,7 @@ const Writer = struct {...@@ -966,7 +958,7 @@ const Writer = struct {
966 try self.writeSrcNode(stream, inst_data.src_node);958 try self.writeSrcNode(stream, inst_data.src_node);
967 }959 }
968960
969 fn writeArrayMul(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {961 fn writeArrayMul(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
970 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;962 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
971 const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;963 const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;
972 try self.writeInstRef(stream, extra.res_ty);964 try self.writeInstRef(stream, extra.res_ty);
...@@ -978,13 +970,13 @@ const Writer = struct {...@@ -978,13 +970,13 @@ const Writer = struct {
978 try self.writeSrcNode(stream, inst_data.src_node);970 try self.writeSrcNode(stream, inst_data.src_node);
979 }971 }
980972
981 fn writeElemValImm(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {973 fn writeElemValImm(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
982 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;974 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;
983 try self.writeInstRef(stream, inst_data.operand);975 try self.writeInstRef(stream, inst_data.operand);
984 try stream.print(", {d})", .{inst_data.idx});976 try stream.print(", {d})", .{inst_data.idx});
985 }977 }
986978
987 fn writeArrayInitElemPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {979 fn writeArrayInitElemPtr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
988 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;980 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
989 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;981 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
990982
...@@ -993,7 +985,7 @@ const Writer = struct {...@@ -993,7 +985,7 @@ const Writer = struct {
993 try self.writeSrcNode(stream, inst_data.src_node);985 try self.writeSrcNode(stream, inst_data.src_node);
994 }986 }
995987
996 fn writePlNodeExport(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {988 fn writePlNodeExport(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
997 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;989 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
998 const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;990 const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
999991
...@@ -1004,7 +996,7 @@ const Writer = struct {...@@ -1004,7 +996,7 @@ const Writer = struct {
1004 try self.writeSrcNode(stream, inst_data.src_node);996 try self.writeSrcNode(stream, inst_data.src_node);
1005 }997 }
1006998
1007 fn writeValidateArrayInitRefTy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {999 fn writeValidateArrayInitRefTy(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1008 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1000 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1009 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;1001 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;
10101002
...@@ -1014,7 +1006,7 @@ const Writer = struct {...@@ -1014,7 +1006,7 @@ const Writer = struct {
1014 try self.writeSrcNode(stream, inst_data.src_node);1006 try self.writeSrcNode(stream, inst_data.src_node);
1015 }1007 }
10161008
1017 fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1009 fn writeStructInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1018 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1010 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1019 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);1011 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
1020 var field_i: u32 = 0;1012 var field_i: u32 = 0;
...@@ -1038,7 +1030,7 @@ const Writer = struct {...@@ -1038,7 +1030,7 @@ const Writer = struct {
1038 try self.writeSrcNode(stream, inst_data.src_node);1030 try self.writeSrcNode(stream, inst_data.src_node);
1039 }1031 }
10401032
1041 fn writeCmpxchg(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1033 fn writeCmpxchg(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1042 const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;1034 const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;
10431035
1044 try self.writeInstRef(stream, extra.ptr);1036 try self.writeInstRef(stream, extra.ptr);
...@@ -1054,7 +1046,7 @@ const Writer = struct {...@@ -1054,7 +1046,7 @@ const Writer = struct {
1054 try self.writeSrcNode(stream, extra.node);1046 try self.writeSrcNode(stream, extra.node);
1055 }1047 }
10561048
1057 fn writePtrCastFull(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1049 fn writePtrCastFull(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1058 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;1050 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1059 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));1051 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1060 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;1052 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
...@@ -1070,7 +1062,7 @@ const Writer = struct {...@@ -1070,7 +1062,7 @@ const Writer = struct {
1070 try self.writeSrcNode(stream, extra.node);1062 try self.writeSrcNode(stream, extra.node);
1071 }1063 }
10721064
1073 fn writePtrCastNoDest(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1065 fn writePtrCastNoDest(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1074 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;1066 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1075 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));1067 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1076 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;1068 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
...@@ -1081,7 +1073,7 @@ const Writer = struct {...@@ -1081,7 +1073,7 @@ const Writer = struct {
1081 try self.writeSrcNode(stream, extra.node);1073 try self.writeSrcNode(stream, extra.node);
1082 }1074 }
10831075
1084 fn writeAtomicLoad(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1076 fn writeAtomicLoad(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1085 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1077 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1086 const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data;1078 const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data;
10871079
...@@ -1094,7 +1086,7 @@ const Writer = struct {...@@ -1094,7 +1086,7 @@ const Writer = struct {
1094 try self.writeSrcNode(stream, inst_data.src_node);1086 try self.writeSrcNode(stream, inst_data.src_node);
1095 }1087 }
10961088
1097 fn writeAtomicStore(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1089 fn writeAtomicStore(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1098 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1090 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1099 const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;1091 const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;
11001092
...@@ -1107,7 +1099,7 @@ const Writer = struct {...@@ -1107,7 +1099,7 @@ const Writer = struct {
1107 try self.writeSrcNode(stream, inst_data.src_node);1099 try self.writeSrcNode(stream, inst_data.src_node);
1108 }1100 }
11091101
1110 fn writeAtomicRmw(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1102 fn writeAtomicRmw(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1111 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1103 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1112 const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;1104 const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
11131105
...@@ -1122,7 +1114,7 @@ const Writer = struct {...@@ -1122,7 +1114,7 @@ const Writer = struct {
1122 try self.writeSrcNode(stream, inst_data.src_node);1114 try self.writeSrcNode(stream, inst_data.src_node);
1123 }1115 }
11241116
1125 fn writeStructInitAnon(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1117 fn writeStructInitAnon(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1126 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1118 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1127 const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);1119 const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
1128 var field_i: u32 = 0;1120 var field_i: u32 = 0;
...@@ -1143,7 +1135,7 @@ const Writer = struct {...@@ -1143,7 +1135,7 @@ const Writer = struct {
1143 try self.writeSrcNode(stream, inst_data.src_node);1135 try self.writeSrcNode(stream, inst_data.src_node);
1144 }1136 }
11451137
1146 fn writeStructInitFieldType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1138 fn writeStructInitFieldType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1147 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1139 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1148 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;1140 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
1149 try self.writeInstRef(stream, extra.container_type);1141 try self.writeInstRef(stream, extra.container_type);
...@@ -1152,7 +1144,7 @@ const Writer = struct {...@@ -1152,7 +1144,7 @@ const Writer = struct {
1152 try self.writeSrcNode(stream, inst_data.src_node);1144 try self.writeSrcNode(stream, inst_data.src_node);
1153 }1145 }
11541146
1155 fn writeFieldTypeRef(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1147 fn writeFieldTypeRef(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1156 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1148 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1157 const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;1149 const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;
1158 try self.writeInstRef(stream, extra.container_type);1150 try self.writeInstRef(stream, extra.container_type);
...@@ -1162,7 +1154,7 @@ const Writer = struct {...@@ -1162,7 +1154,7 @@ const Writer = struct {
1162 try self.writeSrcNode(stream, inst_data.src_node);1154 try self.writeSrcNode(stream, inst_data.src_node);
1163 }1155 }
11641156
1165 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1157 fn writeNodeMultiOp(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1166 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);1158 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
1167 const operands = self.code.refSlice(extra.end, extended.small);1159 const operands = self.code.refSlice(extra.end, extended.small);
11681160
...@@ -1176,9 +1168,9 @@ const Writer = struct {...@@ -1176,9 +1168,9 @@ const Writer = struct {
11761168
1177 fn writeInstNode(1169 fn writeInstNode(
1178 self: *Writer,1170 self: *Writer,
1179 stream: anytype,1171 stream: *std.io.Writer,
1180 inst: Zir.Inst.Index,1172 inst: Zir.Inst.Index,
1181 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {1173 ) Error!void {
1182 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node;1174 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node;
1183 try self.writeInstIndex(stream, inst_data.inst);1175 try self.writeInstIndex(stream, inst_data.inst);
1184 try stream.writeAll(") ");1176 try stream.writeAll(") ");
...@@ -1187,7 +1179,7 @@ const Writer = struct {...@@ -1187,7 +1179,7 @@ const Writer = struct {
11871179
1188 fn writeAsm(1180 fn writeAsm(
1189 self: *Writer,1181 self: *Writer,
1190 stream: anytype,1182 stream: *std.io.Writer,
1191 extended: Zir.Inst.Extended.InstData,1183 extended: Zir.Inst.Extended.InstData,
1192 tmpl_is_expr: bool,1184 tmpl_is_expr: bool,
1193 ) !void {1185 ) !void {
...@@ -1203,7 +1195,7 @@ const Writer = struct {...@@ -1203,7 +1195,7 @@ const Writer = struct {
1203 try stream.writeAll(", ");1195 try stream.writeAll(", ");
1204 } else {1196 } else {
1205 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);1197 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
1206 try stream.print("\"{}\", ", .{std.zig.fmtEscapes(asm_source)});1198 try stream.print("\"{f}\", ", .{std.zig.fmtString(asm_source)});
1207 }1199 }
1208 try stream.writeAll(", ");1200 try stream.writeAll(", ");
12091201
...@@ -1220,8 +1212,8 @@ const Writer = struct {...@@ -1220,8 +1212,8 @@ const Writer = struct {
12201212
1221 const name = self.code.nullTerminatedString(output.data.name);1213 const name = self.code.nullTerminatedString(output.data.name);
1222 const constraint = self.code.nullTerminatedString(output.data.constraint);1214 const constraint = self.code.nullTerminatedString(output.data.constraint);
1223 try stream.print("output({p}, \"{}\", ", .{1215 try stream.print("output({f}, \"{f}\", ", .{
1224 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),1216 std.zig.fmtIdP(name), std.zig.fmtString(constraint),
1225 });1217 });
1226 try self.writeFlag(stream, "->", is_type);1218 try self.writeFlag(stream, "->", is_type);
1227 try self.writeInstRef(stream, output.data.operand);1219 try self.writeInstRef(stream, output.data.operand);
...@@ -1239,8 +1231,8 @@ const Writer = struct {...@@ -1239,8 +1231,8 @@ const Writer = struct {
12391231
1240 const name = self.code.nullTerminatedString(input.data.name);1232 const name = self.code.nullTerminatedString(input.data.name);
1241 const constraint = self.code.nullTerminatedString(input.data.constraint);1233 const constraint = self.code.nullTerminatedString(input.data.constraint);
1242 try stream.print("input({p}, \"{}\", ", .{1234 try stream.print("input({f}, \"{f}\", ", .{
1243 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),1235 std.zig.fmtIdP(name), std.zig.fmtString(constraint),
1244 });1236 });
1245 try self.writeInstRef(stream, input.data.operand);1237 try self.writeInstRef(stream, input.data.operand);
1246 try stream.writeAll(")");1238 try stream.writeAll(")");
...@@ -1255,7 +1247,7 @@ const Writer = struct {...@@ -1255,7 +1247,7 @@ const Writer = struct {
1255 const str_index = self.code.extra[extra_i];1247 const str_index = self.code.extra[extra_i];
1256 extra_i += 1;1248 extra_i += 1;
1257 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));1249 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));
1258 try stream.print("{p}", .{std.zig.fmtId(clobber)});1250 try stream.print("{f}", .{std.zig.fmtIdP(clobber)});
1259 if (i + 1 < clobbers_len) {1251 if (i + 1 < clobbers_len) {
1260 try stream.writeAll(", ");1252 try stream.writeAll(", ");
1261 }1253 }
...@@ -1265,7 +1257,7 @@ const Writer = struct {...@@ -1265,7 +1257,7 @@ const Writer = struct {
1265 try self.writeSrcNode(stream, extra.data.src_node);1257 try self.writeSrcNode(stream, extra.data.src_node);
1266 }1258 }
12671259
1268 fn writeOverflowArithmetic(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1260 fn writeOverflowArithmetic(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1269 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;1261 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
12701262
1271 try self.writeInstRef(stream, extra.lhs);1263 try self.writeInstRef(stream, extra.lhs);
...@@ -1277,7 +1269,7 @@ const Writer = struct {...@@ -1277,7 +1269,7 @@ const Writer = struct {
12771269
1278 fn writeCall(1270 fn writeCall(
1279 self: *Writer,1271 self: *Writer,
1280 stream: anytype,1272 stream: *std.io.Writer,
1281 inst: Zir.Inst.Index,1273 inst: Zir.Inst.Index,
1282 comptime kind: enum { direct, field },1274 comptime kind: enum { direct, field },
1283 ) !void {1275 ) !void {
...@@ -1299,7 +1291,7 @@ const Writer = struct {...@@ -1299,7 +1291,7 @@ const Writer = struct {
1299 .field => {1291 .field => {
1300 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);1292 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
1301 try self.writeInstRef(stream, extra.data.obj_ptr);1293 try self.writeInstRef(stream, extra.data.obj_ptr);
1302 try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)});1294 try stream.print(", \"{f}\"", .{std.zig.fmtString(field_name)});
1303 },1295 },
1304 }1296 }
1305 try stream.writeAll(", [");1297 try stream.writeAll(", [");
...@@ -1311,7 +1303,7 @@ const Writer = struct {...@@ -1311,7 +1303,7 @@ const Writer = struct {
1311 var i: usize = 0;1303 var i: usize = 0;
1312 var arg_start: u32 = args_len;1304 var arg_start: u32 = args_len;
1313 while (i < args_len) : (i += 1) {1305 while (i < args_len) : (i += 1) {
1314 try stream.writeByteNTimes(' ', self.indent);1306 try stream.splatByteAll(' ', self.indent);
1315 const arg_end = self.code.extra[extra.end + i];1307 const arg_end = self.code.extra[extra.end + i];
1316 defer arg_start = arg_end;1308 defer arg_start = arg_end;
1317 const arg_body = body[arg_start..arg_end];1309 const arg_body = body[arg_start..arg_end];
...@@ -1321,14 +1313,14 @@ const Writer = struct {...@@ -1321,14 +1313,14 @@ const Writer = struct {
1321 }1313 }
1322 self.indent -= 2;1314 self.indent -= 2;
1323 if (args_len != 0) {1315 if (args_len != 0) {
1324 try stream.writeByteNTimes(' ', self.indent);1316 try stream.splatByteAll(' ', self.indent);
1325 }1317 }
13261318
1327 try stream.writeAll("]) ");1319 try stream.writeAll("]) ");
1328 try self.writeSrcNode(stream, inst_data.src_node);1320 try self.writeSrcNode(stream, inst_data.src_node);
1329 }1321 }
13301322
1331 fn writeBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1323 fn writeBlock(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1332 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1324 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1333 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);1325 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1334 const body = self.code.bodySlice(extra.end, extra.data.body_len);1326 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -1337,7 +1329,7 @@ const Writer = struct {...@@ -1337,7 +1329,7 @@ const Writer = struct {
1337 try self.writeSrcNode(stream, inst_data.src_node);1329 try self.writeSrcNode(stream, inst_data.src_node);
1338 }1330 }
13391331
1340 fn writeBlockComptime(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1332 fn writeBlockComptime(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1341 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1333 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1342 const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);1334 const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);
1343 const body = self.code.bodySlice(extra.end, extra.data.body_len);1335 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -1347,7 +1339,7 @@ const Writer = struct {...@@ -1347,7 +1339,7 @@ const Writer = struct {
1347 try self.writeSrcNode(stream, inst_data.src_node);1339 try self.writeSrcNode(stream, inst_data.src_node);
1348 }1340 }
13491341
1350 fn writeCondBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1342 fn writeCondBr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1351 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1343 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1352 const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);1344 const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
1353 const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);1345 const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);
...@@ -1361,7 +1353,7 @@ const Writer = struct {...@@ -1361,7 +1353,7 @@ const Writer = struct {
1361 try self.writeSrcNode(stream, inst_data.src_node);1353 try self.writeSrcNode(stream, inst_data.src_node);
1362 }1354 }
13631355
1364 fn writeTry(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1356 fn writeTry(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1365 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1357 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1366 const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index);1358 const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1367 const body = self.code.bodySlice(extra.end, extra.data.body_len);1359 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -1372,7 +1364,7 @@ const Writer = struct {...@@ -1372,7 +1364,7 @@ const Writer = struct {
1372 try self.writeSrcNode(stream, inst_data.src_node);1364 try self.writeSrcNode(stream, inst_data.src_node);
1373 }1365 }
13741366
1375 fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1367 fn writeStructDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1376 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);1368 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
13771369
1378 const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);1370 const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);
...@@ -1388,7 +1380,7 @@ const Writer = struct {...@@ -1388,7 +1380,7 @@ const Writer = struct {
1388 extra.data.fields_hash_3,1380 extra.data.fields_hash_3,
1389 });1381 });
13901382
1391 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});1383 try stream.print("hash({x}) ", .{&fields_hash});
13921384
1393 var extra_index: usize = extra.end;1385 var extra_index: usize = extra.end;
13941386
...@@ -1446,7 +1438,7 @@ const Writer = struct {...@@ -1446,7 +1438,7 @@ const Writer = struct {
1446 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));1438 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1447 self.indent -= 2;1439 self.indent -= 2;
1448 extra_index += decls_len;1440 extra_index += decls_len;
1449 try stream.writeByteNTimes(' ', self.indent);1441 try stream.splatByteAll(' ', self.indent);
1450 try stream.writeAll("}, ");1442 try stream.writeAll("}, ");
1451 }1443 }
14521444
...@@ -1515,11 +1507,11 @@ const Writer = struct {...@@ -1515,11 +1507,11 @@ const Writer = struct {
1515 self.indent += 2;1507 self.indent += 2;
15161508
1517 for (fields, 0..) |field, i| {1509 for (fields, 0..) |field, i| {
1518 try stream.writeByteNTimes(' ', self.indent);1510 try stream.splatByteAll(' ', self.indent);
1519 try self.writeFlag(stream, "comptime ", field.is_comptime);1511 try self.writeFlag(stream, "comptime ", field.is_comptime);
1520 if (field.name != .empty) {1512 if (field.name != .empty) {
1521 const field_name = self.code.nullTerminatedString(field.name);1513 const field_name = self.code.nullTerminatedString(field.name);
1522 try stream.print("{p}: ", .{std.zig.fmtId(field_name)});1514 try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)});
1523 } else {1515 } else {
1524 try stream.print("@\"{d}\": ", .{i});1516 try stream.print("@\"{d}\": ", .{i});
1525 }1517 }
...@@ -1558,13 +1550,13 @@ const Writer = struct {...@@ -1558,13 +1550,13 @@ const Writer = struct {
1558 }1550 }
15591551
1560 self.indent -= 2;1552 self.indent -= 2;
1561 try stream.writeByteNTimes(' ', self.indent);1553 try stream.splatByteAll(' ', self.indent);
1562 try stream.writeAll("}) ");1554 try stream.writeAll("}) ");
1563 }1555 }
1564 try self.writeSrcNode(stream, .zero);1556 try self.writeSrcNode(stream, .zero);
1565 }1557 }
15661558
1567 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1559 fn writeUnionDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1568 const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));1560 const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));
15691561
1570 const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);1562 const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);
...@@ -1580,7 +1572,7 @@ const Writer = struct {...@@ -1580,7 +1572,7 @@ const Writer = struct {
1580 extra.data.fields_hash_3,1572 extra.data.fields_hash_3,
1581 });1573 });
15821574
1583 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});1575 try stream.print("hash({x}) ", .{&fields_hash});
15841576
1585 var extra_index: usize = extra.end;1577 var extra_index: usize = extra.end;
15861578
...@@ -1630,7 +1622,7 @@ const Writer = struct {...@@ -1630,7 +1622,7 @@ const Writer = struct {
1630 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));1622 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1631 self.indent -= 2;1623 self.indent -= 2;
1632 extra_index += decls_len;1624 extra_index += decls_len;
1633 try stream.writeByteNTimes(' ', self.indent);1625 try stream.splatByteAll(' ', self.indent);
1634 try stream.writeAll("}");1626 try stream.writeAll("}");
1635 }1627 }
16361628
...@@ -1681,8 +1673,8 @@ const Writer = struct {...@@ -1681,8 +1673,8 @@ const Writer = struct {
1681 const field_name = self.code.nullTerminatedString(field_name_index);1673 const field_name = self.code.nullTerminatedString(field_name_index);
1682 extra_index += 1;1674 extra_index += 1;
16831675
1684 try stream.writeByteNTimes(' ', self.indent);1676 try stream.splatByteAll(' ', self.indent);
1685 try stream.print("{p}", .{std.zig.fmtId(field_name)});1677 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
16861678
1687 if (has_type) {1679 if (has_type) {
1688 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1680 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
...@@ -1710,12 +1702,12 @@ const Writer = struct {...@@ -1710,12 +1702,12 @@ const Writer = struct {
1710 }1702 }
17111703
1712 self.indent -= 2;1704 self.indent -= 2;
1713 try stream.writeByteNTimes(' ', self.indent);1705 try stream.splatByteAll(' ', self.indent);
1714 try stream.writeAll("}) ");1706 try stream.writeAll("}) ");
1715 try self.writeSrcNode(stream, .zero);1707 try self.writeSrcNode(stream, .zero);
1716 }1708 }
17171709
1718 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1710 fn writeEnumDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1719 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));1711 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));
17201712
1721 const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);1713 const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);
...@@ -1731,7 +1723,7 @@ const Writer = struct {...@@ -1731,7 +1723,7 @@ const Writer = struct {
1731 extra.data.fields_hash_3,1723 extra.data.fields_hash_3,
1732 });1724 });
17331725
1734 try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)});1726 try stream.print("hash({x}) ", .{&fields_hash});
17351727
1736 var extra_index: usize = extra.end;1728 var extra_index: usize = extra.end;
17371729
...@@ -1779,7 +1771,7 @@ const Writer = struct {...@@ -1779,7 +1771,7 @@ const Writer = struct {
1779 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));1771 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1780 self.indent -= 2;1772 self.indent -= 2;
1781 extra_index += decls_len;1773 extra_index += decls_len;
1782 try stream.writeByteNTimes(' ', self.indent);1774 try stream.splatByteAll(' ', self.indent);
1783 try stream.writeAll("}, ");1775 try stream.writeAll("}, ");
1784 }1776 }
17851777
...@@ -1815,8 +1807,8 @@ const Writer = struct {...@@ -1815,8 +1807,8 @@ const Writer = struct {
1815 const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));1807 const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));
1816 extra_index += 1;1808 extra_index += 1;
18171809
1818 try stream.writeByteNTimes(' ', self.indent);1810 try stream.splatByteAll(' ', self.indent);
1819 try stream.print("{p}", .{std.zig.fmtId(field_name)});1811 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
18201812
1821 if (has_tag_value) {1813 if (has_tag_value) {
1822 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1814 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
...@@ -1828,7 +1820,7 @@ const Writer = struct {...@@ -1828,7 +1820,7 @@ const Writer = struct {
1828 try stream.writeAll(",\n");1820 try stream.writeAll(",\n");
1829 }1821 }
1830 self.indent -= 2;1822 self.indent -= 2;
1831 try stream.writeByteNTimes(' ', self.indent);1823 try stream.splatByteAll(' ', self.indent);
1832 try stream.writeAll("}) ");1824 try stream.writeAll("}) ");
1833 }1825 }
1834 try self.writeSrcNode(stream, .zero);1826 try self.writeSrcNode(stream, .zero);
...@@ -1836,7 +1828,7 @@ const Writer = struct {...@@ -1836,7 +1828,7 @@ const Writer = struct {
18361828
1837 fn writeOpaqueDecl(1829 fn writeOpaqueDecl(
1838 self: *Writer,1830 self: *Writer,
1839 stream: anytype,1831 stream: *std.io.Writer,
1840 extended: Zir.Inst.Extended.InstData,1832 extended: Zir.Inst.Extended.InstData,
1841 ) !void {1833 ) !void {
1842 const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));1834 const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));
...@@ -1872,13 +1864,13 @@ const Writer = struct {...@@ -1872,13 +1864,13 @@ const Writer = struct {
1872 self.indent += 2;1864 self.indent += 2;
1873 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));1865 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1874 self.indent -= 2;1866 self.indent -= 2;
1875 try stream.writeByteNTimes(' ', self.indent);1867 try stream.splatByteAll(' ', self.indent);
1876 try stream.writeAll("}) ");1868 try stream.writeAll("}) ");
1877 }1869 }
1878 try self.writeSrcNode(stream, .zero);1870 try self.writeSrcNode(stream, .zero);
1879 }1871 }
18801872
1881 fn writeTupleDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1873 fn writeTupleDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1882 const fields_len = extended.small;1874 const fields_len = extended.small;
1883 assert(fields_len != 0);1875 assert(fields_len != 0);
1884 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);1876 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);
...@@ -1906,7 +1898,7 @@ const Writer = struct {...@@ -1906,7 +1898,7 @@ const Writer = struct {
19061898
1907 fn writeErrorSetDecl(1899 fn writeErrorSetDecl(
1908 self: *Writer,1900 self: *Writer,
1909 stream: anytype,1901 stream: *std.io.Writer,
1910 inst: Zir.Inst.Index,1902 inst: Zir.Inst.Index,
1911 ) !void {1903 ) !void {
1912 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1904 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
...@@ -1920,18 +1912,18 @@ const Writer = struct {...@@ -1920,18 +1912,18 @@ const Writer = struct {
1920 while (extra_index < extra_index_end) : (extra_index += 1) {1912 while (extra_index < extra_index_end) : (extra_index += 1) {
1921 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);1913 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1922 const name = self.code.nullTerminatedString(name_index);1914 const name = self.code.nullTerminatedString(name_index);
1923 try stream.writeByteNTimes(' ', self.indent);1915 try stream.splatByteAll(' ', self.indent);
1924 try stream.print("{p},\n", .{std.zig.fmtId(name)});1916 try stream.print("{f},\n", .{std.zig.fmtIdP(name)});
1925 }1917 }
19261918
1927 self.indent -= 2;1919 self.indent -= 2;
1928 try stream.writeByteNTimes(' ', self.indent);1920 try stream.splatByteAll(' ', self.indent);
1929 try stream.writeAll("}) ");1921 try stream.writeAll("}) ");
19301922
1931 try self.writeSrcNode(stream, inst_data.src_node);1923 try self.writeSrcNode(stream, inst_data.src_node);
1932 }1924 }
19331925
1934 fn writeSwitchBlockErrUnion(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1926 fn writeSwitchBlockErrUnion(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
1935 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1927 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1936 const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);1928 const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);
19371929
...@@ -1967,7 +1959,7 @@ const Writer = struct {...@@ -1967,7 +1959,7 @@ const Writer = struct {
1967 extra_index += body.len;1959 extra_index += body.len;
19681960
1969 try stream.writeAll(",\n");1961 try stream.writeAll(",\n");
1970 try stream.writeByteNTimes(' ', self.indent);1962 try stream.splatByteAll(' ', self.indent);
1971 try stream.writeAll("non_err => ");1963 try stream.writeAll("non_err => ");
1972 try self.writeBracedBody(stream, body);1964 try self.writeBracedBody(stream, body);
1973 }1965 }
...@@ -1985,7 +1977,7 @@ const Writer = struct {...@@ -1985,7 +1977,7 @@ const Writer = struct {
1985 extra_index += body.len;1977 extra_index += body.len;
19861978
1987 try stream.writeAll(",\n");1979 try stream.writeAll(",\n");
1988 try stream.writeByteNTimes(' ', self.indent);1980 try stream.splatByteAll(' ', self.indent);
1989 try stream.print("{s}{s}else => ", .{ capture_text, inline_text });1981 try stream.print("{s}{s}else => ", .{ capture_text, inline_text });
1990 try self.writeBracedBody(stream, body);1982 try self.writeBracedBody(stream, body);
1991 }1983 }
...@@ -2002,7 +1994,7 @@ const Writer = struct {...@@ -2002,7 +1994,7 @@ const Writer = struct {
2002 extra_index += info.body_len;1994 extra_index += info.body_len;
20031995
2004 try stream.writeAll(",\n");1996 try stream.writeAll(",\n");
2005 try stream.writeByteNTimes(' ', self.indent);1997 try stream.splatByteAll(' ', self.indent);
2006 switch (info.capture) {1998 switch (info.capture) {
2007 .none => {},1999 .none => {},
2008 .by_val => try stream.writeAll("by_val "),2000 .by_val => try stream.writeAll("by_val "),
...@@ -2027,7 +2019,7 @@ const Writer = struct {...@@ -2027,7 +2019,7 @@ const Writer = struct {
2027 extra_index += items_len;2019 extra_index += items_len;
20282020
2029 try stream.writeAll(",\n");2021 try stream.writeAll(",\n");
2030 try stream.writeByteNTimes(' ', self.indent);2022 try stream.splatByteAll(' ', self.indent);
2031 switch (info.capture) {2023 switch (info.capture) {
2032 .none => {},2024 .none => {},
2033 .by_val => try stream.writeAll("by_val "),2025 .by_val => try stream.writeAll("by_val "),
...@@ -2068,7 +2060,7 @@ const Writer = struct {...@@ -2068,7 +2060,7 @@ const Writer = struct {
2068 try self.writeSrcNode(stream, inst_data.src_node);2060 try self.writeSrcNode(stream, inst_data.src_node);
2069 }2061 }
20702062
2071 fn writeSwitchBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2063 fn writeSwitchBlock(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2072 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2064 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2073 const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);2065 const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
20742066
...@@ -2115,7 +2107,7 @@ const Writer = struct {...@@ -2115,7 +2107,7 @@ const Writer = struct {
2115 extra_index += body.len;2107 extra_index += body.len;
21162108
2117 try stream.writeAll(",\n");2109 try stream.writeAll(",\n");
2118 try stream.writeByteNTimes(' ', self.indent);2110 try stream.splatByteAll(' ', self.indent);
2119 try stream.print("{s}{s}{s} => ", .{ capture_text, inline_text, prong_name });2111 try stream.print("{s}{s}{s} => ", .{ capture_text, inline_text, prong_name });
2120 try self.writeBracedBody(stream, body);2112 try self.writeBracedBody(stream, body);
2121 }2113 }
...@@ -2132,7 +2124,7 @@ const Writer = struct {...@@ -2132,7 +2124,7 @@ const Writer = struct {
2132 extra_index += info.body_len;2124 extra_index += info.body_len;
21332125
2134 try stream.writeAll(",\n");2126 try stream.writeAll(",\n");
2135 try stream.writeByteNTimes(' ', self.indent);2127 try stream.splatByteAll(' ', self.indent);
2136 switch (info.capture) {2128 switch (info.capture) {
2137 .none => {},2129 .none => {},
2138 .by_val => try stream.writeAll("by_val "),2130 .by_val => try stream.writeAll("by_val "),
...@@ -2157,7 +2149,7 @@ const Writer = struct {...@@ -2157,7 +2149,7 @@ const Writer = struct {
2157 extra_index += items_len;2149 extra_index += items_len;
21582150
2159 try stream.writeAll(",\n");2151 try stream.writeAll(",\n");
2160 try stream.writeByteNTimes(' ', self.indent);2152 try stream.splatByteAll(' ', self.indent);
2161 switch (info.capture) {2153 switch (info.capture) {
2162 .none => {},2154 .none => {},
2163 .by_val => try stream.writeAll("by_val "),2155 .by_val => try stream.writeAll("by_val "),
...@@ -2198,16 +2190,16 @@ const Writer = struct {...@@ -2198,16 +2190,16 @@ const Writer = struct {
2198 try self.writeSrcNode(stream, inst_data.src_node);2190 try self.writeSrcNode(stream, inst_data.src_node);
2199 }2191 }
22002192
2201 fn writePlNodeField(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2193 fn writePlNodeField(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2202 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2194 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2203 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;2195 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
2204 const name = self.code.nullTerminatedString(extra.field_name_start);2196 const name = self.code.nullTerminatedString(extra.field_name_start);
2205 try self.writeInstRef(stream, extra.lhs);2197 try self.writeInstRef(stream, extra.lhs);
2206 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});2198 try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)});
2207 try self.writeSrcNode(stream, inst_data.src_node);2199 try self.writeSrcNode(stream, inst_data.src_node);
2208 }2200 }
22092201
2210 fn writePlNodeFieldNamed(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2202 fn writePlNodeFieldNamed(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2211 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2203 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2212 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;2204 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
2213 try self.writeInstRef(stream, extra.lhs);2205 try self.writeInstRef(stream, extra.lhs);
...@@ -2217,7 +2209,7 @@ const Writer = struct {...@@ -2217,7 +2209,7 @@ const Writer = struct {
2217 try self.writeSrcNode(stream, inst_data.src_node);2209 try self.writeSrcNode(stream, inst_data.src_node);
2218 }2210 }
22192211
2220 fn writeAs(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2212 fn writeAs(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2221 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2213 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2222 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;2214 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
2223 try self.writeInstRef(stream, extra.dest_type);2215 try self.writeInstRef(stream, extra.dest_type);
...@@ -2229,9 +2221,9 @@ const Writer = struct {...@@ -2229,9 +2221,9 @@ const Writer = struct {
22292221
2230 fn writeNode(2222 fn writeNode(
2231 self: *Writer,2223 self: *Writer,
2232 stream: anytype,2224 stream: *std.io.Writer,
2233 inst: Zir.Inst.Index,2225 inst: Zir.Inst.Index,
2234 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {2226 ) Error!void {
2235 const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node;2227 const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node;
2236 try stream.writeAll(") ");2228 try stream.writeAll(") ");
2237 try self.writeSrcNode(stream, src_node);2229 try self.writeSrcNode(stream, src_node);
...@@ -2239,25 +2231,25 @@ const Writer = struct {...@@ -2239,25 +2231,25 @@ const Writer = struct {
22392231
2240 fn writeStrTok(2232 fn writeStrTok(
2241 self: *Writer,2233 self: *Writer,
2242 stream: anytype,2234 stream: *std.io.Writer,
2243 inst: Zir.Inst.Index,2235 inst: Zir.Inst.Index,
2244 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {2236 ) Error!void {
2245 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;2237 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
2246 const str = inst_data.get(self.code);2238 const str = inst_data.get(self.code);
2247 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});2239 try stream.print("\"{f}\") ", .{std.zig.fmtString(str)});
2248 try self.writeSrcTok(stream, inst_data.src_tok);2240 try self.writeSrcTok(stream, inst_data.src_tok);
2249 }2241 }
22502242
2251 fn writeStrOp(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2243 fn writeStrOp(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2252 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;2244 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
2253 const str = inst_data.getStr(self.code);2245 const str = inst_data.getStr(self.code);
2254 try self.writeInstRef(stream, inst_data.operand);2246 try self.writeInstRef(stream, inst_data.operand);
2255 try stream.print(", \"{}\")", .{std.zig.fmtEscapes(str)});2247 try stream.print(", \"{f}\")", .{std.zig.fmtString(str)});
2256 }2248 }
22572249
2258 fn writeFunc(2250 fn writeFunc(
2259 self: *Writer,2251 self: *Writer,
2260 stream: anytype,2252 stream: *std.io.Writer,
2261 inst: Zir.Inst.Index,2253 inst: Zir.Inst.Index,
2262 inferred_error_set: bool,2254 inferred_error_set: bool,
2263 ) !void {2255 ) !void {
...@@ -2308,7 +2300,7 @@ const Writer = struct {...@@ -2308,7 +2300,7 @@ const Writer = struct {
2308 );2300 );
2309 }2301 }
23102302
2311 fn writeFuncFancy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2303 fn writeFuncFancy(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2312 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2304 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2313 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);2305 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
23142306
...@@ -2367,7 +2359,7 @@ const Writer = struct {...@@ -2367,7 +2359,7 @@ const Writer = struct {
2367 );2359 );
2368 }2360 }
23692361
2370 fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2362 fn writeAllocExtended(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2371 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);2363 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
2372 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));2364 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
23732365
...@@ -2390,7 +2382,7 @@ const Writer = struct {...@@ -2390,7 +2382,7 @@ const Writer = struct {
2390 try self.writeSrcNode(stream, extra.data.src_node);2382 try self.writeSrcNode(stream, extra.data.src_node);
2391 }2383 }
23922384
2393 fn writeTypeofPeer(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2385 fn writeTypeofPeer(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2394 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);2386 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
2395 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);2387 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);
2396 try self.writeBracedBody(stream, body);2388 try self.writeBracedBody(stream, body);
...@@ -2403,7 +2395,7 @@ const Writer = struct {...@@ -2403,7 +2395,7 @@ const Writer = struct {
2403 try stream.writeAll("])");2395 try stream.writeAll("])");
2404 }2396 }
24052397
2406 fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2398 fn writeBoolBr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2407 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2399 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2408 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);2400 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
2409 const body = self.code.bodySlice(extra.end, extra.data.body_len);2401 const body = self.code.bodySlice(extra.end, extra.data.body_len);
...@@ -2414,7 +2406,7 @@ const Writer = struct {...@@ -2414,7 +2406,7 @@ const Writer = struct {
2414 try self.writeSrcNode(stream, inst_data.src_node);2406 try self.writeSrcNode(stream, inst_data.src_node);
2415 }2407 }
24162408
2417 fn writeIntType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2409 fn writeIntType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2418 const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type;2410 const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type;
2419 const prefix: u8 = switch (int_type.signedness) {2411 const prefix: u8 = switch (int_type.signedness) {
2420 .signed => 'i',2412 .signed => 'i',
...@@ -2424,7 +2416,7 @@ const Writer = struct {...@@ -2424,7 +2416,7 @@ const Writer = struct {
2424 try self.writeSrcNode(stream, int_type.src_node);2416 try self.writeSrcNode(stream, int_type.src_node);
2425 }2417 }
24262418
2427 fn writeSaveErrRetIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2419 fn writeSaveErrRetIndex(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2428 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index;2420 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index;
24292421
2430 try self.writeInstRef(stream, inst_data.operand);2422 try self.writeInstRef(stream, inst_data.operand);
...@@ -2432,7 +2424,7 @@ const Writer = struct {...@@ -2432,7 +2424,7 @@ const Writer = struct {
2432 try stream.writeAll(")");2424 try stream.writeAll(")");
2433 }2425 }
24342426
2435 fn writeRestoreErrRetIndex(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2427 fn writeRestoreErrRetIndex(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2436 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;2428 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
24372429
2438 try self.writeInstRef(stream, extra.block);2430 try self.writeInstRef(stream, extra.block);
...@@ -2442,7 +2434,7 @@ const Writer = struct {...@@ -2442,7 +2434,7 @@ const Writer = struct {
2442 try self.writeSrcNode(stream, extra.src_node);2434 try self.writeSrcNode(stream, extra.src_node);
2443 }2435 }
24442436
2445 fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2437 fn writeBreak(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2446 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break";2438 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break";
2447 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;2439 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
24482440
...@@ -2452,7 +2444,7 @@ const Writer = struct {...@@ -2452,7 +2444,7 @@ const Writer = struct {
2452 try stream.writeAll(")");2444 try stream.writeAll(")");
2453 }2445 }
24542446
2455 fn writeArrayInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2447 fn writeArrayInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2456 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2448 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24572449
2458 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);2450 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
...@@ -2468,7 +2460,7 @@ const Writer = struct {...@@ -2468,7 +2460,7 @@ const Writer = struct {
2468 try self.writeSrcNode(stream, inst_data.src_node);2460 try self.writeSrcNode(stream, inst_data.src_node);
2469 }2461 }
24702462
2471 fn writeArrayInitAnon(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2463 fn writeArrayInitAnon(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2472 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2464 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24732465
2474 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);2466 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
...@@ -2483,7 +2475,7 @@ const Writer = struct {...@@ -2483,7 +2475,7 @@ const Writer = struct {
2483 try self.writeSrcNode(stream, inst_data.src_node);2475 try self.writeSrcNode(stream, inst_data.src_node);
2484 }2476 }
24852477
2486 fn writeArrayInitSent(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2478 fn writeArrayInitSent(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2487 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;2479 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24882480
2489 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);2481 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
...@@ -2503,7 +2495,7 @@ const Writer = struct {...@@ -2503,7 +2495,7 @@ const Writer = struct {
2503 try self.writeSrcNode(stream, inst_data.src_node);2495 try self.writeSrcNode(stream, inst_data.src_node);
2504 }2496 }
25052497
2506 fn writeUnreachable(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2498 fn writeUnreachable(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2507 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";2499 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";
2508 try stream.writeAll(") ");2500 try stream.writeAll(") ");
2509 try self.writeSrcNode(stream, inst_data.src_node);2501 try self.writeSrcNode(stream, inst_data.src_node);
...@@ -2511,7 +2503,7 @@ const Writer = struct {...@@ -2511,7 +2503,7 @@ const Writer = struct {
25112503
2512 fn writeFuncCommon(2504 fn writeFuncCommon(
2513 self: *Writer,2505 self: *Writer,
2514 stream: anytype,2506 stream: *std.io.Writer,
2515 inferred_error_set: bool,2507 inferred_error_set: bool,
2516 var_args: bool,2508 var_args: bool,
2517 is_noinline: bool,2509 is_noinline: bool,
...@@ -2548,19 +2540,19 @@ const Writer = struct {...@@ -2548,19 +2540,19 @@ const Writer = struct {
2548 try self.writeSrcNode(stream, src_node);2540 try self.writeSrcNode(stream, src_node);
2549 }2541 }
25502542
2551 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2543 fn writeDbgStmt(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2552 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;2544 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
2553 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });2545 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });
2554 }2546 }
25552547
2556 fn writeDefer(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2548 fn writeDefer(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2557 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";2549 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";
2558 const body = self.code.bodySlice(inst_data.index, inst_data.len);2550 const body = self.code.bodySlice(inst_data.index, inst_data.len);
2559 try self.writeBracedBody(stream, body);2551 try self.writeBracedBody(stream, body);
2560 try stream.writeByte(')');2552 try stream.writeByte(')');
2561 }2553 }
25622554
2563 fn writeDeferErrCode(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2555 fn writeDeferErrCode(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2564 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;2556 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;
2565 const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;2557 const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
25662558
...@@ -2573,7 +2565,7 @@ const Writer = struct {...@@ -2573,7 +2565,7 @@ const Writer = struct {
2573 try stream.writeByte(')');2565 try stream.writeByte(')');
2574 }2566 }
25752567
2576 fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2568 fn writeDeclaration(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2577 const decl = self.code.getDeclaration(inst);2569 const decl = self.code.getDeclaration(inst);
25782570
2579 const prev_parent_decl_node = self.parent_decl_node;2571 const prev_parent_decl_node = self.parent_decl_node;
...@@ -2594,10 +2586,8 @@ const Writer = struct {...@@ -2594,10 +2586,8 @@ const Writer = struct {
2594 },2586 },
2595 }2587 }
2596 const src_hash = self.code.getAssociatedSrcHash(inst).?;2588 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2597 try stream.print(" line({d}) column({d}) hash({})", .{2589 try stream.print(" line({d}) column({d}) hash({x})", .{
2598 decl.src_line,2590 decl.src_line, decl.src_column, &src_hash,
2599 decl.src_column,
2600 std.fmt.fmtSliceHexLower(&src_hash),
2601 });2591 });
26022592
2603 {2593 {
...@@ -2631,26 +2621,26 @@ const Writer = struct {...@@ -2631,26 +2621,26 @@ const Writer = struct {
2631 try self.writeSrcNode(stream, .zero);2621 try self.writeSrcNode(stream, .zero);
2632 }2622 }
26332623
2634 fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2624 fn writeClosureGet(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2635 try stream.print("{d})) ", .{extended.small});2625 try stream.print("{d})) ", .{extended.small});
2636 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));2626 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
2637 try self.writeSrcNode(stream, src_node);2627 try self.writeSrcNode(stream, src_node);
2638 }2628 }
26392629
2640 fn writeBuiltinValue(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2630 fn writeBuiltinValue(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2641 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);2631 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2642 try stream.print("{s})) ", .{@tagName(val)});2632 try stream.print("{s})) ", .{@tagName(val)});
2643 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));2633 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
2644 try self.writeSrcNode(stream, src_node);2634 try self.writeSrcNode(stream, src_node);
2645 }2635 }
26462636
2647 fn writeInplaceArithResultTy(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2637 fn writeInplaceArithResultTy(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2648 const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small);2638 const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small);
2649 try self.writeInstRef(stream, @enumFromInt(extended.operand));2639 try self.writeInstRef(stream, @enumFromInt(extended.operand));
2650 try stream.print(", {s}))", .{@tagName(op)});2640 try stream.print(", {s}))", .{@tagName(op)});
2651 }2641 }
26522642
2653 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {2643 fn writeInstRef(self: *Writer, stream: *std.io.Writer, ref: Zir.Inst.Ref) !void {
2654 if (ref == .none) {2644 if (ref == .none) {
2655 return stream.writeAll(".none");2645 return stream.writeAll(".none");
2656 } else if (ref.toIndex()) |i| {2646 } else if (ref.toIndex()) |i| {
...@@ -2661,12 +2651,12 @@ const Writer = struct {...@@ -2661,12 +2651,12 @@ const Writer = struct {
2661 }2651 }
2662 }2652 }
26632653
2664 fn writeInstIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2654 fn writeInstIndex(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2665 _ = self;2655 _ = self;
2666 return stream.print("%{d}", .{@intFromEnum(inst)});2656 return stream.print("%{d}", .{@intFromEnum(inst)});
2667 }2657 }
26682658
2669 fn writeCaptures(self: *Writer, stream: anytype, extra_index: usize, captures_len: u32) !usize {2659 fn writeCaptures(self: *Writer, stream: *std.io.Writer, extra_index: usize, captures_len: u32) !usize {
2670 if (captures_len == 0) {2660 if (captures_len == 0) {
2671 try stream.writeAll("{}");2661 try stream.writeAll("{}");
2672 return extra_index;2662 return extra_index;
...@@ -2686,7 +2676,7 @@ const Writer = struct {...@@ -2686,7 +2676,7 @@ const Writer = struct {
2686 return extra_index + 2 * captures_len;2676 return extra_index + 2 * captures_len;
2687 }2677 }
26882678
2689 fn writeCapture(self: *Writer, stream: anytype, capture: Zir.Inst.Capture) !void {2679 fn writeCapture(self: *Writer, stream: *std.io.Writer, capture: Zir.Inst.Capture) !void {
2690 switch (capture.unwrap()) {2680 switch (capture.unwrap()) {
2691 .nested => |i| return stream.print("[{d}]", .{i}),2681 .nested => |i| return stream.print("[{d}]", .{i}),
2692 .instruction => |inst| return self.writeInstIndex(stream, inst),2682 .instruction => |inst| return self.writeInstIndex(stream, inst),
...@@ -2694,18 +2684,18 @@ const Writer = struct {...@@ -2694,18 +2684,18 @@ const Writer = struct {
2694 try stream.writeAll("load ");2684 try stream.writeAll("load ");
2695 try self.writeInstIndex(stream, ptr_inst);2685 try self.writeInstIndex(stream, ptr_inst);
2696 },2686 },
2697 .decl_val => |str| try stream.print("decl_val \"{}\"", .{2687 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{
2698 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),2688 std.zig.fmtString(self.code.nullTerminatedString(str)),
2699 }),2689 }),
2700 .decl_ref => |str| try stream.print("decl_ref \"{}\"", .{2690 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
2701 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),2691 std.zig.fmtString(self.code.nullTerminatedString(str)),
2702 }),2692 }),
2703 }2693 }
2704 }2694 }
27052695
2706 fn writeOptionalInstRef(2696 fn writeOptionalInstRef(
2707 self: *Writer,2697 self: *Writer,
2708 stream: anytype,2698 stream: *std.io.Writer,
2709 prefix: []const u8,2699 prefix: []const u8,
2710 inst: Zir.Inst.Ref,2700 inst: Zir.Inst.Ref,
2711 ) !void {2701 ) !void {
...@@ -2716,7 +2706,7 @@ const Writer = struct {...@@ -2716,7 +2706,7 @@ const Writer = struct {
27162706
2717 fn writeOptionalInstRefOrBody(2707 fn writeOptionalInstRefOrBody(
2718 self: *Writer,2708 self: *Writer,
2719 stream: anytype,2709 stream: *std.io.Writer,
2720 prefix: []const u8,2710 prefix: []const u8,
2721 ref: Zir.Inst.Ref,2711 ref: Zir.Inst.Ref,
2722 body: []const Zir.Inst.Index,2712 body: []const Zir.Inst.Index,
...@@ -2734,7 +2724,7 @@ const Writer = struct {...@@ -2734,7 +2724,7 @@ const Writer = struct {
27342724
2735 fn writeFlag(2725 fn writeFlag(
2736 self: *Writer,2726 self: *Writer,
2737 stream: anytype,2727 stream: *std.io.Writer,
2738 name: []const u8,2728 name: []const u8,
2739 flag: bool,2729 flag: bool,
2740 ) !void {2730 ) !void {
...@@ -2743,7 +2733,7 @@ const Writer = struct {...@@ -2743,7 +2733,7 @@ const Writer = struct {
2743 try stream.writeAll(name);2733 try stream.writeAll(name);
2744 }2734 }
27452735
2746 fn writeSrcNode(self: *Writer, stream: anytype, src_node: Ast.Node.Offset) !void {2736 fn writeSrcNode(self: *Writer, stream: *std.io.Writer, src_node: Ast.Node.Offset) !void {
2747 const tree = self.tree orelse return;2737 const tree = self.tree orelse return;
2748 const abs_node = src_node.toAbsolute(self.parent_decl_node);2738 const abs_node = src_node.toAbsolute(self.parent_decl_node);
2749 const src_span = tree.nodeToSpan(abs_node);2739 const src_span = tree.nodeToSpan(abs_node);
...@@ -2755,7 +2745,7 @@ const Writer = struct {...@@ -2755,7 +2745,7 @@ const Writer = struct {
2755 });2745 });
2756 }2746 }
27572747
2758 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: Ast.TokenOffset) !void {2748 fn writeSrcTok(self: *Writer, stream: *std.io.Writer, src_tok: Ast.TokenOffset) !void {
2759 const tree = self.tree orelse return;2749 const tree = self.tree orelse return;
2760 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));2750 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2761 const span_start = tree.tokenStart(abs_tok);2751 const span_start = tree.tokenStart(abs_tok);
...@@ -2768,7 +2758,7 @@ const Writer = struct {...@@ -2768,7 +2758,7 @@ const Writer = struct {
2768 });2758 });
2769 }2759 }
27702760
2771 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: Ast.TokenIndex) !void {2761 fn writeSrcTokAbs(self: *Writer, stream: *std.io.Writer, src_tok: Ast.TokenIndex) !void {
2772 const tree = self.tree orelse return;2762 const tree = self.tree orelse return;
2773 const span_start = tree.tokenStart(src_tok);2763 const span_start = tree.tokenStart(src_tok);
2774 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));2764 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
...@@ -2780,15 +2770,15 @@ const Writer = struct {...@@ -2780,15 +2770,15 @@ const Writer = struct {
2780 });2770 });
2781 }2771 }
27822772
2783 fn writeBracedDecl(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void {2773 fn writeBracedDecl(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
2784 try self.writeBracedBodyConditional(stream, body, self.recurse_decls);2774 try self.writeBracedBodyConditional(stream, body, self.recurse_decls);
2785 }2775 }
27862776
2787 fn writeBracedBody(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void {2777 fn writeBracedBody(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
2788 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);2778 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);
2789 }2779 }
27902780
2791 fn writeBracedBodyConditional(self: *Writer, stream: anytype, body: []const Zir.Inst.Index, enabled: bool) !void {2781 fn writeBracedBodyConditional(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index, enabled: bool) !void {
2792 if (body.len == 0) {2782 if (body.len == 0) {
2793 try stream.writeAll("{}");2783 try stream.writeAll("{}");
2794 } else if (enabled) {2784 } else if (enabled) {
...@@ -2796,7 +2786,7 @@ const Writer = struct {...@@ -2796,7 +2786,7 @@ const Writer = struct {
2796 self.indent += 2;2786 self.indent += 2;
2797 try self.writeBody(stream, body);2787 try self.writeBody(stream, body);
2798 self.indent -= 2;2788 self.indent -= 2;
2799 try stream.writeByteNTimes(' ', self.indent);2789 try stream.splatByteAll(' ', self.indent);
2800 try stream.writeAll("}");2790 try stream.writeAll("}");
2801 } else if (body.len == 1) {2791 } else if (body.len == 1) {
2802 try stream.writeByte('{');2792 try stream.writeByte('{');
...@@ -2817,21 +2807,21 @@ const Writer = struct {...@@ -2817,21 +2807,21 @@ const Writer = struct {
2817 }2807 }
2818 }2808 }
28192809
2820 fn writeBody(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void {2810 fn writeBody(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
2821 for (body) |inst| {2811 for (body) |inst| {
2822 try stream.writeByteNTimes(' ', self.indent);2812 try stream.splatByteAll(' ', self.indent);
2823 try stream.print("%{d} ", .{@intFromEnum(inst)});2813 try stream.print("%{d} ", .{@intFromEnum(inst)});
2824 try self.writeInstToStream(stream, inst);2814 try self.writeInstToStream(stream, inst);
2825 try stream.writeByte('\n');2815 try stream.writeByte('\n');
2826 }2816 }
2827 }2817 }
28282818
2829 fn writeImport(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2819 fn writeImport(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
2830 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;2820 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
2831 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;2821 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
2832 try self.writeInstRef(stream, extra.res_ty);2822 try self.writeInstRef(stream, extra.res_ty);
2833 const import_path = self.code.nullTerminatedString(extra.path);2823 const import_path = self.code.nullTerminatedString(extra.path);
2834 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(import_path)});2824 try stream.print(", \"{f}\") ", .{std.zig.fmtString(import_path)});
2835 try self.writeSrcTok(stream, inst_data.src_tok);2825 try self.writeSrcTok(stream, inst_data.src_tok);
2836 }2826 }
2837};2827};
src/print_zoir.zig+22-28
...@@ -1,13 +1,8 @@...@@ -1,13 +1,8 @@
1pub fn renderToFile(zoir: Zoir, arena: Allocator, f: std.fs.File) (std.fs.File.WriteError || Allocator.Error)!void {1pub const Error = error{ WriteFailed, OutOfMemory };
2 var bw = std.io.bufferedWriter(f.writer());
3 try renderToWriter(zoir, arena, bw.writer());
4 try bw.flush();
5}
62
7pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Error || Allocator.Error)!void {3pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *Writer) Error!void {
8 assert(!zoir.hasCompileErrors());4 assert(!zoir.hasCompileErrors());
95
10 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
11 const bytes_per_node = comptime n: {6 const bytes_per_node = comptime n: {
12 var n: usize = 0;7 var n: usize = 0;
13 for (@typeInfo(Zoir.Node.Repr).@"struct".fields) |f| {8 for (@typeInfo(Zoir.Node.Repr).@"struct".fields) |f| {
...@@ -23,42 +18,42 @@ pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Erro...@@ -23,42 +18,42 @@ pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Erro
2318
24 // zig fmt: off19 // zig fmt: off
25 try w.print(20 try w.print(
26 \\# Nodes: {} ({})21 \\# Nodes: {} ({Bi})
27 \\# Extra Data Items: {} ({})22 \\# Extra Data Items: {} ({Bi})
28 \\# BigInt Limbs: {} ({})23 \\# BigInt Limbs: {} ({Bi})
29 \\# String Table Bytes: {}24 \\# String Table Bytes: {Bi}
30 \\# Total ZON Bytes: {}25 \\# Total ZON Bytes: {Bi}
31 \\26 \\
32 , .{27 , .{
33 zoir.nodes.len, fmtIntSizeBin(node_bytes),28 zoir.nodes.len, node_bytes,
34 zoir.extra.len, fmtIntSizeBin(extra_bytes),29 zoir.extra.len, extra_bytes,
35 zoir.limbs.len, fmtIntSizeBin(limb_bytes),30 zoir.limbs.len, limb_bytes,
36 fmtIntSizeBin(string_bytes),31 string_bytes,
37 fmtIntSizeBin(node_bytes + extra_bytes + limb_bytes + string_bytes),32 node_bytes + extra_bytes + limb_bytes + string_bytes,
38 });33 });
39 // zig fmt: on34 // zig fmt: on
40 var pz: PrintZon = .{35 var pz: PrintZon = .{
41 .w = w.any(),36 .w = w,
42 .arena = arena,37 .arena = arena,
43 .zoir = zoir,38 .zoir = zoir,
44 .indent = 0,39 .indent = 0,
45 };40 };
4641
47 return @errorCast(pz.renderRoot());42 return pz.renderRoot();
48}43}
4944
50const PrintZon = struct {45const PrintZon = struct {
51 w: std.io.AnyWriter,46 w: *Writer,
52 arena: Allocator,47 arena: Allocator,
53 zoir: Zoir,48 zoir: Zoir,
54 indent: u32,49 indent: u32,
5550
56 fn renderRoot(pz: *PrintZon) anyerror!void {51 fn renderRoot(pz: *PrintZon) Error!void {
57 try pz.renderNode(.root);52 try pz.renderNode(.root);
58 try pz.w.writeByte('\n');53 try pz.w.writeByte('\n');
59 }54 }
6055
61 fn renderNode(pz: *PrintZon, node: Zoir.Node.Index) anyerror!void {56 fn renderNode(pz: *PrintZon, node: Zoir.Node.Index) Error!void {
62 const zoir = pz.zoir;57 const zoir = pz.zoir;
63 try pz.w.print("%{d} = ", .{@intFromEnum(node)});58 try pz.w.print("%{d} = ", .{@intFromEnum(node)});
64 switch (node.get(zoir)) {59 switch (node.get(zoir)) {
...@@ -77,8 +72,8 @@ const PrintZon = struct {...@@ -77,8 +72,8 @@ const PrintZon = struct {
77 },72 },
78 .float_literal => |x| try pz.w.print("float({d})", .{x}),73 .float_literal => |x| try pz.w.print("float({d})", .{x}),
79 .char_literal => |x| try pz.w.print("char({d})", .{x}),74 .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))}),75 .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)}),76 .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtString(x)}),
82 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),77 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),
83 .array_literal => |vals| {78 .array_literal => |vals| {
84 try pz.w.writeAll("array_literal({");79 try pz.w.writeAll("array_literal({");
...@@ -97,7 +92,7 @@ const PrintZon = struct {...@@ -97,7 +92,7 @@ const PrintZon = struct {
97 pz.indent += 1;92 pz.indent += 1;
98 for (s.names, 0..s.vals.len) |name, idx| {93 for (s.names, 0..s.vals.len) |name, idx| {
99 try pz.newline();94 try pz.newline();
100 try pz.w.print("[{p}] ", .{std.zig.fmtId(name.get(zoir))});95 try pz.w.print("[{f}] ", .{std.zig.fmtIdP(name.get(zoir))});
101 try pz.renderNode(s.vals.at(@intCast(idx)));96 try pz.renderNode(s.vals.at(@intCast(idx)));
102 try pz.w.writeByte(',');97 try pz.w.writeByte(',');
103 }98 }
...@@ -110,9 +105,7 @@ const PrintZon = struct {...@@ -110,9 +105,7 @@ const PrintZon = struct {
110105
111 fn newline(pz: *PrintZon) !void {106 fn newline(pz: *PrintZon) !void {
112 try pz.w.writeByte('\n');107 try pz.w.writeByte('\n');
113 for (0..pz.indent) |_| {108 try pz.w.splatByteAll(' ', 2 * pz.indent);
114 try pz.w.writeByteNTimes(' ', 2);
115 }
116 }109 }
117};110};
118111
...@@ -120,3 +113,4 @@ const std = @import("std");...@@ -120,3 +113,4 @@ const std = @import("std");
120const assert = std.debug.assert;113const assert = std.debug.assert;
121const Allocator = std.mem.Allocator;114const Allocator = std.mem.Allocator;
122const Zoir = std.zig.Zoir;115const Zoir = std.zig.Zoir;
116const Writer = std.io.Writer;
src/register_manager.zig+3-3
...@@ -238,7 +238,7 @@ pub fn RegisterManager(...@@ -238,7 +238,7 @@ pub fn RegisterManager(
238 if (i < count) return null;238 if (i < count) return null;
239239
240 for (regs, insts) |reg, inst| {240 for (regs, insts) |reg, inst| {
241 log.debug("tryAllocReg {} for inst {?}", .{ reg, inst });241 log.debug("tryAllocReg {} for inst {?f}", .{ reg, inst });
242 self.markRegAllocated(reg);242 self.markRegAllocated(reg);
243243
244 if (inst) |tracked_inst| {244 if (inst) |tracked_inst| {
...@@ -317,7 +317,7 @@ pub fn RegisterManager(...@@ -317,7 +317,7 @@ pub fn RegisterManager(
317 tracked_index: TrackedIndex,317 tracked_index: TrackedIndex,
318 inst: ?Air.Inst.Index,318 inst: ?Air.Inst.Index,
319 ) AllocationError!void {319 ) AllocationError!void {
320 log.debug("getReg {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst });320 log.debug("getReg {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst });
321 if (!self.isRegIndexFree(tracked_index)) {321 if (!self.isRegIndexFree(tracked_index)) {
322 // Move the instruction that was previously there to a322 // Move the instruction that was previously there to a
323 // stack allocation.323 // stack allocation.
...@@ -349,7 +349,7 @@ pub fn RegisterManager(...@@ -349,7 +349,7 @@ pub fn RegisterManager(
349 tracked_index: TrackedIndex,349 tracked_index: TrackedIndex,
350 inst: ?Air.Inst.Index,350 inst: ?Air.Inst.Index,
351 ) void {351 ) void {
352 log.debug("getRegAssumeFree {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst });352 log.debug("getRegAssumeFree {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst });
353 self.markRegIndexAllocated(tracked_index);353 self.markRegIndexAllocated(tracked_index);
354354
355 assert(self.isRegIndexFree(tracked_index));355 assert(self.isRegIndexFree(tracked_index));
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, .{ .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, .{ .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, .{ .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: usize = @intCast(std.fmt.count("{f}", .{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, "{f}", .{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 },
stage1/wasi.c+18-6
...@@ -520,12 +520,15 @@ uint32_t wasi_snapshot_preview1_fd_read(uint32_t fd, uint32_t iovs, uint32_t iov...@@ -520,12 +520,15 @@ uint32_t wasi_snapshot_preview1_fd_read(uint32_t fd, uint32_t iovs, uint32_t iov
520 default: panic("unimplemented: fd_read special file");520 default: panic("unimplemented: fd_read special file");
521 }521 }
522522
523 if (fds[fd].stream == NULL) {
524 store32_align2(res_size_ptr, 0);
525 return wasi_errno_success;
526 }
527
523 size_t size = 0;528 size_t size = 0;
524 for (uint32_t i = 0; i < iovs_len; i += 1) {529 for (uint32_t i = 0; i < iovs_len; i += 1) {
525 uint32_t len = load32_align2(&iovs_ptr[i].len);530 uint32_t len = load32_align2(&iovs_ptr[i].len);
526 size_t read_size = 0;531 size_t read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
527 if (fds[fd].stream != NULL)
528 read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
529 size += read_size;532 size += read_size;
530 if (read_size < len) break;533 if (read_size < len) break;
531 }534 }
...@@ -633,8 +636,10 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i...@@ -633,8 +636,10 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i
633 }636 }
634637
635 fpos_t pos;638 fpos_t pos;
636 if (fgetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;639 if (fds[fd].stream != NULL) {
637 if (fseek(fds[fd].stream, offset, SEEK_SET) < 0) return wasi_errno_io;640 if (fgetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;
641 if (fseek(fds[fd].stream, offset, SEEK_SET) < 0) return wasi_errno_io;
642 }
638643
639 size_t size = 0;644 size_t size = 0;
640 for (uint32_t i = 0; i < iovs_len; i += 1) {645 for (uint32_t i = 0; i < iovs_len; i += 1) {
...@@ -648,7 +653,9 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i...@@ -648,7 +653,9 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i
648 if (written_size < len) break;653 if (written_size < len) break;
649 }654 }
650655
651 if (fsetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;656 if (fds[fd].stream != NULL) {
657 if (fsetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;
658 }
652659
653 if (size > 0) {660 if (size > 0) {
654 time_t now = time(NULL);661 time_t now = time(NULL);
...@@ -964,6 +971,11 @@ uint32_t wasi_snapshot_preview1_fd_pread(uint32_t fd, uint32_t iovs, uint32_t io...@@ -964,6 +971,11 @@ uint32_t wasi_snapshot_preview1_fd_pread(uint32_t fd, uint32_t iovs, uint32_t io
964 default: panic("unimplemented: fd_pread special file");971 default: panic("unimplemented: fd_pread special file");
965 }972 }
966973
974 if (fds[fd].stream == NULL) {
975 store32_align2(res_size_ptr, 0);
976 return wasi_errno_success;
977 }
978
967 fpos_t pos;979 fpos_t pos;
968 if (fgetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;980 if (fgetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;
969 if (fseek(fds[fd].stream, offset, SEEK_SET) < 0) return wasi_errno_io;981 if (fseek(fds[fd].stream, offset, SEEK_SET) < 0) return wasi_errno_io;
test/behavior/error.zig-18
...@@ -1032,24 +1032,6 @@ test "function called at runtime is properly analyzed for inferred error set" {...@@ -1032,24 +1032,6 @@ test "function called at runtime is properly analyzed for inferred error set" {
1032 };1032 };
1033}1033}
10341034
1035test "generic type constructed from inferred error set of unresolved function" {
1036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1037 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1038 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1039
1040 const S = struct {
1041 fn write(_: void, bytes: []const u8) !usize {
1042 _ = bytes;
1043 return 0;
1044 }
1045 const T = std.io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).@"fn".return_type.?).error_union.error_set, write);
1046 fn writer() T {
1047 return .{ .context = {} };
1048 }
1049 };
1050 _ = std.io.multiWriter(.{S.writer()});
1051}
1052
1053test "errorCast to adhoc inferred error set" {1035test "errorCast to adhoc inferred error set" {
1054 const S = struct {1036 const S = struct {
1055 inline fn baz() !i32 {1037 inline fn baz() !i32 {
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/cases/safety/slice sentinel mismatch - floats.zig +1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "sentinel mismatch: expected 1.2e0, found 4e0")) {5 if (std.mem.eql(u8, message, "sentinel mismatch: expected 1.2, found 4")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 std.process.exit(1);
test/compare_output.zig+3-286
...@@ -17,15 +17,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -17,15 +17,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
17 \\}17 \\}
18 , "Hello, world!" ++ if (@import("builtin").os.tag == .windows) "\r\n" else "\n");18 , "Hello, world!" ++ if (@import("builtin").os.tag == .windows) "\r\n" else "\n");
1919
20 cases.add("hello world without libc",
21 \\const io = @import("std").io;
22 \\
23 \\pub fn main() void {
24 \\ const stdout = io.getStdOut().writer();
25 \\ stdout.print("Hello, world!\n{d:4} {x:3} {c}\n", .{@as(u32, 12), @as(u16, 0x12), @as(u8, 'a')}) catch unreachable;
26 \\}
27 , "Hello, world!\n 12 12 a\n");
28
29 cases.addC("number literals",20 cases.addC("number literals",
30 \\const std = @import("std");21 \\const std = @import("std");
31 \\const builtin = @import("builtin");22 \\const builtin = @import("builtin");
...@@ -158,24 +149,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -158,24 +149,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
158 \\149 \\
159 );150 );
160151
161 cases.add("order-independent declarations",
162 \\const io = @import("std").io;
163 \\const z = io.stdin_fileno;
164 \\const x : @TypeOf(y) = 1234;
165 \\const y : u16 = 5678;
166 \\pub fn main() void {
167 \\ var x_local : i32 = print_ok(x);
168 \\ _ = &x_local;
169 \\}
170 \\fn print_ok(val: @TypeOf(x)) @TypeOf(foo) {
171 \\ _ = val;
172 \\ const stdout = io.getStdOut().writer();
173 \\ stdout.print("OK\n", .{}) catch unreachable;
174 \\ return 0;
175 \\}
176 \\const foo : i32 = 0;
177 , "OK\n");
178
179 cases.addC("expose function pointer to C land",152 cases.addC("expose function pointer to C land",
180 \\const c = @cImport(@cInclude("stdlib.h"));153 \\const c = @cImport(@cInclude("stdlib.h"));
181 \\154 \\
...@@ -236,267 +209,11 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -236,267 +209,11 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
236 \\}209 \\}
237 , "3.25\n3\n3.00\n-0.40\n");210 , "3.25\n3\n3.00\n-0.40\n");
238211
239 cases.add("same named methods in incomplete struct",212 cases.add("valid carriage return example", "const std = @import(\"std\");\r\n" ++ // Testing CRLF line endings are valid
240 \\const io = @import("std").io;
241 \\
242 \\const Foo = struct {
243 \\ field1: Bar,
244 \\
245 \\ fn method(a: *const Foo) bool {
246 \\ _ = a;
247 \\ return true;
248 \\ }
249 \\};
250 \\
251 \\const Bar = struct {
252 \\ field2: i32,
253 \\
254 \\ fn method(b: *const Bar) bool {
255 \\ _ = b;
256 \\ return true;
257 \\ }
258 \\};
259 \\
260 \\pub fn main() void {
261 \\ const bar = Bar {.field2 = 13,};
262 \\ const foo = Foo {.field1 = bar,};
263 \\ const stdout = io.getStdOut().writer();
264 \\ if (!foo.method()) {
265 \\ stdout.print("BAD\n", .{}) catch unreachable;
266 \\ }
267 \\ if (!bar.method()) {
268 \\ stdout.print("BAD\n", .{}) catch unreachable;
269 \\ }
270 \\ stdout.print("OK\n", .{}) catch unreachable;
271 \\}
272 , "OK\n");
273
274 cases.add("defer with only fallthrough",
275 \\const io = @import("std").io;
276 \\pub fn main() void {
277 \\ const stdout = io.getStdOut().writer();
278 \\ stdout.print("before\n", .{}) catch unreachable;
279 \\ defer stdout.print("defer1\n", .{}) catch unreachable;
280 \\ defer stdout.print("defer2\n", .{}) catch unreachable;
281 \\ defer stdout.print("defer3\n", .{}) catch unreachable;
282 \\ stdout.print("after\n", .{}) catch unreachable;
283 \\}
284 , "before\nafter\ndefer3\ndefer2\ndefer1\n");
285
286 cases.add("defer with return",
287 \\const io = @import("std").io;
288 \\const os = @import("std").os;
289 \\pub fn main() void {
290 \\ const stdout = io.getStdOut().writer();
291 \\ stdout.print("before\n", .{}) catch unreachable;
292 \\ defer stdout.print("defer1\n", .{}) catch unreachable;
293 \\ defer stdout.print("defer2\n", .{}) catch unreachable;
294 \\ var gpa: @import("std").heap.GeneralPurposeAllocator(.{}) = .init;
295 \\ defer _ = gpa.deinit();
296 \\ var arena = @import("std").heap.ArenaAllocator.init(gpa.allocator());
297 \\ defer arena.deinit();
298 \\ var args_it = @import("std").process.argsWithAllocator(arena.allocator()) catch unreachable;
299 \\ if (args_it.skip() and !args_it.skip()) return;
300 \\ defer stdout.print("defer3\n", .{}) catch unreachable;
301 \\ stdout.print("after\n", .{}) catch unreachable;
302 \\}
303 , "before\ndefer2\ndefer1\n");
304
305 cases.add("errdefer and it fails",
306 \\const io = @import("std").io;
307 \\pub fn main() void {
308 \\ do_test() catch return;
309 \\}
310 \\fn do_test() !void {
311 \\ const stdout = io.getStdOut().writer();
312 \\ stdout.print("before\n", .{}) catch unreachable;
313 \\ defer stdout.print("defer1\n", .{}) catch unreachable;
314 \\ errdefer stdout.print("deferErr\n", .{}) catch unreachable;
315 \\ try its_gonna_fail();
316 \\ defer stdout.print("defer3\n", .{}) catch unreachable;
317 \\ stdout.print("after\n", .{}) catch unreachable;
318 \\}
319 \\fn its_gonna_fail() !void {
320 \\ return error.IToldYouItWouldFail;
321 \\}
322 , "before\ndeferErr\ndefer1\n");
323
324 cases.add("errdefer and it passes",
325 \\const io = @import("std").io;
326 \\pub fn main() void {
327 \\ do_test() catch return;
328 \\}
329 \\fn do_test() !void {
330 \\ const stdout = io.getStdOut().writer();
331 \\ stdout.print("before\n", .{}) catch unreachable;
332 \\ defer stdout.print("defer1\n", .{}) catch unreachable;
333 \\ errdefer stdout.print("deferErr\n", .{}) catch unreachable;
334 \\ try its_gonna_pass();
335 \\ defer stdout.print("defer3\n", .{}) catch unreachable;
336 \\ stdout.print("after\n", .{}) catch unreachable;
337 \\}
338 \\fn its_gonna_pass() anyerror!void { }
339 , "before\nafter\ndefer3\ndefer1\n");
340
341 cases.addCase(x: {
342 var tc = cases.create("@embedFile",
343 \\const foo_txt = @embedFile("foo.txt");
344 \\const io = @import("std").io;
345 \\
346 \\pub fn main() void {
347 \\ const stdout = io.getStdOut().writer();
348 \\ stdout.print(foo_txt, .{}) catch unreachable;
349 \\}
350 , "1234\nabcd\n");
351
352 tc.addSourceFile("foo.txt", "1234\nabcd\n");
353
354 break :x tc;
355 });
356
357 cases.addCase(x: {
358 var tc = cases.create("parsing args",
359 \\const std = @import("std");
360 \\const io = std.io;
361 \\const os = std.os;
362 \\
363 \\pub fn main() !void {
364 \\ var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
365 \\ defer _ = gpa.deinit();
366 \\ var arena = std.heap.ArenaAllocator.init(gpa.allocator());
367 \\ defer arena.deinit();
368 \\ var args_it = try std.process.argsWithAllocator(arena.allocator());
369 \\ const stdout = io.getStdOut().writer();
370 \\ var index: usize = 0;
371 \\ _ = args_it.skip();
372 \\ while (args_it.next()) |arg| : (index += 1) {
373 \\ try stdout.print("{}: {s}\n", .{index, arg});
374 \\ }
375 \\}
376 ,
377 \\0: first arg
378 \\1: 'a' 'b' \
379 \\2: bare
380 \\3: ba""re
381 \\4: "
382 \\5: last arg
383 \\
384 );
385
386 tc.setCommandLineArgs(&[_][]const u8{
387 "first arg",
388 "'a' 'b' \\",
389 "bare",
390 "ba\"\"re",
391 "\"",
392 "last arg",
393 });
394
395 break :x tc;
396 });
397
398 cases.addCase(x: {
399 var tc = cases.create("parsing args new API",
400 \\const std = @import("std");
401 \\const io = std.io;
402 \\const os = std.os;
403 \\
404 \\pub fn main() !void {
405 \\ var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
406 \\ defer _ = gpa.deinit();
407 \\ var arena = std.heap.ArenaAllocator.init(gpa.allocator());
408 \\ defer arena.deinit();
409 \\ var args_it = try std.process.argsWithAllocator(arena.allocator());
410 \\ const stdout = io.getStdOut().writer();
411 \\ var index: usize = 0;
412 \\ _ = args_it.skip();
413 \\ while (args_it.next()) |arg| : (index += 1) {
414 \\ try stdout.print("{}: {s}\n", .{index, arg});
415 \\ }
416 \\}
417 ,
418 \\0: first arg
419 \\1: 'a' 'b' \
420 \\2: bare
421 \\3: ba""re
422 \\4: "
423 \\5: last arg
424 \\
425 );
426
427 tc.setCommandLineArgs(&[_][]const u8{
428 "first arg",
429 "'a' 'b' \\",
430 "bare",
431 "ba\"\"re",
432 "\"",
433 "last arg",
434 });
435
436 break :x tc;
437 });
438
439 // It is required to override the log function in order to print to stdout instead of stderr
440 cases.add("std.log per scope log level override",
441 \\const std = @import("std");
442 \\
443 \\pub const std_options: std.Options = .{
444 \\ .log_level = .debug,
445 \\
446 \\ .log_scope_levels = &.{
447 \\ .{ .scope = .a, .level = .warn },
448 \\ .{ .scope = .c, .level = .err },
449 \\ },
450 \\ .logFn = log,
451 \\};
452 \\
453 \\const loga = std.log.scoped(.a);
454 \\const logb = std.log.scoped(.b);
455 \\const logc = std.log.scoped(.c);
456 \\
457 \\pub fn main() !void {
458 \\ loga.debug("", .{});
459 \\ logb.debug("", .{});
460 \\ logc.debug("", .{});
461 \\
462 \\ loga.info("", .{});
463 \\ logb.info("", .{});
464 \\ logc.info("", .{});
465 \\
466 \\ loga.warn("", .{});
467 \\ logb.warn("", .{});
468 \\ logc.warn("", .{});
469 \\
470 \\ loga.err("", .{});
471 \\ logb.err("", .{});
472 \\ logc.err("", .{});
473 \\}
474 \\pub fn log(
475 \\ comptime level: std.log.Level,
476 \\ comptime scope: @TypeOf(.EnumLiteral),
477 \\ comptime format: []const u8,
478 \\ args: anytype,
479 \\) void {
480 \\ const level_txt = comptime level.asText();
481 \\ const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "):";
482 \\ const stdout = std.io.getStdOut().writer();
483 \\ nosuspend stdout.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return;
484 \\}
485 ,
486 \\debug(b):
487 \\info(b):
488 \\warning(a):
489 \\warning(b):
490 \\error(a):
491 \\error(b):
492 \\error(c):
493 \\
494 );
495
496 cases.add("valid carriage return example", "const io = @import(\"std\").io;\r\n" ++ // Testing CRLF line endings are valid
497 "\r\n" ++213 "\r\n" ++
498 "pub \r fn main() void {\r\n" ++ // Testing isolated carriage return as whitespace is valid214 "pub \r fn main() void {\r\n" ++ // Testing isolated carriage return as whitespace is valid
499 " const stdout = io.getStdOut().writer();\r\n" ++215 " var file_writer = std.fs.File.stdout().writerStreaming(&.{});\r\n" ++
216 " const stdout = &file_writer.interface;\r\n" ++
500 " stdout.print(\\\\A Multiline\r\n" ++ // testing CRLF at end of multiline string line is valid and normalises to \n in the output217 " stdout.print(\\\\A Multiline\r\n" ++ // testing CRLF at end of multiline string line is valid and normalises to \n in the output
501 " \\\\String\r\n" ++218 " \\\\String\r\n" ++
502 " , .{}) catch unreachable;\r\n" ++219 " , .{}) catch unreachable;\r\n" ++
test/incremental/add_decl+7-7
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6#file=main.zig6#file=main.zig
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 try std.io.getStdOut().writeAll(foo);9 try std.fs.File.stdout().writeAll(foo);
10}10}
11const foo = "good morning\n";11const foo = "good morning\n";
12#expect_stdout="good morning\n"12#expect_stdout="good morning\n"
...@@ -15,7 +15,7 @@ const foo = "good morning\n";...@@ -15,7 +15,7 @@ const foo = "good morning\n";
15#file=main.zig15#file=main.zig
16const std = @import("std");16const std = @import("std");
17pub fn main() !void {17pub fn main() !void {
18 try std.io.getStdOut().writeAll(foo);18 try std.fs.File.stdout().writeAll(foo);
19}19}
20const foo = "good morning\n";20const foo = "good morning\n";
21const bar = "good evening\n";21const bar = "good evening\n";
...@@ -25,7 +25,7 @@ const bar = "good evening\n";...@@ -25,7 +25,7 @@ const bar = "good evening\n";
25#file=main.zig25#file=main.zig
26const std = @import("std");26const std = @import("std");
27pub fn main() !void {27pub fn main() !void {
28 try std.io.getStdOut().writeAll(bar);28 try std.fs.File.stdout().writeAll(bar);
29}29}
30const foo = "good morning\n";30const foo = "good morning\n";
31const bar = "good evening\n";31const bar = "good evening\n";
...@@ -35,17 +35,17 @@ const bar = "good evening\n";...@@ -35,17 +35,17 @@ const bar = "good evening\n";
35#file=main.zig35#file=main.zig
36const std = @import("std");36const std = @import("std");
37pub fn main() !void {37pub fn main() !void {
38 try std.io.getStdOut().writeAll(qux);38 try std.fs.File.stdout().writeAll(qux);
39}39}
40const foo = "good morning\n";40const foo = "good morning\n";
41const bar = "good evening\n";41const bar = "good evening\n";
42#expect_error=main.zig:3:37: error: use of undeclared identifier 'qux'42#expect_error=main.zig:3:39: error: use of undeclared identifier 'qux'
4343
44#update=add missing declaration44#update=add missing declaration
45#file=main.zig45#file=main.zig
46const std = @import("std");46const std = @import("std");
47pub fn main() !void {47pub fn main() !void {
48 try std.io.getStdOut().writeAll(qux);48 try std.fs.File.stdout().writeAll(qux);
49}49}
50const foo = "good morning\n";50const foo = "good morning\n";
51const bar = "good evening\n";51const bar = "good evening\n";
...@@ -56,7 +56,7 @@ const qux = "good night\n";...@@ -56,7 +56,7 @@ const qux = "good night\n";
56#file=main.zig56#file=main.zig
57const std = @import("std");57const std = @import("std");
58pub fn main() !void {58pub fn main() !void {
59 try std.io.getStdOut().writeAll(qux);59 try std.fs.File.stdout().writeAll(qux);
60}60}
61const qux = "good night\n";61const qux = "good night\n";
62#expect_stdout="good night\n"62#expect_stdout="good night\n"
test/incremental/add_decl_namespaced+7-7
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6#file=main.zig6#file=main.zig
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 try std.io.getStdOut().writeAll(@This().foo);9 try std.fs.File.stdout().writeAll(@This().foo);
10}10}
11const foo = "good morning\n";11const foo = "good morning\n";
12#expect_stdout="good morning\n"12#expect_stdout="good morning\n"
...@@ -15,7 +15,7 @@ const foo = "good morning\n";...@@ -15,7 +15,7 @@ const foo = "good morning\n";
15#file=main.zig15#file=main.zig
16const std = @import("std");16const std = @import("std");
17pub fn main() !void {17pub fn main() !void {
18 try std.io.getStdOut().writeAll(@This().foo);18 try std.fs.File.stdout().writeAll(@This().foo);
19}19}
20const foo = "good morning\n";20const foo = "good morning\n";
21const bar = "good evening\n";21const bar = "good evening\n";
...@@ -25,7 +25,7 @@ const bar = "good evening\n";...@@ -25,7 +25,7 @@ const bar = "good evening\n";
25#file=main.zig25#file=main.zig
26const std = @import("std");26const std = @import("std");
27pub fn main() !void {27pub fn main() !void {
28 try std.io.getStdOut().writeAll(@This().bar);28 try std.fs.File.stdout().writeAll(@This().bar);
29}29}
30const foo = "good morning\n";30const foo = "good morning\n";
31const bar = "good evening\n";31const bar = "good evening\n";
...@@ -35,18 +35,18 @@ const bar = "good evening\n";...@@ -35,18 +35,18 @@ const bar = "good evening\n";
35#file=main.zig35#file=main.zig
36const std = @import("std");36const std = @import("std");
37pub fn main() !void {37pub fn main() !void {
38 try std.io.getStdOut().writeAll(@This().qux);38 try std.fs.File.stdout().writeAll(@This().qux);
39}39}
40const foo = "good morning\n";40const foo = "good morning\n";
41const bar = "good evening\n";41const bar = "good evening\n";
42#expect_error=main.zig:3:44: error: root source file struct 'main' has no member named 'qux'42#expect_error=main.zig:3:46: error: root source file struct 'main' has no member named 'qux'
43#expect_error=main.zig:1:1: note: struct declared here43#expect_error=main.zig:1:1: note: struct declared here
4444
45#update=add missing declaration45#update=add missing declaration
46#file=main.zig46#file=main.zig
47const std = @import("std");47const std = @import("std");
48pub fn main() !void {48pub fn main() !void {
49 try std.io.getStdOut().writeAll(@This().qux);49 try std.fs.File.stdout().writeAll(@This().qux);
50}50}
51const foo = "good morning\n";51const foo = "good morning\n";
52const bar = "good evening\n";52const bar = "good evening\n";
...@@ -57,7 +57,7 @@ const qux = "good night\n";...@@ -57,7 +57,7 @@ const qux = "good night\n";
57#file=main.zig57#file=main.zig
58const std = @import("std");58const std = @import("std");
59pub fn main() !void {59pub fn main() !void {
60 try std.io.getStdOut().writeAll(@This().qux);60 try std.fs.File.stdout().writeAll(@This().qux);
61}61}
62const qux = "good night\n";62const qux = "good night\n";
63#expect_stdout="good night\n"63#expect_stdout="good night\n"
test/incremental/bad_import+2-2
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7#file=main.zig7#file=main.zig
8pub fn main() !void {8pub fn main() !void {
9 _ = @import("foo.zig");9 _ = @import("foo.zig");
10 try std.io.getStdOut().writeAll("success\n");10 try std.fs.File.stdout().writeAll("success\n");
11}11}
12const std = @import("std");12const std = @import("std");
13#file=foo.zig13#file=foo.zig
...@@ -29,7 +29,7 @@ comptime {...@@ -29,7 +29,7 @@ comptime {
29#file=main.zig29#file=main.zig
30pub fn main() !void {30pub fn main() !void {
31 //_ = @import("foo.zig");31 //_ = @import("foo.zig");
32 try std.io.getStdOut().writeAll("success\n");32 try std.fs.File.stdout().writeAll("success\n");
33}33}
34const std = @import("std");34const std = @import("std");
35#expect_stdout="success\n"35#expect_stdout="success\n"
test/incremental/change_embed_file+3-3
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const std = @import("std");7const std = @import("std");
8const string = @embedFile("string.txt");8const string = @embedFile("string.txt");
9pub fn main() !void {9pub fn main() !void {
10 try std.io.getStdOut().writeAll(string);10 try std.fs.File.stdout().writeAll(string);
11}11}
12#file=string.txt12#file=string.txt
13Hello, World!13Hello, World!
...@@ -27,7 +27,7 @@ Hello again, World!...@@ -27,7 +27,7 @@ Hello again, World!
27const std = @import("std");27const std = @import("std");
28const string = @embedFile("string.txt");28const string = @embedFile("string.txt");
29pub fn main() !void {29pub fn main() !void {
30 try std.io.getStdOut().writeAll("a hardcoded string\n");30 try std.fs.File.stdout().writeAll("a hardcoded string\n");
31}31}
32#expect_stdout="a hardcoded string\n"32#expect_stdout="a hardcoded string\n"
3333
...@@ -36,7 +36,7 @@ pub fn main() !void {...@@ -36,7 +36,7 @@ pub fn main() !void {
36const std = @import("std");36const std = @import("std");
37const string = @embedFile("string.txt");37const string = @embedFile("string.txt");
38pub fn main() !void {38pub fn main() !void {
39 try std.io.getStdOut().writeAll(string);39 try std.fs.File.stdout().writeAll(string);
40}40}
41#expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound41#expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound
4242
test/incremental/change_enum_tag_type+6-3
...@@ -14,7 +14,8 @@ const Foo = enum(Tag) {...@@ -14,7 +14,8 @@ const Foo = enum(Tag) {
14pub fn main() !void {14pub fn main() !void {
15 var val: Foo = undefined;15 var val: Foo = undefined;
16 val = .a;16 val = .a;
17 try std.io.getStdOut().writer().print("{s}\n", .{@tagName(val)});17 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
18 try stdout_writer.interface.print("{s}\n", .{@tagName(val)});
18}19}
19const std = @import("std");20const std = @import("std");
20#expect_stdout="a\n"21#expect_stdout="a\n"
...@@ -31,7 +32,8 @@ const Foo = enum(Tag) {...@@ -31,7 +32,8 @@ const Foo = enum(Tag) {
31pub fn main() !void {32pub fn main() !void {
32 var val: Foo = undefined;33 var val: Foo = undefined;
33 val = .a;34 val = .a;
34 try std.io.getStdOut().writer().print("{s}\n", .{@tagName(val)});35 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
36 try stdout_writer.interface.print("{s}\n", .{@tagName(val)});
35}37}
36comptime {38comptime {
37 // These can't be true at the same time; analysis should stop as soon as it sees `Foo`39 // These can't be true at the same time; analysis should stop as soon as it sees `Foo`
...@@ -53,7 +55,8 @@ const Foo = enum(Tag) {...@@ -53,7 +55,8 @@ const Foo = enum(Tag) {
53pub fn main() !void {55pub fn main() !void {
54 var val: Foo = undefined;56 var val: Foo = undefined;
55 val = .a;57 val = .a;
56 try std.io.getStdOut().writer().print("{s}\n", .{@tagName(val)});58 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
59 try stdout_writer.interface.print("{s}\n", .{@tagName(val)});
57}60}
58const std = @import("std");61const std = @import("std");
59#expect_stdout="a\n"62#expect_stdout="a\n"
test/incremental/change_exports+12-6
...@@ -16,7 +16,8 @@ pub fn main() !void {...@@ -16,7 +16,8 @@ pub fn main() !void {
16 extern const bar: u32;16 extern const bar: u32;
17 };17 };
18 S.foo();18 S.foo();
19 try std.io.getStdOut().writer().print("{}\n", .{S.bar});19 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
20 try stdout_writer.interface.print("{}\n", .{S.bar});
20}21}
21const std = @import("std");22const std = @import("std");
22#expect_stdout="123\n"23#expect_stdout="123\n"
...@@ -37,7 +38,8 @@ pub fn main() !void {...@@ -37,7 +38,8 @@ pub fn main() !void {
37 extern const other: u32;38 extern const other: u32;
38 };39 };
39 S.foo();40 S.foo();
40 try std.io.getStdOut().writer().print("{} {}\n", .{ S.bar, S.other });41 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
42 try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
41}43}
42const std = @import("std");44const std = @import("std");
43#expect_error=main.zig:6:5: error: exported symbol collision: foo45#expect_error=main.zig:6:5: error: exported symbol collision: foo
...@@ -59,7 +61,8 @@ pub fn main() !void {...@@ -59,7 +61,8 @@ pub fn main() !void {
59 extern const other: u32;61 extern const other: u32;
60 };62 };
61 S.foo();63 S.foo();
62 try std.io.getStdOut().writer().print("{} {}\n", .{ S.bar, S.other });64 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
65 try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
63}66}
64const std = @import("std");67const std = @import("std");
65#expect_stdout="123 456\n"68#expect_stdout="123 456\n"
...@@ -83,7 +86,8 @@ pub fn main() !void {...@@ -83,7 +86,8 @@ pub fn main() !void {
83 extern const other: u32;86 extern const other: u32;
84 };87 };
85 S.foo();88 S.foo();
86 try std.io.getStdOut().writer().print("{} {}\n", .{ S.bar, S.other });89 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
90 try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
87}91}
88const std = @import("std");92const std = @import("std");
89#expect_stdout="123 456\n"93#expect_stdout="123 456\n"
...@@ -128,7 +132,8 @@ pub fn main() !void {...@@ -128,7 +132,8 @@ pub fn main() !void {
128 extern const other: u32;132 extern const other: u32;
129 };133 };
130 S.foo();134 S.foo();
131 try std.io.getStdOut().writer().print("{} {}\n", .{ S.bar, S.other });135 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
136 try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
132}137}
133const std = @import("std");138const std = @import("std");
134#expect_stdout="123 456\n"139#expect_stdout="123 456\n"
...@@ -152,7 +157,8 @@ pub fn main() !void {...@@ -152,7 +157,8 @@ pub fn main() !void {
152 extern const other: u32;157 extern const other: u32;
153 };158 };
154 S.foo();159 S.foo();
155 try std.io.getStdOut().writer().print("{} {}\n", .{ S.bar, S.other });160 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
161 try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
156}162}
157const std = @import("std");163const std = @import("std");
158#expect_error=main.zig:5:5: error: exported symbol collision: bar164#expect_error=main.zig:5:5: error: exported symbol collision: bar
test/incremental/change_fn_type+6-3
...@@ -7,7 +7,8 @@ pub fn main() !void {...@@ -7,7 +7,8 @@ pub fn main() !void {
7 try foo(123);7 try foo(123);
8}8}
9fn foo(x: u8) !void {9fn foo(x: u8) !void {
10 return std.io.getStdOut().writer().print("{d}\n", .{x});10 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
11 return stdout_writer.interface.print("{d}\n", .{x});
11}12}
12const std = @import("std");13const std = @import("std");
13#expect_stdout="123\n"14#expect_stdout="123\n"
...@@ -18,7 +19,8 @@ pub fn main() !void {...@@ -18,7 +19,8 @@ pub fn main() !void {
18 try foo(123);19 try foo(123);
19}20}
20fn foo(x: i64) !void {21fn foo(x: i64) !void {
21 return std.io.getStdOut().writer().print("{d}\n", .{x});22 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
23 return stdout_writer.interface.print("{d}\n", .{x});
22}24}
23const std = @import("std");25const std = @import("std");
24#expect_stdout="123\n"26#expect_stdout="123\n"
...@@ -29,7 +31,8 @@ pub fn main() !void {...@@ -29,7 +31,8 @@ pub fn main() !void {
29 try foo(-42);31 try foo(-42);
30}32}
31fn foo(x: i64) !void {33fn foo(x: i64) !void {
32 return std.io.getStdOut().writer().print("{d}\n", .{x});34 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
35 return stdout_writer.interface.print("{d}\n", .{x});
33}36}
34const std = @import("std");37const std = @import("std");
35#expect_stdout="-42\n"38#expect_stdout="-42\n"
test/incremental/change_generic_line_number+2-2
...@@ -6,7 +6,7 @@ const std = @import("std");...@@ -6,7 +6,7 @@ const std = @import("std");
6fn Printer(message: []const u8) type {6fn Printer(message: []const u8) type {
7 return struct {7 return struct {
8 fn print() !void {8 fn print() !void {
9 try std.io.getStdOut().writeAll(message);9 try std.fs.File.stdout().writeAll(message);
10 }10 }
11 };11 };
12}12}
...@@ -22,7 +22,7 @@ const std = @import("std");...@@ -22,7 +22,7 @@ const std = @import("std");
22fn Printer(message: []const u8) type {22fn Printer(message: []const u8) type {
23 return struct {23 return struct {
24 fn print() !void {24 fn print() !void {
25 try std.io.getStdOut().writeAll(message);25 try std.fs.File.stdout().writeAll(message);
26 }26 }
27 };27 };
28}28}
test/incremental/change_line_number+2-2
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4#file=main.zig4#file=main.zig
5const std = @import("std");5const std = @import("std");
6pub fn main() !void {6pub fn main() !void {
7 try std.io.getStdOut().writeAll("foo\n");7 try std.fs.File.stdout().writeAll("foo\n");
8}8}
9#expect_stdout="foo\n"9#expect_stdout="foo\n"
10#update=change line number10#update=change line number
...@@ -12,6 +12,6 @@ pub fn main() !void {...@@ -12,6 +12,6 @@ pub fn main() !void {
12const std = @import("std");12const std = @import("std");
1313
14pub fn main() !void {14pub fn main() !void {
15 try std.io.getStdOut().writeAll("foo\n");15 try std.fs.File.stdout().writeAll("foo\n");
16}16}
17#expect_stdout="foo\n"17#expect_stdout="foo\n"
test/incremental/change_panic_handler+6-3
...@@ -11,7 +11,8 @@ pub fn main() !u8 {...@@ -11,7 +11,8 @@ pub fn main() !u8 {
11}11}
12pub const panic = std.debug.FullPanic(myPanic);12pub const panic = std.debug.FullPanic(myPanic);
13fn myPanic(msg: []const u8, _: ?usize) noreturn {13fn myPanic(msg: []const u8, _: ?usize) noreturn {
14 std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};14 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
15 stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {};
15 std.process.exit(0);16 std.process.exit(0);
16}17}
17const std = @import("std");18const std = @import("std");
...@@ -27,7 +28,8 @@ pub fn main() !u8 {...@@ -27,7 +28,8 @@ pub fn main() !u8 {
27}28}
28pub const panic = std.debug.FullPanic(myPanic);29pub const panic = std.debug.FullPanic(myPanic);
29fn myPanic(msg: []const u8, _: ?usize) noreturn {30fn myPanic(msg: []const u8, _: ?usize) noreturn {
30 std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};31 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
32 stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {};
31 std.process.exit(0);33 std.process.exit(0);
32}34}
33const std = @import("std");35const std = @import("std");
...@@ -43,7 +45,8 @@ pub fn main() !u8 {...@@ -43,7 +45,8 @@ pub fn main() !u8 {
43}45}
44pub const panic = std.debug.FullPanic(myPanicNew);46pub const panic = std.debug.FullPanic(myPanicNew);
45fn myPanicNew(msg: []const u8, _: ?usize) noreturn {47fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
46 std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};48 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
49 stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {};
47 std.process.exit(0);50 std.process.exit(0);
48}51}
49const std = @import("std");52const std = @import("std");
test/incremental/change_panic_handler_explicit+6-3
...@@ -41,7 +41,8 @@ pub const panic = struct {...@@ -41,7 +41,8 @@ pub const panic = struct {
41 pub const noreturnReturned = no_panic.noreturnReturned;41 pub const noreturnReturned = no_panic.noreturnReturned;
42};42};
43fn myPanic(msg: []const u8, _: ?usize) noreturn {43fn myPanic(msg: []const u8, _: ?usize) noreturn {
44 std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};44 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
45 stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {};
45 std.process.exit(0);46 std.process.exit(0);
46}47}
47const std = @import("std");48const std = @import("std");
...@@ -87,7 +88,8 @@ pub const panic = struct {...@@ -87,7 +88,8 @@ pub const panic = struct {
87 pub const noreturnReturned = no_panic.noreturnReturned;88 pub const noreturnReturned = no_panic.noreturnReturned;
88};89};
89fn myPanic(msg: []const u8, _: ?usize) noreturn {90fn myPanic(msg: []const u8, _: ?usize) noreturn {
90 std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};91 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
92 stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {};
91 std.process.exit(0);93 std.process.exit(0);
92}94}
93const std = @import("std");95const std = @import("std");
...@@ -133,7 +135,8 @@ pub const panic = struct {...@@ -133,7 +135,8 @@ pub const panic = struct {
133 pub const noreturnReturned = no_panic.noreturnReturned;135 pub const noreturnReturned = no_panic.noreturnReturned;
134};136};
135fn myPanicNew(msg: []const u8, _: ?usize) noreturn {137fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
136 std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};138 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
139 stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {};
137 std.process.exit(0);140 std.process.exit(0);
138}141}
139const std = @import("std");142const std = @import("std");
test/incremental/change_shift_op+4-2
...@@ -8,7 +8,8 @@ pub fn main() !void {...@@ -8,7 +8,8 @@ pub fn main() !void {
8 try foo(0x1300);8 try foo(0x1300);
9}9}
10fn foo(x: u16) !void {10fn foo(x: u16) !void {
11 try std.io.getStdOut().writer().print("0x{x}\n", .{x << 4});11 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
12 try stdout_writer.interface.print("0x{x}\n", .{x << 4});
12}13}
13const std = @import("std");14const std = @import("std");
14#expect_stdout="0x3000\n"15#expect_stdout="0x3000\n"
...@@ -18,7 +19,8 @@ pub fn main() !void {...@@ -18,7 +19,8 @@ pub fn main() !void {
18 try foo(0x1300);19 try foo(0x1300);
19}20}
20fn foo(x: u16) !void {21fn foo(x: u16) !void {
21 try std.io.getStdOut().writer().print("0x{x}\n", .{x >> 4});22 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
23 try stdout_writer.interface.print("0x{x}\n", .{x >> 4});
22}24}
23const std = @import("std");25const std = @import("std");
24#expect_stdout="0x130\n"26#expect_stdout="0x130\n"
test/incremental/change_struct_same_fields+6-3
...@@ -10,7 +10,8 @@ pub fn main() !void {...@@ -10,7 +10,8 @@ pub fn main() !void {
10 try foo(&val);10 try foo(&val);
11}11}
12fn foo(val: *const S) !void {12fn foo(val: *const S) !void {
13 try std.io.getStdOut().writer().print(13 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
14 try stdout_writer.interface.print(
14 "{d} {d}\n",15 "{d} {d}\n",
15 .{ val.x, val.y },16 .{ val.x, val.y },
16 );17 );
...@@ -26,7 +27,8 @@ pub fn main() !void {...@@ -26,7 +27,8 @@ pub fn main() !void {
26 try foo(&val);27 try foo(&val);
27}28}
28fn foo(val: *const S) !void {29fn foo(val: *const S) !void {
29 try std.io.getStdOut().writer().print(30 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
31 try stdout_writer.interface.print(
30 "{d} {d}\n",32 "{d} {d}\n",
31 .{ val.x, val.y },33 .{ val.x, val.y },
32 );34 );
...@@ -42,7 +44,8 @@ pub fn main() !void {...@@ -42,7 +44,8 @@ pub fn main() !void {
42 try foo(&val);44 try foo(&val);
43}45}
44fn foo(val: *const S) !void {46fn foo(val: *const S) !void {
45 try std.io.getStdOut().writer().print(47 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
48 try stdout_writer.interface.print(
46 "{d} {d}\n",49 "{d} {d}\n",
47 .{ val.x, val.y },50 .{ val.x, val.y },
48 );51 );
test/incremental/change_zon_file+3-3
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const std = @import("std");7const std = @import("std");
8const message: []const u8 = @import("message.zon");8const message: []const u8 = @import("message.zon");
9pub fn main() !void {9pub fn main() !void {
10 try std.io.getStdOut().writeAll(message);10 try std.fs.File.stdout().writeAll(message);
11}11}
12#file=message.zon12#file=message.zon
13"Hello, World!\n"13"Hello, World!\n"
...@@ -28,7 +28,7 @@ pub fn main() !void {...@@ -28,7 +28,7 @@ pub fn main() !void {
28const std = @import("std");28const std = @import("std");
29const message: []const u8 = @import("message.zon");29const message: []const u8 = @import("message.zon");
30pub fn main() !void {30pub fn main() !void {
31 try std.io.getStdOut().writeAll("a hardcoded string\n");31 try std.fs.File.stdout().writeAll("a hardcoded string\n");
32}32}
33#expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound33#expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound
34#expect_error=main.zig:2:37: note: file imported here34#expect_error=main.zig:2:37: note: file imported here
...@@ -43,6 +43,6 @@ pub fn main() !void {...@@ -43,6 +43,6 @@ pub fn main() !void {
43const std = @import("std");43const std = @import("std");
44const message: []const u8 = @import("message.zon");44const message: []const u8 = @import("message.zon");
45pub fn main() !void {45pub fn main() !void {
46 try std.io.getStdOut().writeAll(message);46 try std.fs.File.stdout().writeAll(message);
47}47}
48#expect_stdout="We're back, World!\n"48#expect_stdout="We're back, World!\n"
test/incremental/change_zon_file_no_result_type+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6#file=main.zig6#file=main.zig
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 try std.io.getStdOut().writeAll(@import("foo.zon").message);9 try std.fs.File.stdout().writeAll(@import("foo.zon").message);
10}10}
11#file=foo.zon11#file=foo.zon
12.{12.{
test/incremental/compile_log+3-3
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7#file=main.zig7#file=main.zig
8const std = @import("std");8const std = @import("std");
9pub fn main() !void {9pub fn main() !void {
10 try std.io.getStdOut().writeAll("Hello, World!\n");10 try std.fs.File.stdout().writeAll("Hello, World!\n");
11}11}
12#expect_stdout="Hello, World!\n"12#expect_stdout="Hello, World!\n"
1313
...@@ -15,7 +15,7 @@ pub fn main() !void {...@@ -15,7 +15,7 @@ pub fn main() !void {
15#file=main.zig15#file=main.zig
16const std = @import("std");16const std = @import("std");
17pub fn main() !void {17pub fn main() !void {
18 try std.io.getStdOut().writeAll("Hello, World!\n");18 try std.fs.File.stdout().writeAll("Hello, World!\n");
19 @compileLog("this is a log");19 @compileLog("this is a log");
20}20}
21#expect_error=main.zig:4:5: error: found compile log statement21#expect_error=main.zig:4:5: error: found compile log statement
...@@ -25,6 +25,6 @@ pub fn main() !void {...@@ -25,6 +25,6 @@ pub fn main() !void {
25#file=main.zig25#file=main.zig
26const std = @import("std");26const std = @import("std");
27pub fn main() !void {27pub fn main() !void {
28 try std.io.getStdOut().writeAll("Hello, World!\n");28 try std.fs.File.stdout().writeAll("Hello, World!\n");
29}29}
30#expect_stdout="Hello, World!\n"30#expect_stdout="Hello, World!\n"
test/incremental/fix_astgen_failure+5-5
...@@ -9,28 +9,28 @@ pub fn main() !void {...@@ -9,28 +9,28 @@ pub fn main() !void {
9}9}
10#file=foo.zig10#file=foo.zig
11pub fn hello() !void {11pub fn hello() !void {
12 try std.io.getStdOut().writeAll("Hello, World!\n");12 try std.fs.File.stdout().writeAll("Hello, World!\n");
13}13}
14#expect_error=foo.zig:2:9: error: use of undeclared identifier 'std'14#expect_error=foo.zig:2:9: error: use of undeclared identifier 'std'
15#update=fix the error15#update=fix the error
16#file=foo.zig16#file=foo.zig
17const std = @import("std");17const std = @import("std");
18pub fn hello() !void {18pub fn hello() !void {
19 try std.io.getStdOut().writeAll("Hello, World!\n");19 try std.fs.File.stdout().writeAll("Hello, World!\n");
20}20}
21#expect_stdout="Hello, World!\n"21#expect_stdout="Hello, World!\n"
22#update=add new error22#update=add new error
23#file=foo.zig23#file=foo.zig
24const std = @import("std");24const std = @import("std");
25pub fn hello() !void {25pub fn hello() !void {
26 try std.io.getStdOut().writeAll(hello_str);26 try std.fs.File.stdout().writeAll(hello_str);
27}27}
28#expect_error=foo.zig:3:37: error: use of undeclared identifier 'hello_str'28#expect_error=foo.zig:3:39: error: use of undeclared identifier 'hello_str'
29#update=fix the new error29#update=fix the new error
30#file=foo.zig30#file=foo.zig
31const std = @import("std");31const std = @import("std");
32const hello_str = "Hello, World! Again!\n";32const hello_str = "Hello, World! Again!\n";
33pub fn hello() !void {33pub fn hello() !void {
34 try std.io.getStdOut().writeAll(hello_str);34 try std.fs.File.stdout().writeAll(hello_str);
35}35}
36#expect_stdout="Hello, World! Again!\n"36#expect_stdout="Hello, World! Again!\n"
test/incremental/function_becomes_inline+3-3
...@@ -7,7 +7,7 @@ pub fn main() !void {...@@ -7,7 +7,7 @@ pub fn main() !void {
7 try foo();7 try foo();
8}8}
9fn foo() !void {9fn foo() !void {
10 try std.io.getStdOut().writer().writeAll("Hello, World!\n");10 try std.fs.File.stdout().writeAll("Hello, World!\n");
11}11}
12const std = @import("std");12const std = @import("std");
13#expect_stdout="Hello, World!\n"13#expect_stdout="Hello, World!\n"
...@@ -18,7 +18,7 @@ pub fn main() !void {...@@ -18,7 +18,7 @@ pub fn main() !void {
18 try foo();18 try foo();
19}19}
20inline fn foo() !void {20inline fn foo() !void {
21 try std.io.getStdOut().writer().writeAll("Hello, World!\n");21 try std.fs.File.stdout().writeAll("Hello, World!\n");
22}22}
23const std = @import("std");23const std = @import("std");
24#expect_stdout="Hello, World!\n"24#expect_stdout="Hello, World!\n"
...@@ -29,7 +29,7 @@ pub fn main() !void {...@@ -29,7 +29,7 @@ pub fn main() !void {
29 try foo();29 try foo();
30}30}
31inline fn foo() !void {31inline fn foo() !void {
32 try std.io.getStdOut().writer().writeAll("Hello, `inline` World!\n");32 try std.fs.File.stdout().writeAll("Hello, `inline` World!\n");
33}33}
34const std = @import("std");34const std = @import("std");
35#expect_stdout="Hello, `inline` World!\n"35#expect_stdout="Hello, `inline` World!\n"
test/incremental/hello+2-2
...@@ -6,13 +6,13 @@...@@ -6,13 +6,13 @@
6#file=main.zig6#file=main.zig
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 try std.io.getStdOut().writeAll("good morning\n");9 try std.fs.File.stdout().writeAll("good morning\n");
10}10}
11#expect_stdout="good morning\n"11#expect_stdout="good morning\n"
12#update=change the string12#update=change the string
13#file=main.zig13#file=main.zig
14const std = @import("std");14const std = @import("std");
15pub fn main() !void {15pub fn main() !void {
16 try std.io.getStdOut().writeAll("おはようございます\n");16 try std.fs.File.stdout().writeAll("おはようございます\n");
17}17}
18#expect_stdout="おはようございます\n"18#expect_stdout="おはようございます\n"
test/incremental/make_decl_pub+2-2
...@@ -11,7 +11,7 @@ pub fn main() !void {...@@ -11,7 +11,7 @@ pub fn main() !void {
11#file=foo.zig11#file=foo.zig
12const std = @import("std");12const std = @import("std");
13fn hello() !void {13fn hello() !void {
14 try std.io.getStdOut().writeAll("Hello, World!\n");14 try std.fs.File.stdout().writeAll("Hello, World!\n");
15}15}
16#expect_error=main.zig:3:12: error: 'hello' is not marked 'pub'16#expect_error=main.zig:3:12: error: 'hello' is not marked 'pub'
17#expect_error=foo.zig:2:1: note: declared here17#expect_error=foo.zig:2:1: note: declared here
...@@ -20,6 +20,6 @@ fn hello() !void {...@@ -20,6 +20,6 @@ fn hello() !void {
20#file=foo.zig20#file=foo.zig
21const std = @import("std");21const std = @import("std");
22pub fn hello() !void {22pub fn hello() !void {
23 try std.io.getStdOut().writeAll("Hello, World!\n");23 try std.fs.File.stdout().writeAll("Hello, World!\n");
24}24}
25#expect_stdout="Hello, World!\n"25#expect_stdout="Hello, World!\n"
test/incremental/modify_inline_fn+2-2
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 const str = getStr();9 const str = getStr();
10 try std.io.getStdOut().writeAll(str);10 try std.fs.File.stdout().writeAll(str);
11}11}
12inline fn getStr() []const u8 {12inline fn getStr() []const u8 {
13 return "foo\n";13 return "foo\n";
...@@ -18,7 +18,7 @@ inline fn getStr() []const u8 {...@@ -18,7 +18,7 @@ inline fn getStr() []const u8 {
18const std = @import("std");18const std = @import("std");
19pub fn main() !void {19pub fn main() !void {
20 const str = getStr();20 const str = getStr();
21 try std.io.getStdOut().writeAll(str);21 try std.fs.File.stdout().writeAll(str);
22}22}
23inline fn getStr() []const u8 {23inline fn getStr() []const u8 {
24 return "bar\n";24 return "bar\n";
test/incremental/move_src+6-4
...@@ -6,7 +6,8 @@...@@ -6,7 +6,8 @@
6#file=main.zig6#file=main.zig
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 try std.io.getStdOut().writer().print("{d} {d}\n", .{ foo(), bar() });9 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
10 try stdout_writer.interface.print("{d} {d}\n", .{ foo(), bar() });
10}11}
11fn foo() u32 {12fn foo() u32 {
12 return @src().line;13 return @src().line;
...@@ -14,13 +15,14 @@ fn foo() u32 {...@@ -14,13 +15,14 @@ fn foo() u32 {
14fn bar() u32 {15fn bar() u32 {
15 return 123;16 return 123;
16}17}
17#expect_stdout="6 123\n"18#expect_stdout="7 123\n"
1819
19#update=add newline20#update=add newline
20#file=main.zig21#file=main.zig
21const std = @import("std");22const std = @import("std");
22pub fn main() !void {23pub fn main() !void {
23 try std.io.getStdOut().writer().print("{d} {d}\n", .{ foo(), bar() });24 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
25 try stdout_writer.interface.print("{d} {d}\n", .{ foo(), bar() });
24}26}
2527
26fn foo() u32 {28fn foo() u32 {
...@@ -29,4 +31,4 @@ fn foo() u32 {...@@ -29,4 +31,4 @@ fn foo() u32 {
29fn bar() u32 {31fn bar() u32 {
30 return 123;32 return 123;
31}33}
32#expect_stdout="7 123\n"34#expect_stdout="8 123\n"
test/incremental/no_change_preserves_tag_names+2-2
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const std = @import("std");7const std = @import("std");
8var some_enum: enum { first, second } = .first;8var some_enum: enum { first, second } = .first;
9pub fn main() !void {9pub fn main() !void {
10 try std.io.getStdOut().writeAll(@tagName(some_enum));10 try std.fs.File.stdout().writeAll(@tagName(some_enum));
11}11}
12#expect_stdout="first"12#expect_stdout="first"
13#update=no change13#update=no change
...@@ -15,6 +15,6 @@ pub fn main() !void {...@@ -15,6 +15,6 @@ pub fn main() !void {
15const std = @import("std");15const std = @import("std");
16var some_enum: enum { first, second } = .first;16var some_enum: enum { first, second } = .first;
17pub fn main() !void {17pub fn main() !void {
18 try std.io.getStdOut().writeAll(@tagName(some_enum));18 try std.fs.File.stdout().writeAll(@tagName(some_enum));
19}19}
20#expect_stdout="first"20#expect_stdout="first"
test/incremental/recursive_function_becomes_non_recursive+2-2
...@@ -8,7 +8,7 @@ pub fn main() !void {...@@ -8,7 +8,7 @@ pub fn main() !void {
8 try foo(false);8 try foo(false);
9}9}
10fn foo(recurse: bool) !void {10fn foo(recurse: bool) !void {
11 const stdout = std.io.getStdOut().writer();11 const stdout = std.fs.File.stdout();
12 if (recurse) return foo(true);12 if (recurse) return foo(true);
13 try stdout.writeAll("non-recursive path\n");13 try stdout.writeAll("non-recursive path\n");
14}14}
...@@ -21,7 +21,7 @@ pub fn main() !void {...@@ -21,7 +21,7 @@ pub fn main() !void {
21 try foo(true);21 try foo(true);
22}22}
23fn foo(recurse: bool) !void {23fn foo(recurse: bool) !void {
24 const stdout = std.io.getStdOut().writer();24 const stdout = std.fs.File.stdout();
25 if (recurse) return stdout.writeAll("x==1\n");25 if (recurse) return stdout.writeAll("x==1\n");
26 try stdout.writeAll("non-recursive path\n");26 try stdout.writeAll("non-recursive path\n");
27}27}
test/incremental/remove_enum_field+5-3
...@@ -9,7 +9,8 @@ const MyEnum = enum(u8) {...@@ -9,7 +9,8 @@ const MyEnum = enum(u8) {
9 bar = 2,9 bar = 2,
10};10};
11pub fn main() !void {11pub fn main() !void {
12 try std.io.getStdOut().writer().print("{}\n", .{@intFromEnum(MyEnum.foo)});12 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
13 try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)});
13}14}
14const std = @import("std");15const std = @import("std");
15#expect_stdout="1\n"16#expect_stdout="1\n"
...@@ -20,8 +21,9 @@ const MyEnum = enum(u8) {...@@ -20,8 +21,9 @@ const MyEnum = enum(u8) {
20 bar = 2,21 bar = 2,
21};22};
22pub fn main() !void {23pub fn main() !void {
23 try std.io.getStdOut().writer().print("{}\n", .{@intFromEnum(MyEnum.foo)});24 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
25 try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)});
24}26}
25const std = @import("std");27const std = @import("std");
26#expect_error=main.zig:6:73: error: enum 'main.MyEnum' has no member named 'foo'28#expect_error=main.zig:7:69: error: enum 'main.MyEnum' has no member named 'foo'
27#expect_error=main.zig:1:16: note: enum declared here29#expect_error=main.zig:1:16: note: enum declared here
test/incremental/unreferenced_error+4-4
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6#file=main.zig6#file=main.zig
7const std = @import("std");7const std = @import("std");
8pub fn main() !void {8pub fn main() !void {
9 try std.io.getStdOut().writeAll(a);9 try std.fs.File.stdout().writeAll(a);
10}10}
11const a = "Hello, World!\n";11const a = "Hello, World!\n";
12#expect_stdout="Hello, World!\n"12#expect_stdout="Hello, World!\n"
...@@ -15,7 +15,7 @@ const a = "Hello, World!\n";...@@ -15,7 +15,7 @@ const a = "Hello, World!\n";
15#file=main.zig15#file=main.zig
16const std = @import("std");16const std = @import("std");
17pub fn main() !void {17pub fn main() !void {
18 try std.io.getStdOut().writeAll(a);18 try std.fs.File.stdout().writeAll(a);
19}19}
20const a = @compileError("bad a");20const a = @compileError("bad a");
21#expect_error=main.zig:5:11: error: bad a21#expect_error=main.zig:5:11: error: bad a
...@@ -24,7 +24,7 @@ const a = @compileError("bad a");...@@ -24,7 +24,7 @@ const a = @compileError("bad a");
24#file=main.zig24#file=main.zig
25const std = @import("std");25const std = @import("std");
26pub fn main() !void {26pub fn main() !void {
27 try std.io.getStdOut().writeAll(b);27 try std.fs.File.stdout().writeAll(b);
28}28}
29const a = @compileError("bad a");29const a = @compileError("bad a");
30const b = "Hi there!\n";30const b = "Hi there!\n";
...@@ -34,7 +34,7 @@ const b = "Hi there!\n";...@@ -34,7 +34,7 @@ const b = "Hi there!\n";
34#file=main.zig34#file=main.zig
35const std = @import("std");35const std = @import("std");
36pub fn main() !void {36pub fn main() !void {
37 try std.io.getStdOut().writeAll(a);37 try std.fs.File.stdout().writeAll(a);
38}38}
39const a = "Back to a\n";39const a = "Back to a\n";
40const b = @compileError("bad b");40const b = @compileError("bad b");
test/link/bss/main.zig+4-1
...@@ -4,8 +4,11 @@ const std = @import("std");...@@ -4,8 +4,11 @@ const std = @import("std");
4var buffer: [0x1000000]u64 = [1]u64{0} ** 0x1000000;4var buffer: [0x1000000]u64 = [1]u64{0} ** 0x1000000;
55
6pub fn main() anyerror!void {6pub fn main() anyerror!void {
7 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
8
7 buffer[0x10] = 1;9 buffer[0x10] = 1;
8 try std.io.getStdOut().writer().print("{d}, {d}, {d}\n", .{10
11 try stdout_writer.interface.print("{d}, {d}, {d}\n", .{
9 // workaround the dreaded decl_val12 // workaround the dreaded decl_val
10 (&buffer)[0],13 (&buffer)[0],
11 (&buffer)[0x10],14 (&buffer)[0x10],
test/link/elf.zig+4-4
...@@ -1315,8 +1315,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {...@@ -1315,8 +1315,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {
1315 \\extern var live_var2: i32;1315 \\extern var live_var2: i32;
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 \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
1319 \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable;1319 \\ stdout_writer.interface.print("{d} {d}\n", .{ live_var1, live_var2 }) catch @panic("fail");
1320 \\ live_fn2();1320 \\ live_fn2();
1321 \\}1321 \\}
1322 ,1322 ,
...@@ -1357,8 +1357,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {...@@ -1357,8 +1357,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step {
1357 \\extern var live_var2: i32;1357 \\extern var live_var2: i32;
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 \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
1361 \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable;1361 \\ stdout_writer.interface.print("{d} {d}\n", .{ live_var1, live_var2 }) catch @panic("fail");
1362 \\ live_fn2();1362 \\ live_fn2();
1363 \\}1363 \\}
1364 ,1364 ,
test/link/macho.zig+4-3
...@@ -710,7 +710,7 @@ fn testHelloZig(b: *Build, opts: Options) *Step {...@@ -710,7 +710,7 @@ fn testHelloZig(b: *Build, opts: Options) *Step {
710 const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes = 710 const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes =
711 \\const std = @import("std");711 \\const std = @import("std");
712 \\pub fn main() void {712 \\pub fn main() void {
713 \\ std.io.getStdOut().writer().print("Hello world!\n", .{}) catch unreachable;713 \\ std.fs.File.stdout().writeAll("Hello world!\n") catch @panic("fail");
714 \\}714 \\}
715 });715 });
716716
...@@ -2365,10 +2365,11 @@ fn testTlsZig(b: *Build, opts: Options) *Step {...@@ -2365,10 +2365,11 @@ fn testTlsZig(b: *Build, opts: Options) *Step {
2365 \\threadlocal var x: i32 = 0;2365 \\threadlocal var x: i32 = 0;
2366 \\threadlocal var y: i32 = -1;2366 \\threadlocal var y: i32 = -1;
2367 \\pub fn main() void {2367 \\pub fn main() void {
2368 \\ std.io.getStdOut().writer().print("{d} {d}\n", .{x, y}) catch unreachable;2368 \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
2369 \\ stdout_writer.interface.print("{d} {d}\n", .{x, y}) catch unreachable;
2369 \\ x -= 1;2370 \\ x -= 1;
2370 \\ y += 1;2371 \\ y += 1;
2371 \\ std.io.getStdOut().writer().print("{d} {d}\n", .{x, y}) catch unreachable;2372 \\ stdout_writer.interface.print("{d} {d}\n", .{x, y}) catch unreachable;
2372 \\}2373 \\}
2373 });2374 });
23742375
test/link/wasm/extern/main.zig+2-2
...@@ -3,6 +3,6 @@ const std = @import("std");...@@ -3,6 +3,6 @@ const std = @import("std");
3extern const foo: u32;3extern const foo: u32;
44
5pub fn main() void {5pub fn main() void {
6 const std_out = std.io.getStdOut();6 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
7 std_out.writer().print("Result: {d}", .{foo}) catch {};7 stdout_writer.interface.print("Result: {d}", .{foo}) catch {};
8}8}
test/src/check-stack-trace.zig+1-1
...@@ -84,5 +84,5 @@ pub fn main() !void {...@@ -84,5 +84,5 @@ pub fn main() !void {
84 break :got_result try buf.toOwnedSlice();84 break :got_result try buf.toOwnedSlice();
85 };85 };
8686
87 try std.io.getStdOut().writeAll(got);87 try std.fs.File.stdout().writeAll(got);
88}88}
test/standalone/child_process/child.zig+4-3
...@@ -27,12 +27,12 @@ fn run(allocator: std.mem.Allocator) !void {...@@ -27,12 +27,12 @@ fn run(allocator: std.mem.Allocator) !void {
27 }27 }
2828
29 // test stdout pipe; parent verifies29 // test stdout pipe; parent verifies
30 try std.io.getStdOut().writer().writeAll("hello from stdout");30 try std.fs.File.stdout().writeAll("hello from stdout");
3131
32 // test stdin pipe from parent32 // test stdin pipe from parent
33 const hello_stdin = "hello from stdin";33 const hello_stdin = "hello from stdin";
34 var buf: [hello_stdin.len]u8 = undefined;34 var buf: [hello_stdin.len]u8 = undefined;
35 const stdin = std.io.getStdIn().reader();35 const stdin: std.fs.File = .stdin();
36 const n = try stdin.readAll(&buf);36 const n = try stdin.readAll(&buf);
37 if (!std.mem.eql(u8, buf[0..n], hello_stdin)) {37 if (!std.mem.eql(u8, buf[0..n], hello_stdin)) {
38 testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin });38 testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin });
...@@ -40,7 +40,8 @@ fn run(allocator: std.mem.Allocator) !void {...@@ -40,7 +40,8 @@ fn run(allocator: std.mem.Allocator) !void {
40}40}
4141
42fn testError(comptime fmt: []const u8, args: anytype) void {42fn testError(comptime fmt: []const u8, args: anytype) void {
43 const stderr = std.io.getStdErr().writer();43 var stderr_writer = std.fs.File.stderr().writer(&.{});
44 const stderr = &stderr_writer.interface;
44 stderr.print("CHILD TEST ERROR: ", .{}) catch {};45 stderr.print("CHILD TEST ERROR: ", .{}) catch {};
45 stderr.print(fmt, args) catch {};46 stderr.print(fmt, args) catch {};
46 if (fmt[fmt.len - 1] != '\n') {47 if (fmt[fmt.len - 1] != '\n') {
test/standalone/child_process/main.zig+4-3
...@@ -19,13 +19,13 @@ pub fn main() !void {...@@ -19,13 +19,13 @@ pub fn main() !void {
19 child.stderr_behavior = .Inherit;19 child.stderr_behavior = .Inherit;
20 try child.spawn();20 try child.spawn();
21 const child_stdin = child.stdin.?;21 const child_stdin = child.stdin.?;
22 try child_stdin.writer().writeAll("hello from stdin"); // verified in child22 try child_stdin.writeAll("hello from stdin"); // verified in child
23 child_stdin.close();23 child_stdin.close();
24 child.stdin = null;24 child.stdin = null;
2525
26 const hello_stdout = "hello from stdout";26 const hello_stdout = "hello from stdout";
27 var buf: [hello_stdout.len]u8 = undefined;27 var buf: [hello_stdout.len]u8 = undefined;
28 const n = try child.stdout.?.reader().readAll(&buf);28 const n = try child.stdout.?.deprecatedReader().readAll(&buf);
29 if (!std.mem.eql(u8, buf[0..n], hello_stdout)) {29 if (!std.mem.eql(u8, buf[0..n], hello_stdout)) {
30 testError("child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout });30 testError("child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout });
31 }31 }
...@@ -45,7 +45,8 @@ pub fn main() !void {...@@ -45,7 +45,8 @@ pub fn main() !void {
45var parent_test_error = false;45var parent_test_error = false;
4646
47fn testError(comptime fmt: []const u8, args: anytype) void {47fn testError(comptime fmt: []const u8, args: anytype) void {
48 const stderr = std.io.getStdErr().writer();48 var stderr_writer = std.fs.File.stderr().writer(&.{});
49 const stderr = &stderr_writer.interface;
49 stderr.print("PARENT TEST ERROR: ", .{}) catch {};50 stderr.print("PARENT TEST ERROR: ", .{}) catch {};
50 stderr.print(fmt, args) catch {};51 stderr.print(fmt, args) catch {};
51 if (fmt[fmt.len - 1] != '\n') {52 if (fmt[fmt.len - 1] != '\n') {
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/sigpipe/breakpipe.zig+1-1
...@@ -10,7 +10,7 @@ pub fn main() !void {...@@ -10,7 +10,7 @@ pub fn main() !void {
10 std.posix.close(pipe[0]);10 std.posix.close(pipe[0]);
11 _ = std.posix.write(pipe[1], "a") catch |err| switch (err) {11 _ = std.posix.write(pipe[1], "a") catch |err| switch (err) {
12 error.BrokenPipe => {12 error.BrokenPipe => {
13 try std.io.getStdOut().writer().writeAll("BrokenPipe\n");13 try std.fs.File.stdout().writeAll("BrokenPipe\n");
14 std.posix.exit(123);14 std.posix.exit(123);
15 },15 },
16 else => |e| return e,16 else => |e| return e,
test/standalone/simple/brace_expansion.zig deleted-292
...@@ -1,292 +0,0 @@
1const std = @import("std");
2const io = std.io;
3const mem = std.mem;
4const debug = std.debug;
5const assert = debug.assert;
6const testing = std.testing;
7const ArrayList = std.ArrayList;
8const maxInt = std.math.maxInt;
9
10const Token = union(enum) {
11 Word: []const u8,
12 OpenBrace,
13 CloseBrace,
14 Comma,
15 Eof,
16};
17
18var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
19var global_allocator = gpa.allocator();
20
21fn tokenize(input: []const u8) !ArrayList(Token) {
22 const State = enum {
23 Start,
24 Word,
25 };
26
27 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
29 var tok_begin: usize = undefined;
30 var state = State.Start;
31
32 for (input, 0..) |b, i| {
33 switch (state) {
34 .Start => switch (b) {
35 'a'...'z', 'A'...'Z' => {
36 state = State.Word;
37 tok_begin = i;
38 },
39 '{' => try token_list.append(Token.OpenBrace),
40 '}' => try token_list.append(Token.CloseBrace),
41 ',' => try token_list.append(Token.Comma),
42 else => return error.InvalidInput,
43 },
44 .Word => switch (b) {
45 'a'...'z', 'A'...'Z' => {},
46 '{', '}', ',' => {
47 try token_list.append(Token{ .Word = input[tok_begin..i] });
48 switch (b) {
49 '{' => try token_list.append(Token.OpenBrace),
50 '}' => try token_list.append(Token.CloseBrace),
51 ',' => try token_list.append(Token.Comma),
52 else => unreachable,
53 }
54 state = State.Start;
55 },
56 else => return error.InvalidInput,
57 },
58 }
59 }
60 switch (state) {
61 State.Start => {},
62 State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
63 }
64 try token_list.append(Token.Eof);
65 return token_list;
66}
67
68const Node = union(enum) {
69 Scalar: []const u8,
70 List: ArrayList(Node),
71 Combine: []Node,
72
73 fn deinit(self: Node) void {
74 switch (self) {
75 .Scalar => {},
76 .Combine => |pair| {
77 pair[0].deinit();
78 pair[1].deinit();
79 global_allocator.free(pair);
80 },
81 .List => |list| {
82 for (list.items) |item| {
83 item.deinit();
84 }
85 list.deinit();
86 },
87 }
88 }
89};
90
91const ParseError = error{
92 InvalidInput,
93 OutOfMemory,
94};
95
96fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
97 const first_token = tokens.items[token_index.*];
98 token_index.* += 1;
99
100 const result_node = switch (first_token) {
101 .Word => |word| Node{ .Scalar = word },
102 .OpenBrace => blk: {
103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
108 while (true) {
109 try list.append(try parse(tokens, token_index));
110
111 const token = tokens.items[token_index.*];
112 token_index.* += 1;
113
114 switch (token) {
115 .CloseBrace => break,
116 .Comma => continue,
117 else => return error.InvalidInput,
118 }
119 }
120 break :blk Node{ .List = list };
121 },
122 else => return error.InvalidInput,
123 };
124
125 switch (tokens.items[token_index.*]) {
126 .Word, .OpenBrace => {
127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
129 pair[0] = result_node;
130 pair[1] = try parse(tokens, token_index);
131 return Node{ .Combine = pair };
132 },
133 else => return result_node,
134 }
135}
136
137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
138 const tokens = try tokenize(input);
139 defer tokens.deinit();
140 if (tokens.items.len == 1) {
141 return output.resize(0);
142 }
143
144 var token_index: usize = 0;
145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
147 const last_token = tokens.items[token_index];
148 switch (last_token) {
149 Token.Eof => {},
150 else => return error.InvalidInput,
151 }
152
153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
158
159 try expandNode(root, &result_list);
160
161 try output.resize(0);
162 for (result_list.items, 0..) |buf, i| {
163 if (i != 0) {
164 try output.append(' ');
165 }
166 try output.appendSlice(buf.items);
167 }
168}
169
170const ExpandNodeError = error{OutOfMemory};
171
172fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void {
173 assert(output.items.len == 0);
174 switch (node) {
175 .Scalar => |scalar| {
176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
180 },
181 .Combine => |pair| {
182 const a_node = pair[0];
183 const b_node = pair[1];
184
185 var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator);
186 defer {
187 for (child_list_a.items) |*buf| buf.deinit();
188 child_list_a.deinit();
189 }
190 try expandNode(a_node, &child_list_a);
191
192 var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator);
193 defer {
194 for (child_list_b.items) |*buf| buf.deinit();
195 child_list_b.deinit();
196 }
197 try expandNode(b_node, &child_list_b);
198
199 for (child_list_a.items) |buf_a| {
200 for (child_list_b.items) |buf_b| {
201 var combined_buf = ArrayList(u8).init(global_allocator);
202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
206 try output.append(combined_buf);
207 }
208 }
209 },
210 .List => |list| {
211 for (list.items) |child_node| {
212 var child_list = ArrayList(ArrayList(u8)).init(global_allocator);
213 errdefer for (child_list.items) |*buf| buf.deinit();
214 defer child_list.deinit();
215
216 try expandNode(child_node, &child_list);
217
218 for (child_list.items) |buf| {
219 try output.append(buf);
220 }
221 }
222 },
223 }
224}
225
226pub fn main() !void {
227 defer _ = gpa.deinit();
228 const stdin_file = io.getStdIn();
229 const stdout_file = io.getStdOut();
230
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232 defer global_allocator.free(stdin);
233
234 var result_buf = ArrayList(u8).init(global_allocator);
235 defer result_buf.deinit();
236
237 try expandString(stdin, &result_buf);
238 try stdout_file.writeAll(result_buf.items);
239}
240
241test "invalid inputs" {
242 global_allocator = std.testing.allocator;
243
244 try expectError("}ABC", error.InvalidInput);
245 try expectError("{ABC", error.InvalidInput);
246 try expectError("}{", error.InvalidInput);
247 try expectError("{}", error.InvalidInput);
248 try expectError("A,B,C", error.InvalidInput);
249 try expectError("{A{B,C}", error.InvalidInput);
250 try expectError("{A,}", error.InvalidInput);
251
252 try expectError("\n", error.InvalidInput);
253}
254
255fn expectError(test_input: []const u8, expected_err: anyerror) !void {
256 var output_buf = ArrayList(u8).init(global_allocator);
257 defer output_buf.deinit();
258
259 try testing.expectError(expected_err, expandString(test_input, &output_buf));
260}
261
262test "valid inputs" {
263 global_allocator = std.testing.allocator;
264
265 try expectExpansion("{x,y,z}", "x y z");
266 try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
267 try expectExpansion("{A,B{x,y}}", "A Bx By");
268
269 try expectExpansion("{ABC}", "ABC");
270 try expectExpansion("{A,B,C}", "A B C");
271 try expectExpansion("ABC", "ABC");
272
273 try expectExpansion("", "");
274 try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
275 try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
276 try expectExpansion("{A,B}a", "Aa Ba");
277 try expectExpansion("{C,{x,y}}", "C x y");
278 try expectExpansion("z{C,{x,y}}", "zC zx zy");
279 try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
280 try expectExpansion("a{x,y}b", "axb ayb");
281 try expectExpansion("z{{a,b}}", "za zb");
282 try expectExpansion("a{b}", "ab");
283}
284
285fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void {
286 var result = ArrayList(u8).init(global_allocator);
287 defer result.deinit();
288
289 expandString(test_input, &result) catch unreachable;
290
291 try testing.expectEqualSlices(u8, expected_result, result.items);
292}
test/standalone/simple/build.zig-4
...@@ -109,10 +109,6 @@ const cases = [_]Case{...@@ -109,10 +109,6 @@ const cases = [_]Case{
109 //.{109 //.{
110 // .src_path = "issue_9693/main.zig",110 // .src_path = "issue_9693/main.zig",
111 //},111 //},
112 .{
113 .src_path = "brace_expansion.zig",
114 .is_test = true,
115 },
116 .{112 .{
117 .src_path = "issue_7030.zig",113 .src_path = "issue_7030.zig",
118 .target = .{114 .target = .{
test/standalone/simple/cat/main.zig+10-10
...@@ -1,42 +1,42 @@...@@ -1,42 +1,42 @@
1const std = @import("std");1const std = @import("std");
2const io = std.io;2const io = std.io;
3const process = std.process;
4const fs = std.fs;3const fs = std.fs;
5const mem = std.mem;4const mem = std.mem;
6const warn = std.log.warn;5const warn = std.log.warn;
6const fatal = std.process.fatal;
77
8pub fn main() !void {8pub fn main() !void {
9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena_instance.deinit();10 defer arena_instance.deinit();
11 const arena = arena_instance.allocator();11 const arena = arena_instance.allocator();
1212
13 const args = try process.argsAlloc(arena);13 const args = try std.process.argsAlloc(arena);
1414
15 const exe = args[0];15 const exe = args[0];
16 var catted_anything = false;16 var catted_anything = false;
17 const stdout_file = io.getStdOut();17 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
18 const stdout = &stdout_writer.interface;
19 var stdin_reader = std.fs.File.stdin().reader(&.{});
1820
19 const cwd = fs.cwd();21 const cwd = fs.cwd();
2022
21 for (args[1..]) |arg| {23 for (args[1..]) |arg| {
22 if (mem.eql(u8, arg, "-")) {24 if (mem.eql(u8, arg, "-")) {
23 catted_anything = true;25 catted_anything = true;
24 try stdout_file.writeFileAll(io.getStdIn(), .{});26 _ = try stdout.sendFileAll(&stdin_reader, .unlimited);
25 } else if (mem.startsWith(u8, arg, "-")) {27 } else if (mem.startsWith(u8, arg, "-")) {
26 return usage(exe);28 return usage(exe);
27 } else {29 } else {
28 const file = cwd.openFile(arg, .{}) catch |err| {30 const file = cwd.openFile(arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err});
29 warn("Unable to open file: {s}\n", .{@errorName(err)});
30 return err;
31 };
32 defer file.close();31 defer file.close();
3332
34 catted_anything = true;33 catted_anything = true;
35 try stdout_file.writeFileAll(file, .{});34 var file_reader = file.reader(&.{});
35 _ = try stdout.sendFileAll(&file_reader, .unlimited);
36 }36 }
37 }37 }
38 if (!catted_anything) {38 if (!catted_anything) {
39 try stdout_file.writeFileAll(io.getStdIn(), .{});39 _ = try stdout.sendFileAll(&stdin_reader, .unlimited);
40 }40 }
41}41}
4242
test/standalone/simple/guess_number/main.zig+11-13
...@@ -1,37 +1,35 @@...@@ -1,37 +1,35 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const io = std.io;
4const fmt = std.fmt;
53
6pub fn main() !void {4pub fn main() !void {
7 const stdout = io.getStdOut().writer();5 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
8 const stdin = io.getStdIn();6 const out = &stdout_writer.interface;
7 const stdin: std.fs.File = .stdin();
98
10 try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});9 try out.writeAll("Welcome to the Guess Number Game in Zig.\n");
1110
12 const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1;11 const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1;
1312
14 while (true) {13 while (true) {
15 try stdout.print("\nGuess a number between 1 and 100: ", .{});14 try out.writeAll("\nGuess a number between 1 and 100: ");
16 var line_buf: [20]u8 = undefined;15 var line_buf: [20]u8 = undefined;
17
18 const amt = try stdin.read(&line_buf);16 const amt = try stdin.read(&line_buf);
19 if (amt == line_buf.len) {17 if (amt == line_buf.len) {
20 try stdout.print("Input too long.\n", .{});18 try out.writeAll("Input too long.\n");
21 continue;19 continue;
22 }20 }
23 const line = std.mem.trimEnd(u8, line_buf[0..amt], "\r\n");21 const line = std.mem.trimEnd(u8, line_buf[0..amt], "\r\n");
2422
25 const guess = fmt.parseUnsigned(u8, line, 10) catch {23 const guess = std.fmt.parseUnsigned(u8, line, 10) catch {
26 try stdout.print("Invalid number.\n", .{});24 try out.writeAll("Invalid number.\n");
27 continue;25 continue;
28 };26 };
29 if (guess > answer) {27 if (guess > answer) {
30 try stdout.print("Guess lower.\n", .{});28 try out.writeAll("Guess lower.\n");
31 } else if (guess < answer) {29 } else if (guess < answer) {
32 try stdout.print("Guess higher.\n", .{});30 try out.writeAll("Guess higher.\n");
33 } else {31 } else {
34 try stdout.print("You win!\n", .{});32 try out.writeAll("You win!\n");
35 return;33 return;
36 }34 }
37 }35 }
test/standalone/simple/hello_world/hello.zig+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() !void {3pub fn main() !void {
4 try std.io.getStdOut().writeAll("Hello, World!\n");4 try std.fs.File.stdout().writeAll("Hello, World!\n");
5}5}
test/standalone/simple/std_enums_big_enums.zig+1
...@@ -6,6 +6,7 @@ pub fn main() void {...@@ -6,6 +6,7 @@ pub fn main() void {
6 const Big = @Type(.{ .@"enum" = .{6 const Big = @Type(.{ .@"enum" = .{
7 .tag_type = u16,7 .tag_type = u16,
8 .fields = make_fields: {8 .fields = make_fields: {
9 @setEvalBranchQuota(500000);
9 var fields: [1001]std.builtin.Type.EnumField = undefined;10 var fields: [1001]std.builtin.Type.EnumField = undefined;
10 for (&fields, 0..) |*field, i| {11 for (&fields, 0..) |*field, i| {
11 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };12 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };
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/standalone/windows_bat_args/echo-args.zig+2-1
...@@ -5,7 +5,8 @@ pub fn main() !void {...@@ -5,7 +5,8 @@ pub fn main() !void {
5 defer arena_state.deinit();5 defer arena_state.deinit();
6 const arena = arena_state.allocator();6 const arena = arena_state.allocator();
77
8 const stdout = std.io.getStdOut().writer();8 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
9 const stdout = &stdout_writer.interface;
9 var args = try std.process.argsAlloc(arena);10 var args = try std.process.argsAlloc(arena);
10 for (args[1..], 1..) |arg, i| {11 for (args[1..], 1..) |arg, i| {
11 try stdout.writeAll(arg);12 try stdout.writeAll(arg);
test/standalone/windows_spawn/hello.zig+2-1
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() !void {3pub fn main() !void {
4 const stdout = std.io.getStdOut().writer();4 var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
5 const stdout = &stdout_writer.interface;
5 try stdout.writeAll("hello from exe\n");6 try stdout.writeAll("hello from exe\n");
6}7}
test/tests.zig+11-9
...@@ -918,14 +918,16 @@ const test_targets = blk: {...@@ -918,14 +918,16 @@ const test_targets = blk: {
918 .link_libc = true,918 .link_libc = true,
919 },919 },
920920
921 .{921 // TODO implement codegen airFieldParentPtr
922 .target = std.Target.Query.parse(.{922 // TODO implement airMemmove for riscv64
923 .arch_os_abi = "riscv64-linux-none",923 //.{
924 .cpu_features = "baseline+v+zbb",924 // .target = std.Target.Query.parse(.{
925 }) catch unreachable,925 // .arch_os_abi = "riscv64-linux-none",
926 .use_llvm = false,926 // .cpu_features = "baseline+v+zbb",
927 .use_lld = false,927 // }) catch unreachable,
928 },928 // .use_llvm = false,
929 // .use_lld = false,
930 //},
929 .{931 .{
930 .target = .{932 .target = .{
931 .cpu_arch = .riscv64,933 .cpu_arch = .riscv64,
...@@ -2753,7 +2755,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {...@@ -2753,7 +2755,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
27532755
2754 run.addArg(b.graph.zig_exe);2756 run.addArg(b.graph.zig_exe);
2755 run.addFileArg(b.path("test/incremental/").path(b, entry.path));2757 run.addFileArg(b.path("test/incremental/").path(b, entry.path));
2756 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });2758 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
27572759
2758 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });2760 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
27592761
tools/docgen.zig+4-5
...@@ -43,8 +43,7 @@ pub fn main() !void {...@@ -43,8 +43,7 @@ pub fn main() !void {
43 while (args_it.next()) |arg| {43 while (args_it.next()) |arg| {
44 if (mem.startsWith(u8, arg, "-")) {44 if (mem.startsWith(u8, arg, "-")) {
45 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {45 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
46 const stdout = io.getStdOut().writer();46 try fs.File.stdout().writeAll(usage);
47 try stdout.writeAll(usage);
48 process.exit(0);47 process.exit(0);
49 } else if (mem.eql(u8, arg, "--code-dir")) {48 } else if (mem.eql(u8, arg, "--code-dir")) {
50 if (args_it.next()) |param| {49 if (args_it.next()) |param| {
...@@ -76,9 +75,9 @@ pub fn main() !void {...@@ -76,9 +75,9 @@ pub fn main() !void {
76 var code_dir = try fs.cwd().openDir(code_dir_path, .{});75 var code_dir = try fs.cwd().openDir(code_dir_path, .{});
77 defer code_dir.close();76 defer code_dir.close();
7877
79 const input_file_bytes = try in_file.reader().readAllAlloc(arena, max_doc_file_size);78 const input_file_bytes = try in_file.deprecatedReader().readAllAlloc(arena, max_doc_file_size);
8079
81 var buffered_writer = io.bufferedWriter(out_file.writer());80 var buffered_writer = io.bufferedWriter(out_file.deprecatedWriter());
8281
83 var tokenizer = Tokenizer.init(input_path, input_file_bytes);82 var tokenizer = Tokenizer.init(input_path, input_file_bytes);
84 var toc = try genToc(arena, &tokenizer);83 var toc = try genToc(arena, &tokenizer);
...@@ -426,7 +425,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -426,7 +425,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
426 try toc.writeByte('\n');425 try toc.writeByte('\n');
427 try toc.writeByteNTimes(' ', header_stack_size * 4);426 try toc.writeByteNTimes(' ', header_stack_size * 4);
428 if (last_columns) |n| {427 if (last_columns) |n| {
429 try toc.print("<ul style=\"columns: {}\">\n", .{n});428 try toc.print("<ul style=\"columns: {d}\">\n", .{n});
430 } else {429 } else {
431 try toc.writeAll("<ul>\n");430 try toc.writeAll("<ul>\n");
432 }431 }
tools/doctest.zig+2-2
...@@ -44,7 +44,7 @@ pub fn main() !void {...@@ -44,7 +44,7 @@ pub fn main() !void {
44 while (args_it.next()) |arg| {44 while (args_it.next()) |arg| {
45 if (mem.startsWith(u8, arg, "-")) {45 if (mem.startsWith(u8, arg, "-")) {
46 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {46 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
47 try std.io.getStdOut().writeAll(usage);47 try std.fs.File.stdout().writeAll(usage);
48 process.exit(0);48 process.exit(0);
49 } else if (mem.eql(u8, arg, "-i")) {49 } else if (mem.eql(u8, arg, "-i")) {
50 opt_input = args_it.next() orelse fatal("expected parameter after -i", .{});50 opt_input = args_it.next() orelse fatal("expected parameter after -i", .{});
...@@ -85,7 +85,7 @@ pub fn main() !void {...@@ -85,7 +85,7 @@ pub fn main() !void {
85 var out_file = try fs.cwd().createFile(output_path, .{});85 var out_file = try fs.cwd().createFile(output_path, .{});
86 defer out_file.close();86 defer out_file.close();
8787
88 var bw = std.io.bufferedWriter(out_file.writer());88 var bw = std.io.bufferedWriter(out_file.deprecatedWriter());
89 const out = bw.writer();89 const out = bw.writer();
9090
91 try printSourceBlock(arena, out, source, fs.path.basename(input_path));91 try printSourceBlock(arena, out, source, fs.path.basename(input_path));
tools/dump-cov.zig+4-3
...@@ -48,8 +48,9 @@ pub fn main() !void {...@@ -48,8 +48,9 @@ pub fn main() !void {
48 fatal("failed to load coverage file {}: {s}", .{ cov_path, @errorName(err) });48 fatal("failed to load coverage file {}: {s}", .{ cov_path, @errorName(err) });
49 };49 };
5050
51 var bw = std.io.bufferedWriter(std.io.getStdOut().writer());51 var stdout_buffer: [4000]u8 = undefined;
52 const stdout = bw.writer();52 var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
53 const stdout = &stdout_writer.interface;
5354
54 const header: *SeenPcsHeader = @ptrCast(cov_bytes);55 const header: *SeenPcsHeader = @ptrCast(cov_bytes);
55 try stdout.print("{any}\n", .{header.*});56 try stdout.print("{any}\n", .{header.*});
...@@ -83,5 +84,5 @@ pub fn main() !void {...@@ -83,5 +84,5 @@ pub fn main() !void {
83 });84 });
84 }85 }
8586
86 try bw.flush();87 try stdout.flush();
87}88}
tools/fetch_them_macos_headers.zig+2-13
...@@ -5,6 +5,8 @@ const mem = std.mem;...@@ -5,6 +5,8 @@ const mem = std.mem;
5const process = std.process;5const process = std.process;
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const tmpDir = std.testing.tmpDir;7const tmpDir = std.testing.tmpDir;
8const fatal = std.process.fatal;
9const info = std.log.info;
810
9const Allocator = mem.Allocator;11const Allocator = mem.Allocator;
10const OsTag = std.Target.Os.Tag;12const OsTag = std.Target.Os.Tag;
...@@ -245,19 +247,6 @@ const ArgsIterator = struct {...@@ -245,19 +247,6 @@ const ArgsIterator = struct {
245 }247 }
246};248};
247249
248fn info(comptime format: []const u8, args: anytype) void {
249 const msg = std.fmt.allocPrint(gpa, "info: " ++ format ++ "\n", args) catch return;
250 std.io.getStdOut().writeAll(msg) catch {};
251}
252
253fn fatal(comptime format: []const u8, args: anytype) noreturn {
254 ret: {
255 const msg = std.fmt.allocPrint(gpa, "fatal: " ++ format ++ "\n", args) catch break :ret;
256 std.io.getStdErr().writeAll(msg) catch {};
257 }
258 std.process.exit(1);
259}
260
261const Version = struct {250const Version = struct {
262 major: u16,251 major: u16,
263 minor: u8,252 minor: u8,
tools/gen_macos_headers_c.zig+9-17
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const info = std.log.info;
4const fatal = std.process.fatal;
35
4const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
57
...@@ -13,19 +15,6 @@ const usage =...@@ -13,19 +15,6 @@ const usage =
13 \\-h, --help Print this help and exit15 \\-h, --help Print this help and exit
14;16;
1517
16fn info(comptime format: []const u8, args: anytype) void {
17 const msg = std.fmt.allocPrint(gpa, "info: " ++ format ++ "\n", args) catch return;
18 std.io.getStdOut().writeAll(msg) catch {};
19}
20
21fn fatal(comptime format: []const u8, args: anytype) noreturn {
22 ret: {
23 const msg = std.fmt.allocPrint(gpa, "fatal: " ++ format ++ "\n", args) catch break :ret;
24 std.io.getStdErr().writeAll(msg) catch {};
25 }
26 std.process.exit(1);
27}
28
29pub fn main() anyerror!void {18pub fn main() anyerror!void {
30 var arena_allocator = std.heap.ArenaAllocator.init(gpa);19 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
31 defer arena_allocator.deinit();20 defer arena_allocator.deinit();
...@@ -58,16 +47,19 @@ pub fn main() anyerror!void {...@@ -58,16 +47,19 @@ pub fn main() anyerror!void {
5847
59 std.mem.sort([]const u8, paths.items, {}, SortFn.lessThan);48 std.mem.sort([]const u8, paths.items, {}, SortFn.lessThan);
6049
61 const stdout = std.io.getStdOut().writer();50 var buffer: [2000]u8 = undefined;
62 try stdout.writeAll("#define _XOPEN_SOURCE\n");51 var stdout_writer = std.fs.File.stdout().writerStreaming(&buffer);
52 const w = &stdout_writer.interface;
53 try w.writeAll("#define _XOPEN_SOURCE\n");
63 for (paths.items) |path| {54 for (paths.items) |path| {
64 try stdout.print("#include <{s}>\n", .{path});55 try w.print("#include <{s}>\n", .{path});
65 }56 }
66 try stdout.writeAll(57 try w.writeAll(
67 \\int main(int argc, char **argv) {58 \\int main(int argc, char **argv) {
68 \\ return 0;59 \\ return 0;
69 \\}60 \\}
70 );61 );
62 try w.flush();
71}63}
7264
73fn findHeaders(65fn findHeaders(
tools/gen_outline_atomics.zig+4-3
...@@ -17,8 +17,9 @@ pub fn main() !void {...@@ -17,8 +17,9 @@ pub fn main() !void {
1717
18 //const args = try std.process.argsAlloc(arena);18 //const args = try std.process.argsAlloc(arena);
1919
20 var bw = std.io.bufferedWriter(std.io.getStdOut().writer());20 var stdout_buffer: [2000]u8 = undefined;
21 const w = bw.writer();21 var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
22 const w = &stdout_writer.interface;
2223
23 try w.writeAll(24 try w.writeAll(
24 \\//! This file is generated by tools/gen_outline_atomics.zig.25 \\//! This file is generated by tools/gen_outline_atomics.zig.
...@@ -57,7 +58,7 @@ pub fn main() !void {...@@ -57,7 +58,7 @@ pub fn main() !void {
5758
58 try w.writeAll(footer.items);59 try w.writeAll(footer.items);
59 try w.writeAll("}\n");60 try w.writeAll("}\n");
60 try bw.flush();61 try w.flush();
61}62}
6263
63fn writeFunction(64fn writeFunction(
tools/gen_spirv_spec.zig+9-12
...@@ -91,9 +91,10 @@ pub fn main() !void {...@@ -91,9 +91,10 @@ pub fn main() !void {
9191
92 try readExtRegistry(&exts, a, std.fs.cwd(), args[2]);92 try readExtRegistry(&exts, a, std.fs.cwd(), args[2]);
9393
94 var bw = std.io.bufferedWriter(std.io.getStdOut().writer());94 var buffer: [4000]u8 = undefined;
95 try render(bw.writer(), a, core_spec, exts.items);95 var w = std.fs.File.stdout().writerStreaming(&buffer);
96 try bw.flush();96 try render(&w, a, core_spec, exts.items);
97 try w.flush();
97}98}
9899
99fn readExtRegistry(exts: *std.ArrayList(Extension), a: Allocator, dir: std.fs.Dir, sub_path: []const u8) !void {100fn readExtRegistry(exts: *std.ArrayList(Extension), a: Allocator, dir: std.fs.Dir, sub_path: []const u8) !void {
...@@ -166,7 +167,7 @@ fn tagPriorityScore(tag: []const u8) usize {...@@ -166,7 +167,7 @@ fn tagPriorityScore(tag: []const u8) usize {
166 }167 }
167}168}
168169
169fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []const Extension) !void {170fn render(writer: *std.io.Writer, a: Allocator, registry: CoreRegistry, extensions: []const Extension) !void {
170 try writer.writeAll(171 try writer.writeAll(
171 \\//! This file is auto-generated by tools/gen_spirv_spec.zig.172 \\//! This file is auto-generated by tools/gen_spirv_spec.zig.
172 \\173 \\
...@@ -188,15 +189,10 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c...@@ -188,15 +189,10 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c
188 \\ none,189 \\ none,
189 \\ _,190 \\ _,
190 \\191 \\
191 \\ pub fn format(192 \\ pub fn format(self: IdResult, writer: *std.io.Writer) std.io.Writer.Error!void {
192 \\ self: IdResult,
193 \\ comptime _: []const u8,
194 \\ _: std.fmt.FormatOptions,
195 \\ writer: anytype,
196 \\ ) @TypeOf(writer).Error!void {
197 \\ switch (self) {193 \\ switch (self) {
198 \\ .none => try writer.writeAll("(none)"),194 \\ .none => try writer.writeAll("(none)"),
199 \\ else => try writer.print("%{}", .{@intFromEnum(self)}),195 \\ else => try writer.print("%{d}", .{@intFromEnum(self)}),
200 \\ }196 \\ }
201 \\ }197 \\ }
202 \\};198 \\};
...@@ -899,7 +895,8 @@ fn parseHexInt(text: []const u8) !u31 {...@@ -899,7 +895,8 @@ fn parseHexInt(text: []const u8) !u31 {
899}895}
900896
901fn usageAndExit(arg0: []const u8, code: u8) noreturn {897fn usageAndExit(arg0: []const u8, code: u8) noreturn {
902 std.io.getStdErr().writer().print(898 const stderr = std.debug.lockStderrWriter(&.{});
899 stderr.print(
903 \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json>900 \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json>
904 \\901 \\
905 \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers902 \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers
tools/gen_stubs.zig+5-1
...@@ -333,7 +333,9 @@ pub fn main() !void {...@@ -333,7 +333,9 @@ pub fn main() !void {
333 }333 }
334 }334 }
335335
336 const stdout = std.io.getStdOut().writer();336 var stdout_buffer: [2000]u8 = undefined;
337 var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
338 const stdout = &stdout_writer.interface;
337 try stdout.writeAll(339 try stdout.writeAll(
338 \\#ifdef PTR64340 \\#ifdef PTR64
339 \\#define WEAK64 .weak341 \\#define WEAK64 .weak
...@@ -533,6 +535,8 @@ pub fn main() !void {...@@ -533,6 +535,8 @@ pub fn main() !void {
533 .all => {},535 .all => {},
534 .single, .multi, .family, .time32 => try stdout.writeAll("#endif\n"),536 .single, .multi, .family, .time32 => try stdout.writeAll("#endif\n"),
535 }537 }
538
539 try stdout.flush();
536}540}
537541
538fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian) !void {542fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian) !void {
tools/generate_JSONTestSuite.zig+5-1
...@@ -6,7 +6,9 @@ pub fn main() !void {...@@ -6,7 +6,9 @@ pub fn main() !void {
6 var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;6 var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
7 var allocator = gpa.allocator();7 var allocator = gpa.allocator();
88
9 var output = std.io.getStdOut().writer();9 var stdout_buffer: [2000]u8 = undefined;
10 var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
11 const output = &stdout_writer.interface;
10 try output.writeAll(12 try output.writeAll(
11 \\// This file was generated by _generate_JSONTestSuite.zig13 \\// This file was generated by _generate_JSONTestSuite.zig
12 \\// These test cases are sourced from: https://github.com/nst/JSONTestSuite14 \\// These test cases are sourced from: https://github.com/nst/JSONTestSuite
...@@ -44,6 +46,8 @@ pub fn main() !void {...@@ -44,6 +46,8 @@ pub fn main() !void {
44 try writeString(output, contents);46 try writeString(output, contents);
45 try output.writeAll(");\n}\n");47 try output.writeAll(");\n}\n");
46 }48 }
49
50 try output.flush();
47}51}
4852
49const i_structure_500_nested_arrays = "[" ** 500 ++ "]" ** 500;53const i_structure_500_nested_arrays = "[" ** 500 ++ "]" ** 500;
tools/generate_c_size_and_align_checks.zig+7-4
...@@ -42,20 +42,23 @@ pub fn main() !void {...@@ -42,20 +42,23 @@ pub fn main() !void {
42 const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] });42 const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] });
43 const target = try std.zig.system.resolveTargetQuery(query);43 const target = try std.zig.system.resolveTargetQuery(query);
4444
45 const stdout = std.io.getStdOut().writer();45 var buffer: [2000]u8 = undefined;
46 var stdout_writer = std.fs.File.stdout().writerStreaming(&buffer);
47 const w = &stdout_writer.interface;
46 inline for (@typeInfo(std.Target.CType).@"enum".fields) |field| {48 inline for (@typeInfo(std.Target.CType).@"enum".fields) |field| {
47 const c_type: std.Target.CType = @enumFromInt(field.value);49 const c_type: std.Target.CType = @enumFromInt(field.value);
48 try stdout.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{50 try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{
49 cName(c_type),51 cName(c_type),
50 target.cTypeByteSize(c_type),52 target.cTypeByteSize(c_type),
51 });53 });
52 try stdout.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{54 try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{
53 cName(c_type),55 cName(c_type),
54 target.cTypeAlignment(c_type),56 target.cTypeAlignment(c_type),
55 });57 });
56 try stdout.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{58 try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{
57 cName(c_type),59 cName(c_type),
58 target.cTypePreferredAlignment(c_type),60 target.cTypePreferredAlignment(c_type),
59 });61 });
60 }62 }
63 try w.flush();
61}64}
tools/generate_linux_syscalls.zig+11-9
...@@ -666,13 +666,16 @@ pub fn main() !void {...@@ -666,13 +666,16 @@ pub fn main() !void {
666 const allocator = arena.allocator();666 const allocator = arena.allocator();
667667
668 const args = try std.process.argsAlloc(allocator);668 const args = try std.process.argsAlloc(allocator);
669 if (args.len < 3 or mem.eql(u8, args[1], "--help"))669 if (args.len < 3 or mem.eql(u8, args[1], "--help")) {
670 usageAndExit(std.io.getStdErr(), args[0], 1);670 usage(std.debug.lockStderrWriter(&.{}), args[0]) catch std.process.exit(2);
671 std.process.exit(1);
672 }
671 const zig_exe = args[1];673 const zig_exe = args[1];
672 const linux_path = args[2];674 const linux_path = args[2];
673675
674 var buf_out = std.io.bufferedWriter(std.io.getStdOut().writer());676 var stdout_buffer: [2000]u8 = undefined;
675 const writer = buf_out.writer();677 var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
678 const writer = &stdout_writer.interface;
676679
677 var linux_dir = try std.fs.cwd().openDir(linux_path, .{});680 var linux_dir = try std.fs.cwd().openDir(linux_path, .{});
678 defer linux_dir.close();681 defer linux_dir.close();
...@@ -714,17 +717,16 @@ pub fn main() !void {...@@ -714,17 +717,16 @@ pub fn main() !void {
714 }717 }
715 }718 }
716719
717 try buf_out.flush();720 try writer.flush();
718}721}
719722
720fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {723fn usage(w: *std.io.Writer, arg0: []const u8) std.io.Writer.Error!void {
721 file.writer().print(724 try w.print(
722 \\Usage: {s} /path/to/zig /path/to/linux725 \\Usage: {s} /path/to/zig /path/to/linux
723 \\Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/zig /path/to/linux726 \\Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/zig /path/to/linux
724 \\727 \\
725 \\Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree.728 \\Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree.
726 \\Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig.729 \\Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig.
727 \\730 \\
728 , .{arg0}) catch std.process.exit(1);731 , .{arg0});
729 std.process.exit(code);
730}732}
tools/update_clang_options.zig+22-20
...@@ -634,25 +634,25 @@ pub fn main() anyerror!void {...@@ -634,25 +634,25 @@ pub fn main() anyerror!void {
634 const allocator = arena.allocator();634 const allocator = arena.allocator();
635 const args = try std.process.argsAlloc(allocator);635 const args = try std.process.argsAlloc(allocator);
636636
637 if (args.len <= 1) {637 var stdout_buffer: [4000]u8 = undefined;
638 usageAndExit(std.io.getStdErr(), args[0], 1);638 var stdout_writer = fs.stdout().writerStreaming(&stdout_buffer);
639 }639 const stdout = &stdout_writer.interface;
640
641 if (args.len <= 1) printUsageAndExit(args[0]);
642
640 if (std.mem.eql(u8, args[1], "--help")) {643 if (std.mem.eql(u8, args[1], "--help")) {
641 usageAndExit(std.io.getStdOut(), args[0], 0);644 printUsage(stdout, args[0]) catch std.process.exit(2);
642 }645 stdout.flush() catch std.process.exit(2);
643 if (args.len < 3) {646 std.process.exit(0);
644 usageAndExit(std.io.getStdErr(), args[0], 1);
645 }647 }
646648
649 if (args.len < 3) printUsageAndExit(args[0]);
650
647 const llvm_tblgen_exe = args[1];651 const llvm_tblgen_exe = args[1];
648 if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) {652 if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) printUsageAndExit(args[0]);
649 usageAndExit(std.io.getStdErr(), args[0], 1);
650 }
651653
652 const llvm_src_root = args[2];654 const llvm_src_root = args[2];
653 if (std.mem.startsWith(u8, llvm_src_root, "-")) {655 if (std.mem.startsWith(u8, llvm_src_root, "-")) printUsageAndExit(args[0]);
654 usageAndExit(std.io.getStdErr(), args[0], 1);
655 }
656656
657 var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator);657 var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator);
658658
...@@ -719,8 +719,6 @@ pub fn main() anyerror!void {...@@ -719,8 +719,6 @@ pub fn main() anyerror!void {
719 // "W" and "Wl,". So we sort this list in order of descending priority.719 // "W" and "Wl,". So we sort this list in order of descending priority.
720 std.mem.sort(*json.ObjectMap, all_objects.items, {}, objectLessThan);720 std.mem.sort(*json.ObjectMap, all_objects.items, {}, objectLessThan);
721721
722 var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer());
723 const stdout = buffered_stdout.writer();
724 try stdout.writeAll(722 try stdout.writeAll(
725 \\// This file is generated by tools/update_clang_options.zig.723 \\// This file is generated by tools/update_clang_options.zig.
726 \\// zig fmt: off724 \\// zig fmt: off
...@@ -815,7 +813,7 @@ pub fn main() anyerror!void {...@@ -815,7 +813,7 @@ pub fn main() anyerror!void {
815 \\813 \\
816 );814 );
817815
818 try buffered_stdout.flush();816 try stdout.flush();
819}817}
820818
821// TODO we should be able to import clang_options.zig but currently this is problematic because it will819// TODO we should be able to import clang_options.zig but currently this is problematic because it will
...@@ -966,13 +964,17 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool {...@@ -966,13 +964,17 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool {
966 return std.mem.lessThan(u8, a_key, b_key);964 return std.mem.lessThan(u8, a_key, b_key);
967}965}
968966
969fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {967fn printUsageAndExit(arg0: []const u8) noreturn {
970 file.writer().print(968 printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2);
969 std.process.exit(1);
970}
971
972fn printUsage(w: *std.io.Writer, arg0: []const u8) std.io.Writer.Error!void {
973 try w.print(
971 \\Usage: {s} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project974 \\Usage: {s} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
972 \\Alternative Usage: zig run /path/to/git/zig/tools/update_clang_options.zig -- /path/to/llvm-tblgen /path/to/git/llvm/llvm-project975 \\Alternative Usage: zig run /path/to/git/zig/tools/update_clang_options.zig -- /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
973 \\976 \\
974 \\Prints to stdout Zig code which you can use to replace the file src/clang_options_data.zig.977 \\Prints to stdout Zig code which you can use to replace the file src/clang_options_data.zig.
975 \\978 \\
976 , .{arg0}) catch std.process.exit(1);979 , .{arg0});
977 std.process.exit(code);
978}980}
tools/update_cpu_features.zig+2-2
...@@ -2082,8 +2082,8 @@ fn processOneTarget(job: Job) void {...@@ -2082,8 +2082,8 @@ fn processOneTarget(job: Job) void {
2082}2082}
20832083
2084fn usageAndExit(arg0: []const u8, code: u8) noreturn {2084fn usageAndExit(arg0: []const u8, code: u8) noreturn {
2085 const stderr = std.io.getStdErr();2085 const stderr = std.debug.lockStderrWriter(&.{});
2086 stderr.writer().print(2086 stderr.print(
2087 \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter]2087 \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter]
2088 \\2088 \\
2089 \\Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td .2089 \\Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td .
tools/update_crc_catalog.zig+10-10
...@@ -11,14 +11,10 @@ pub fn main() anyerror!void {...@@ -11,14 +11,10 @@ pub fn main() anyerror!void {
11 const arena = arena_state.allocator();11 const arena = arena_state.allocator();
1212
13 const args = try std.process.argsAlloc(arena);13 const args = try std.process.argsAlloc(arena);
14 if (args.len <= 1) {14 if (args.len <= 1) printUsageAndExit(args[0]);
15 usageAndExit(std.io.getStdErr(), args[0], 1);
16 }
1715
18 const zig_src_root = args[1];16 const zig_src_root = args[1];
19 if (mem.startsWith(u8, zig_src_root, "-")) {17 if (mem.startsWith(u8, zig_src_root, "-")) printUsageAndExit(args[0]);
20 usageAndExit(std.io.getStdErr(), args[0], 1);
21 }
2218
23 var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{});19 var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{});
24 defer zig_src_dir.close();20 defer zig_src_dir.close();
...@@ -193,10 +189,14 @@ pub fn main() anyerror!void {...@@ -193,10 +189,14 @@ pub fn main() anyerror!void {
193 }189 }
194}190}
195191
196fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {192fn printUsageAndExit(arg0: []const u8) noreturn {
197 file.writer().print(193 printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2);
194 std.process.exit(1);
195}
196
197fn printUsage(w: *std.io.Writer, arg0: []const u8) std.io.Writer.Error!void {
198 return w.print(
198 \\Usage: {s} /path/git/zig199 \\Usage: {s} /path/git/zig
199 \\200 \\
200 , .{arg0}) catch std.process.exit(1);201 , .{arg0});
201 std.process.exit(code);
202}202}